Meh*_*dad 3 c++ performance code-generation visual-c++
下面的代码(从我的大代码中减去,在我惊讶于它的速度如何与之相比之后std::vector)有两个特殊的特征:
当我对源代码进行非常小的修改时,它运行速度提高了三倍以上(总是用Visual C++ 2010 编译它)./O2
注意:为了使这更有趣,我在最后给出了修改的提示,这样你就可以花一些时间自己搞清楚这个改变.原始代码大约是500行,所以我花了很长时间才把它固定下来,因为修复看起来与性能无关.
它运行约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)
Run Code Online (Sandbox Code Playgroud)循环使用 /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)
Run Code Online (Sandbox Code Playgroud)环与所述修改(100〜MS !!):
00403361 mov dword ptr [esi+eax*4],eax
00403364 inc eax
00403365 cmp eax,4000000h
0040336A jl main+21h (403361h)
Run Code Online (Sandbox Code Playgroud)现在我的问题是,为什么上述变化会产生影响呢?这完全是奇怪的!
特别是第一个 - 它根本不应该影响任何东西(一旦你看到代码中的差异),但它会大大降低速度.
对此有解释吗?
#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);
}
Run Code Online (Sandbox Code Playgroud)
它与分配器有关.
更改
Allocator &a_到Allocator a_.
对于它的价值,我猜测/MT和之间的差异/MTd是/MTd堆分配将绘制堆内存以进行调试,使其更有可能被分页 - 这是在你开始计时之前发生的.
如果你'预热'矢量分配,你得到相同的数字/MT和/MTd:
vector<int> vect(COUNT);
// make sure vect's memory is warmed up
for (int i = 0; i < COUNT; i++) { vect.push_back(i); }
vect.n = 0; // clear the vector
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);
Run Code Online (Sandbox Code Playgroud)