假设我在一个大数据集上迭代,根据用户提供的变量,我会进行区分大小写或不区分大小写的排序。我认为,因为这个用户提供的值永远不会改变,所以最好将其放入寄存器,例如:
int main(int argc, char * argv[])
{
clock_t t0, t1;
int sort = 1;
t0 = clock();
register int case_insensitive_sort = sort;
int z = 0;
for (int i=0; i < 1e8; i++) {
if (case_insensitive_sort) {
z += 3; // for debugging to see where it's going
} else {
z -= 5;
}
};
t1 = clock();
printf("The function took %fs to complete.n", ((double)(t1-t0))/CLOCKS_PER_SEC);
t0 = clock();
int case_insensitive_sort2 = sort;
z = 0;
for (int i=0; i < 1e8; i++) {
if (case_insensitive_sort2) {
z += 3; // for debugging to see where it's going
} else {
z -= 5;
}
};
t1 = clock();
printf("The function took %fs to complete.n", ((double)(t1-t0))/CLOCKS_PER_SEC);
return 0;
}
下面是编译器输出的一个示例——https://godbolt.org/z/7KrGzr.似乎有了register
前缀,寄存器中会有一个比较,看看它是否为0:
testl %ebx, %ebx
如果没有它,它可以与内存地址进行比较:
cmpl $0, -12(%rbp)
然而,当我在本地运行时,没有register
的版本要快得多:
函数需要0.255494秒才能完成。
函数耗时0.188364秒完成。
为什么会这样?我认为使用寄存器而不是进行内存比较会更快。
更新:感谢您在这方面提供的所有帮助。从Peter的建议和相关答案来看,最大的改进不是从register
到case_insensitive_sort
,而是在循环vars:上进行
register int case_insensitive_sort = sort;
register int z = 0;
for (register int i=0; i < 1e8; i++) { ...
从中我得到了以下两者之间的改进:
函数需要0.255494s才能完成寄存器(之前(
该函数用了0.038112s才完成寄存器(之后(
在没有寄存器的情况下,该函数需要0.252963秒才能完成。
- 在不启用编译器优化的情况下进行任何微观优化都毫无意义
- 对编译器进行优化时忽略register关键字
- 你的测试没有测试任何东西
启用编译器优化时,生成的代码完全相同。https://godbolt.org/z/Tfjn9x