TL;DR VS2013 のオプティマイザが混乱しているか、測定値が間違っているか、またはテストを有効にするために実際にグローバル ダミーを揮発性にする必要があるか、または ____ ですか?
免責事項:これは主に「学術的」な関心から外れています。私が見た違いが実際に製品コードに影響を与えるとは思いません。
はじめに: VS2013とVS2013の間で大きな違いが見られたため、私の最近の測定結果からこの質問にたどり着きました。(そこのコメントも参照してください)std::vector<std::unique_ptr<T> >
boost::ptr_vector
私の特定のテスト ケースでは、boost::ptr_vector 内の要素へのアクセスは、unique_ptr のベクトルを使用するよりも 50% 高速になる可能性があります。
私のテストコードはここにあります: http://coliru.stacked-crooked.com/a/27dc2f1b91380cca (この質問には含めません。以下にスニペットを含めます)
gcc 4.8 は違いを報告しないため、これは VS2013 のものです。
Start... The timings are as follows for accessing all (1000000) elements 200 times: * St6vectorISt10unique_ptrIjSt14default_deleteIjEESaIS3_EE: 1764 ms * N5boost10ptr_vectorIjNS_20heap_clone_allocatorESaIPvEEE: 1781 ms Dummy output: 500000
リンクされているテストコードの正確なタイミングは次のとおりです。
Start... The timings are as follows for accessing all (1.000.000) elements 200 times: * class std::vector<....>: 344 ms * class boost::ptr_vector<unsigned int,....>: 216 ms Dummy output: 500.000
テストループは次のようになります。また、私が見たものを説明する長いコメントをそこに残しておきます。
template<typename C>
void RunContainerAccess(C& c) {
for (size_t i = 0; i != loop_count; ++i) {
for (auto& e : c) {
// This is relevant:
// If the if-condition is present, VC++2013 will show
// approx. the same runtime for both cases. However,
// if the only line in this loop is assigning the element
// to the pGlobalDummy, *then* ptr_vector will run approx. 50%
// faster than the unique_vector version!
//
// g++-4.8 does not show this behaviour
//
// Note: VS2013 commmand line: (release; /O2; no whole prg opt)
// /GS /analyze- /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /sdl /Fd"Release\vc120.pdb" /fp:precise /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_LIB" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oy- /Oi /MD /Fa"Release\" /EHsc /nologo /Fo"Release\" /Fp"Release\simple.pch"
//
// Note: http://coliru.stacked-crooked.com/ command line:
// g++-4.8 -std=c++11 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
// if (pGlobalDummy)
pGlobalDummy = PtrShim(e);
}
}
}
ループ内の唯一の行が要素にアクセスしている (ptr をグローバル ダミーに入れている) 場合、VS2013 オプティマイザーが奇妙なことをしているように見えます。が存在する場合if (pGlobalDummy)
、どちらの場合も同じです。
誰でもこれについていくつかの光を共有できますか?
ハワードの回答のおかげでvolatile
、グローバルダミーに追加すると違いが生じることがわかりました。つまり、グローバルダミーが次のように揮発性である場合:
extern MyType* volatile pGlobalDummy;
MyType* volatile pGlobalDummy = nullptr;
ループの実行は少し遅くなりますが、まったく同じように実行されます。ここで揮発性が違いを生むべきですか?つまり、揮発性がなくてもテストは有効ですか?