【发布时间】:2021-02-14 14:22:32
【问题描述】:
假设我正在迭代一个大型数据集,并根据用户提供的变量进行区分大小写或不区分大小写的排序。我认为因为这个用户提供的值永远不会改变,所以将它放入寄存器是一个好主意,例如:
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 秒。
为什么会这样?我认为使用寄存器而不是进行内存比较会快得多。
更新:感谢您提供的所有帮助。从彼得的建议和链接的答案来看,最大的改进不是来自register-ing case_insensitive_sort,而是通过在循环变量上进行:
register int case_insensitive_sort = sort;
register int z = 0;
for (register int i=0; i < 1e8; i++) { ...
由此我得到以下两者之间的改进:
函数用了 0.255494 秒完成了寄存器(之前)。
该函数需要 0.038112 秒才能完成寄存器(之后)。
该函数在没有寄存器的情况下需要 0.252963 秒才能完成。
【问题讨论】:
-
评论不用于扩展讨论;这个对话是moved to chat。
标签: c performance assembly gcc x86