你有两个数组和一个计算它们之间差异的函数:
for( i = 0; i < len; ++i ) {
int value1 = vector1[i];
int value2 = vector2[i];
if( value1 != value2 ) ++num_differences;
}
由于分支降低了性能,它可以优化为:
for( i = 0; i < len; ++i ) {
num_differences += !!(vector1[i] != vector2[i])
}
// !!(..) is to be sure that the result is boolean 0 or 1
所以没有if
条款。但它几乎有意义吗?由于GCC(和其他编译器)非常聪明,使用这种优化是否有意义?
答案 0 :(得分:4)
简短的回答是:“相信你的编译器”。
一般来说,除非你正在使用非常庞大的数据集,否则你不会从这样的优化中看到太多的好处。即使这样,你真的需要对代码进行基准测试,看看是否有任何改进。
答案 1 :(得分:2)
除非len
数百万大,或者你在比较很多数组,否则没有。第二个版本的可读性较差(对于有经验的程序员来说不是那么多),所以我更喜欢第一个版本,除非这是瓶颈(可疑)。
生成以下代码,并进行优化:
for( i = 0; i < 4; ++i ) {
int value1 = vector1[i];
int value2 = vector2[i];
if( value1 != value2 ) ++num_differences;
00401000 mov ecx,dword ptr [vector1 (40301Ch)]
00401006 xor eax,eax
00401008 cmp ecx,dword ptr [vector2 (40302Ch)]
0040100E je wmain+15h (401015h)
00401010 mov eax,1
00401015 mov edx,dword ptr [vector1+4 (403020h)]
0040101B cmp edx,dword ptr [vector2+4 (403030h)]
00401021 je wmain+26h (401026h)
00401023 add eax,1
00401026 mov ecx,dword ptr [vector1+8 (403024h)]
0040102C cmp ecx,dword ptr [vector2+8 (403034h)]
00401032 je wmain+37h (401037h)
00401034 add eax,1
00401037 mov edx,dword ptr [vector1+0Ch (403028h)]
0040103D cmp edx,dword ptr [vector2+0Ch (403038h)]
00401043 je wmain+48h (401048h)
00401045 add eax,1
}
for( i = 0; i < 4; ++i ) {
num_differences += !!(vector1[i] != vector2[i]);
00401064 mov edx,dword ptr [vector1+0Ch (403028h)]
0040106A xor eax,eax
0040106C cmp edx,dword ptr [vector2+0Ch (403038h)]
00401072 mov edx,dword ptr [vector1+8 (403024h)]
00401078 setne al
0040107B xor ecx,ecx
0040107D cmp edx,dword ptr [vector2+8 (403034h)]
00401083 mov edx,dword ptr [vector1+4 (403020h)]
00401089 setne cl
0040108C add eax,ecx
0040108E xor ecx,ecx
00401090 cmp edx,dword ptr [vector2+4 (403030h)]
00401096 mov edx,dword ptr [vector1 (40301Ch)]
0040109C setne cl
0040109F add eax,ecx
004010A1 xor ecx,ecx
004010A3 cmp edx,dword ptr [vector2 (40302Ch)]
004010A9 setne cl
004010AC add eax,ecx
}
所以,实际上,第二个版本稍慢(理论上)。第二项为19项指令,第一项为17项。
答案 2 :(得分:1)
您应该比较编译器生成的代码。它可能是等价的。
编译器非常聪明,但优秀的工程师当然可以提高程序的性能。
答案 3 :(得分:1)
我不认为你会做得更好,你的第二个例子很难读懂/理解普通程序员,这意味着两个难以理解和维护的事情,两个你可能会陷入黑暗,更少测试/支持,编译器的角落。沿着线路之间的道路行驶,不要在肩膀上或在错误的车道上徘徊。
使用此
for( i = 0; i < len; ++i ) {
int value1 = vector1[i];
int value2 = vector2[i];
if( value1 != value2 ) ++num_differences;
}
或者
for( i = 0; i < len; ++i ) {
if( vector1[i] != vector2[i] ) ++num_differences;
}
如果它确实困扰着你并且你已经正确地断定了这是你的性能瓶颈,那么就把它们之间的时间区分开来吧。从所示的拆卸和该平台的性质来看,很难恰当地计算这些东西并得出正确的结论。太多的缓存,以及其他因素导致错误的结果,导致错误的结论等等,并且没有两个x86实现具有相同的性能,所以如果你碰巧为你的计算机进行调整,你可能会因为x86的其他模型而失去它在具有不同I / O特性的不同主板上制作相同的产品。