Man*_*ero -1 c++ performance iterator c++11
我正在学习C++(和C++ 11)的性能.我需要在调试和发布模式下执行,因为我花时间进行调试和执行.
我对这两个测试感到惊讶,并且对不同的编译器标志优化有多大的改变.
测试迭代器1:
测试迭代器2:
PD:我使用以下时钟代码.
测试迭代器1:
void test_iterator_1()
{
int z = 0;
int nv = 1200000000;
std::vector<int> v(nv);
size_t count = v.size();
for (unsigned int i = 0; i < count; ++i) {
v[i] = 1;
}
}
Run Code Online (Sandbox Code Playgroud)
测试迭代器2:
void test_iterator_2()
{
int z = 0;
int nv = 1200000000;
std::vector<int> v(nv);
for (int& i : v) {
i = 1;
}
}
Run Code Online (Sandbox Code Playgroud)
更新:问题仍然是相同的,但对于-O3中的ranged-for,差异很小.所以对于循环1是最好的.
更新2:结果:
使用-O3:
t1: 80 units
t2: 74 units
Run Code Online (Sandbox Code Playgroud)
使用-O0:
t1: 287 units
t2: 538 units
Run Code Online (Sandbox Code Playgroud)
更新3:代码!.编译:g ++ -std = c ++ 11 test.cpp -O0(然后是-O3)
您的第一个测试实际上是将向量中每个元素的值设置为1.
您的第二个测试是将向量中每个元素的副本的值设置为1(原始向量是相同的).
当你进行优化时,第二个循环很可能被完全删除,因为它基本上什么都不做.
如果您希望第二个循环实际设置值:
for (int& i : v) // notice the &
{
i = 1;
}
Run Code Online (Sandbox Code Playgroud)
一旦进行了更改,您的循环可能会生成几乎完全相同的汇编代码.
作为旁注,如果您想将整个向量初始化为单个值,更好的方法是:
std::vector<int> v(SIZE, 1);
Run Code Online (Sandbox Code Playgroud)
编辑
组装相当长(100多行),所以我不会发布所有内容,但需要注意几点:
版本1将存储值count和增量i,每次都对其进行测试.版本2使用迭代器(基本相同std::for_each(b.begin(), v.end() ...)).因此,循环维护的代码是非常不同的(它是针对版本2的更多设置,但每次迭代的工作量更少).
版本1(只是循环的内容)
mov eax, DWORD PTR _i$2[ebp]
push eax
lea ecx, DWORD PTR _v$[ebp]
call ??A?$vector@HV?$allocator@H@std@@@std@@QAEAAHI@Z ; std::vector<int,std::allocator<int> >::operator[]
mov DWORD PTR [eax], 1
Run Code Online (Sandbox Code Playgroud)
版本2(只是循环的内容)
mov eax, DWORD PTR _i$2[ebp]
mov DWORD PTR [eax], 1
Run Code Online (Sandbox Code Playgroud)
当它们得到优化时,这一切都会发生变化(除了几条指令的排序),输出几乎相同.
版本1(优化)
push ebp
mov ebp, esp
sub esp, 12 ; 0000000cH
push ecx
lea ecx, DWORD PTR _v$[ebp]
mov DWORD PTR _v$[ebp], 0
mov DWORD PTR _v$[ebp+4], 0
mov DWORD PTR _v$[ebp+8], 0
call ?resize@?$vector@HV?$allocator@H@std@@@std@@QAEXI@Z ; std::vector<int,std::allocator<int> >::resize
mov ecx, DWORD PTR _v$[ebp+4]
mov edx, DWORD PTR _v$[ebp]
sub ecx, edx
sar ecx, 2 ; this is the only differing instruction
test ecx, ecx
je SHORT $LN3@test_itera
push edi
mov eax, 1
mov edi, edx
rep stosd
pop edi
$LN3@test_itera:
test edx, edx
je SHORT $LN21@test_itera
push edx
call DWORD PTR __imp_??3@YAXPAX@Z
add esp, 4
$LN21@test_itera:
mov esp, ebp
pop ebp
ret 0
Run Code Online (Sandbox Code Playgroud)
版本2(优化)
push ebp
mov ebp, esp
sub esp, 12 ; 0000000cH
push ecx
lea ecx, DWORD PTR _v$[ebp]
mov DWORD PTR _v$[ebp], 0
mov DWORD PTR _v$[ebp+4], 0
mov DWORD PTR _v$[ebp+8], 0
call ?resize@?$vector@HV?$allocator@H@std@@@std@@QAEXI@Z ; std::vector<int,std::allocator<int> >::resize
mov edx, DWORD PTR _v$[ebp]
mov ecx, DWORD PTR _v$[ebp+4]
mov eax, edx
cmp edx, ecx
je SHORT $LN1@test_itera
$LL33@test_itera:
mov DWORD PTR [eax], 1
add eax, 4
cmp eax, ecx
jne SHORT $LL33@test_itera
$LN1@test_itera:
test edx, edx
je SHORT $LN47@test_itera
push edx
call DWORD PTR __imp_??3@YAXPAX@Z
add esp, 4
$LN47@test_itera:
mov esp, ebp
pop ebp
ret 0
Run Code Online (Sandbox Code Playgroud)