我碰巧写了一个if-else语句,条件在大多数时候都是假的(检查是否分配了静态指针)。编译器优化哪一个会更好?或者他们是平等的?该函数将被调用很多次,因此优化其性能至关重要。
void foo() {
static int * p = NULL;
if (p == NULL) {
p = (int *) malloc( SIZE * sizeof(int));
}
//do something here
}
void foo() {
static int * p = NULL;
if (p != NULL) {
//do something here
} else {
p = (int *) malloc( SIZE * sizeof(int));
//do something
}
}
答案 0 :(得分:5)
某些编译器可以允许开发人员指定哪种情况更有可能或不太可能发生。 这在Linux内核中大量使用。
在gcc中,有可能的(x)或不太可能的(x)宏。 例如:
if (unlikely(p == NULL)) {
p = malloc(10);
}
答案 1 :(得分:2)
如果经常调用该函数以便不从分支预测器中逐出,则预测器将为您处理所有事情,因为它将非常快速地学习哪个是“可能”分支。
某些编译器允许您使用预测提示来装饰条件。检查供应商的文档,如果可以,请添加提示。
特定平台记录了默认的预测变量行为(例如,参见x86的英特尔优化手册),但最好由编译器通过上述提示实现。事实上,你真的没有选择,因为你无论如何都不能控制你的编译器代码生成,所以留给你的唯一最后一个措施是自己编写机器代码中的代码并实现平台对默认预测的建议
答案 2 :(得分:1)
最后,它取决于编译器和它的优化,它从编译器版本,处理器,编译器系列改变......
我对这类主题的经验法则是通过进行一些广泛的分析来检查您的实际平台。我通常也会首先正确遵循规则"代码,只在需要时才进行优化"。尝试预先优化通常会导致代码和设计的可读性降低(有时甚至没有更好的性能)。
答案 3 :(得分:0)
从左到右按顺序检查条件,这是在C标准中,因此允许像
这样的条件if( ptr != NULL && ptr->member == value )
这也意味着首先放置最可能是错误的条件是有意义的。
答案 4 :(得分:0)
如果你在寻找性能,我根本就不会使用malloc。获取大量的RAM并直接使用它而无需分配释放包装器。另外考虑使用宏代码会更大但性能也会提高。
#define ASSURE_PTR(a) if (!a){ \
a = (int *) malloc (SIZE * sizeof(int)); \
}
答案 5 :(得分:0)
如果经常调用函数,任何体面的分支预测器都会学会很快地预测公共路径。 请注意,代码的编译方式可能与您预期的不同,因为某些编译器依赖static branch prediction,并且可能会识别此模式。