下面的代码(从我的大量代码中精简而来,当我惊讶于其速度与std::vector相比之后)具有两个奇特的特点:
- 当我对源代码进行非常微小的修改时(始终使用Visual C++ 2010的/O2编译),它比原代码运行速度快三倍以上。 - 使用/MTd比使用/MT快约20%,尽管输出循环看起来相同!
微小修改的汇编代码差异如下:
- 当我对源代码进行非常微小的修改时(始终使用Visual C++ 2010的/O2编译),它比原代码运行速度快三倍以上。 - 使用/MTd比使用/MT快约20%,尽管输出循环看起来相同!
微小修改的汇编代码差异如下:
Loop without the modification (~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)
Loop with
/MTd
(looks identical! but ~270 ms):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)
Loop with the modification (~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_
。
std::swap(n_, n);
这一行,则始终会得到快速循环。另外请注意,在vector
构造函数中,您有两个名为n
的变量:成员和参数!这相当令人困惑。 - rodrigo