KBe*_*y57 9 c++ performance stl c++14 gcc6
我正在分析一小段代码,这是一个更大的模拟的一部分,令我惊讶的是,STL函数等于(std :: equal)比一个简单的for循环慢得多,比较两个数组元素.我写了一个小测试用例,我认为这是两者之间的公平比较,而差异,使用Debian档案中的g ++ 6.1.1并不是无关紧要的.我正在比较有符号整数的两个四元素数组.我测试了std :: equal,operator ==和一个小的for循环.我没有使用std :: chrono来获得精确的时间,但是可以通过时间明确地看出差异./a.out.
我的问题是,给定下面的示例代码,为什么operator ==和重载函数std :: equal(调用operator ==我相信)需要大约40秒来完成,而手写循环只需要8s?我正在使用最新的基于英特尔的笔记本电脑.for循环在所有优化级别上都更快,-O1,-O2,-O3和-Ofast.我编译了代码
g++ -std=c++14 -Ofast -march=native -mtune=native
循环运行了很多次,只是为了使肉眼看清楚.模运算符表示对其中一个数组元素的廉价操作,并用于防止编译器优化循环.
#include<iostream>
#include<algorithm>
#include<array>
using namespace std;
using T = array<int32_t, 4>;
bool
are_equal_manual(const T& L, const T& R)
noexcept {
bool test{ true };
for(uint32_t i{0}; i < 4; ++i) { test = test && (L[i] == R[i]); }
return test;
}
bool
are_equal_alg(const T& L, const T& R)
noexcept {
bool test{ equal(cbegin(L),cend(L),cbegin(R)) };
return test;
}
int main(int argc, char** argv) {
T left{ {0,1,2,3} };
T right{ {0,1,2,3} };
cout << boolalpha << are_equal_manual(left,right) << endl;
cout << boolalpha << are_equal_alg(left,right) << endl;
cout << boolalpha << (left == right) << endl;
bool t{};
const size_t N{ 5000000000 };
for(size_t i{}; i < N; ++i) {
//t = left == right; // SLOW
//t = are_equal_manual(left,right); // FAST
t = are_equal_alg(left,right); // SLOW
left[0] = i % 10;
right[2] = i % 8;
}
cout<< boolalpha << t << endl;
return(EXIT_SUCCESS);
}
Run Code Online (Sandbox Code Playgroud)
这是使用该函数时生成的for循环汇编:main()are_equal_manual(left,right)
.L21:
xor esi, esi
test eax, eax
jne .L20
cmp edx, 2
sete sil
.L20:
mov rax, rcx
movzx esi, sil
mul r8
shr rdx, 3
lea rax, [rdx+rdx*4]
mov edx, ecx
add rax, rax
sub edx, eax
mov eax, edx
mov edx, ecx
add rcx, 1
and edx, 7
cmp rcx, rdi
Run Code Online (Sandbox Code Playgroud)
这是are_equal_alg(left,right)使用该函数时生成的内容:
.L20:
lea rsi, [rsp+16]
mov edx, 16
mov rdi, rsp
call memcmp
mov ecx, eax
mov rax, rbx
mov rdi, rbx
mul r12
shr rdx, 3
lea rax, [rdx+rdx*4]
add rax, rax
sub rdi, rax
mov eax, ebx
add rbx, 1
and eax, 7
cmp rbx, rbp
mov DWORD PTR [rsp], edi
mov DWORD PTR [rsp+24], eax
jne .L20
Run Code Online (Sandbox Code Playgroud)
我不太确定第一种情况生成的代码中发生了什么,但它显然没有调用memcmp(). 它似乎根本没有比较数组的内容。虽然循环仍被迭代 5000000000 次,但它已优化为不执行任何操作。然而,使用的循环are_equal_alg(left,right)仍在执行比较。基本上,编译器仍然能够比std::equal模板更好地优化手动比较。
| 归档时间: |
|
| 查看次数: |
404 次 |
| 最近记录: |