我必须做一个比较,我想知道哪个更快。
1)
for (i=0;i<4;i++){
if (object1(i)==object2(i))
retval = true;
else {
retval = false;
break;
}
}
2)
if ( (object1(0)==object2(0) && (object1(1)==object2(1) && (object1(2)==object2(2) && (object1(3)==object2(3)){
retval = true;
else
retval = false;
或两者都表现相同?
谢谢你的建议
答案 0 :(得分:2)
如果启用了优化标志,那么编译器可能会为这两个代码生成相同的机器指令,完全取消for
循环,因为编译器已知确切的迭代次数:
顺便说一句,如果你非常关心,那么你可以这样写:
bool retValue = (object1(0)==object2(0)) &&
(object1(1)==object2(1)) &&
(object1(2)==object2(2)) &&
(object1(3)==object2(3));
避免了:for
循环,以及if-else
分支,并且它不依赖于编译器优化。
答案 1 :(得分:2)
严格来说,最有效的途径是:
retval = object1(0) == object2(0) && object1(1) == object2(1).....
这基本上与你的循环相同,但不必将结果与true
进行比较以确定条件的结果。
但是,我强烈建议保持循环,因为它更容易适应添加或删除数字。
答案 2 :(得分:2)
你需要衡量。但无论如何,第一个代码可以简化一点:
for (i = 0; i < 4; ++i)
if (object1(i) != object2(i))
return false;
return true;
现在选择更易读的形式。我会在这里选择循环,除非您已确认此代码导致性能问题。
答案 3 :(得分:0)
与优化一样,单一规则是 MEASURE 。
此外,我想编译器可能会以某种方式优化此代码(我和我甚至无法想象)。因此,我建议用最简单的可读形式编写它。
答案 4 :(得分:0)
我喜欢使用Try out LLVM和Clang页面:
struct Object {
int operator()(int i) const;
};
bool loop(Object const& left, Object const& right) {
bool retval = false;
for (int i = 0; i < 4; i++) {
if (left(i) == right(i) )
retval = true;
else {
retval = false;
break;
}
}
return true;
}
bool inlineif(Object const& left, Object const& right) {
bool retval = true;
if ( left(0) == right(0) &&
left(1) == right(1) &&
left(2) == right(2) &&
left(3) == right(3))
retval = true;
else
retval = false;
return retval;
}
bool betterloop(Object const& left, Object const& right) {
for (int i = 0; i < 4; ++i)
if (left(i) != right(i))
return false;
return true;
}
bool betterif(Object const& left, Object const& right) {
return left(0) == right(0) &&
left(1) == right(1) &&
left(2) == right(2) &&
left(3) == right(3);
}
为循环生成以下IR(无论它们是如何编写的):
define zeroext i1 @_Z4loopRK6ObjectS1_(%struct.Object* %left, %struct.Object* %right) uwtable {
br label %1
; <label>:1 ; preds = %7, %0
%i.0 = phi i32 [ 0, %0 ], [ %8, %7 ]
%2 = icmp slt i32 %i.0, 4
br i1 %2, label %3, label %9
; <label>:3 ; preds = %1
%4 = tail call i32 @_ZNK6ObjectclEi(%struct.Object* %left, i32 %i.0)
%5 = tail call i32 @_ZNK6ObjectclEi(%struct.Object* %right, i32 %i.0)
%6 = icmp eq i32 %4, %5
br i1 %6, label %7, label %9
; <label>:7 ; preds = %3
%8 = add nsw i32 %i.0, 1
br label %1
; <label>:9 ; preds = %3, %1
ret i1 true
}
两个if的非常相似的IR(所以我只给一个):
define zeroext i1 @_Z8betterifRK6ObjectS1_(%struct.Object* %left, %struct.Object* %right) uwtable {
%1 = tail call i32 @_ZNK6ObjectclEi(%struct.Object* %left, i32 0)
%2 = tail call i32 @_ZNK6ObjectclEi(%struct.Object* %right, i32 0)
%3 = icmp eq i32 %1, %2
br i1 %3, label %4, label %16
; <label>:4 ; preds = %0
%5 = tail call i32 @_ZNK6ObjectclEi(%struct.Object* %left, i32 1)
%6 = tail call i32 @_ZNK6ObjectclEi(%struct.Object* %right, i32 1)
%7 = icmp eq i32 %5, %6
br i1 %7, label %8, label %16
; <label>:8 ; preds = %4
%9 = tail call i32 @_ZNK6ObjectclEi(%struct.Object* %left, i32 2)
%10 = tail call i32 @_ZNK6ObjectclEi(%struct.Object* %right, i32 2)
%11 = icmp eq i32 %9, %10
br i1 %11, label %12, label %16
; <label>:12 ; preds = %8
%13 = tail call i32 @_ZNK6ObjectclEi(%struct.Object* %left, i32 3)
%14 = tail call i32 @_ZNK6ObjectclEi(%struct.Object* %right, i32 3)
%15 = icmp eq i32 %13, %14
br label %16
; <label>:16 ; preds = %12, %8, %4, %0
%17 = phi i1 [ false, %8 ], [ false, %4 ], [ false, %0 ], [ %15, %12 ]
ret i1 %17
}
这里的重要说明是br
,它是分支指令。它可以用作简单的goto
或边缘条件:
br i1 %11, label %12, label %16
表示如果i1
为真,请转到label %12
,否则转到label %16
。
似乎“自然”LLVM不会展开传统的循环版本,因此if
版本在这里表现更好。实际上,我很惊讶它没有,我无法弄清楚为什么它不会......
所以,如果代码可能的内联速度要快一些,但是根据left(i) == right(i)
(甚至那时)的成本,内联也可能不明显,因为CPU非常擅长分支预测。