以下のコード(私の大きなコードから縮小されたもので、速度がそれと比較してどのように低下したかに驚いた後std::vector
)には、2つの特有の機能があります。
ソースコードにごくわずかな変更を加えると、3倍以上高速に実行されます(常にVisual C ++ 2010でコンパイルします)。
/O2
注:これをもう少し楽しくするために、最後に変更のヒントを示します。これにより、自分で変更を理解するために時間を費やすことができます。元のコードは約500行だったので、修正はパフォーマンスとはかなり無関係に見えるため、ピン留めするのにかなり長い時間がかかりました。
出力ループは同じように見えますが、を使用した場合よりも約20%高速に実行されます。
/MTd
/MT
tiny-modificationの場合のアセンブリコードの違いは次のとおりです。
変更せずにループする(〜300ミリ秒):
00403383 mov esi,dword ptr [esp+10h] 00403387 mov edx,dword ptr [esp+0Ch] 0040338B mov dword ptr [edx+esi*4],eax 0040338E add dword ptr [esp+10h],ecx 00403392 add eax,ecx 00403394 cmp eax,4000000h 00403399 jl main+43h (403383h)
ループし
/MTd
ます(同じように見えますが、約270ミリ秒):00407D73 mov esi,dword ptr [esp+10h] 00407D77 mov edx,dword ptr [esp+0Ch] 00407D7B mov dword ptr [edx+esi*4],eax 00407D7E add dword ptr [esp+10h],ecx 00407D82 add eax,ecx 00407D84 cmp eax,4000000h 00407D89 jl main+43h (407D73h)
変更を加えてループします(〜100ミリ秒!!):
00403361 mov dword ptr [esi+eax*4],eax 00403364 inc eax 00403365 cmp eax,4000000h 0040336A jl main+21h (403361h)
さて、私の質問は、なぜ上記の変更がそれらの効果をもたらすのかということです。それは完全に奇妙です!
特に最初のもの-それは(コードの違いを見ると)何にも影響を与えないはずですが、それでも速度を劇的に低下させます。
これについての説明はありますか?
#include <cstdio>
#include <ctime>
#include <algorithm>
#include <memory>
template<class T, class Allocator = std::allocator<T> >
struct vector : Allocator
{
T *p;
size_t n;
struct scoped
{
T *p_;
size_t n_;
Allocator &a_;
~scoped() { if (p_) { a_.deallocate(p_, n_); } }
scoped(Allocator &a, size_t n) : a_(a), n_(n), p_(a.allocate(n, 0)) { }
void swap(T *&p, size_t &n)
{
std::swap(p_, p);
std::swap(n_, n);
}
};
vector(size_t n) : n(0), p(0) { scoped(*this, n).swap(p, n); }
void push_back(T const &value) { p[n++] = value; }
};
int main()
{
int const COUNT = 1 << 26;
vector<int> vect(COUNT);
clock_t start = clock();
for (int i = 0; i < COUNT; i++) { vect.push_back(i); }
printf("time: %d\n", (clock() - start) * 1000 / CLOCKS_PER_SEC);
}
ヒント(下にマウスを置く):
それはアロケータと関係があります。
回答:
に変更
Allocator &a_
しAllocator a_
ます。