下面的代码(从我的较大代码中减少,在我对它的速度与 的速度相比感到惊讶之后std::vector
)有两个独特的特征:
当我对源代码进行非常小的修改(总是使用 Visual C++ 2010 编译它)时,它的运行速度提高了三倍以上。
/O2
注意:为了让这个更有趣,我在最后给出了修改的提示,所以你可以花一些时间自己弄清楚改变。原始代码大约 500 行,所以我花了很长时间才确定它,因为修复看起来与性能无关。
即使输出循环看起来相同,它的运行速度也比 with快20 % !
/MTd
/MT
微小修改案例的汇编代码的区别是:
未经修改的循环(~300 ms):
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 ms!!):
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_
。