当前位置: 首页 > 知识库问答 >
问题:

为什么带寄存器操作数的TEST比带内存和立即数操作数的CMP运行得慢?[副本]

梁宪
2023-03-14

假设我在一个大型数据集上迭代,根据用户提供的变量,我要么区分大小写,要么不区分大小写。我认为,因为这个用户提供的值永远不会改变,所以将它放入一个寄存器是一个好主意,例如:

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.似乎与寄存器前缀在寄存器中进行了比较,以查看它是否为0:

testl   %ebx, %ebx

如果没有它,它与内存地址进行比较:

cmpl    $0, -12(%rbp)

然而,当我在本地运行它时,没有寄存器的版本要快得多:

该功能需要0.255494秒才能完成。

该功能需要0.188364秒才能完成。

为什么会这样?我认为使用寄存器而不是进行内存比较会快得多。

更新:感谢所有的帮助。根据Peter的建议和链接的答案,最大的改进不是来自< code > register -ing < code > case _ insensitive _ sort ,而是通过在循环变量上这样做:

register int case_insensitive_sort = sort;
register int z = 0;
for (register int i=0; i < 1e8; i++) { ...

由此,我得到了两者之间的改进:

使用寄存器(之前)完成该函数需要0.255494s。< br >该函数用0.038112秒完成寄存器(之后)。< br >在没有寄存器的情况下,该函数需要0.252963s才能完成。

共有1个答案

国跃
2023-03-14
    < li >在不启用编译器优化的情况下进行任何微优化都毫无意义。 < li >编译器上的With optimizations忽略register关键字 < li >您的测试不测试任何内容。

启用编译器优化时,生成的代码完全相同。https://godbolt.org/z/Tfjn9x

 类似资料:
  • 从逻辑上讲,写入任何CPU存储变量应该比相应的内存操作快,因为没有缓存未命中的机会。这些状态缓存在 CPU 中,并且在下一次虚拟机启动/虚拟机恢复操作之前不会更改任何 CPU 状态。因此,它们应该比对内存地址的等效操作更快 当查看AMD和英特尔提供的不同虚拟化解决方案时,就会出现这个问题。英特尔要求对VMCS数据结构的所有更改都应始终通过VMREAD/VMWRITE接口,而不是通过常规内存R/W操

  • Vim 可以将不同字段剪切或复制到不同寄存器中,您可以从不同寄存器中取出内容后粘贴 "寄存器名称 按下"键和另一个字符键,便可以定义一个寄存器。例如:"a "1 定义寄存器后直接进行操作 "ayy 将当前行复制到寄存器 a 中 "ap 将寄存器 a 中的内容粘贴到光标之后 :registers 查看所有寄存器的内容 通常情况下,寄存器 + (先按",再按 Shift+= )对应

  • 内存操作 函数 void *  rt_memset (void *s, int c, rt_ubase_t count)   设置内存数据   void *  rt_memcpy (void *dst, const void *src, rt_ubase_t count)   复制内存数据   void *  rt_memmove (void *dest, const void *src, rt_

  • 在最近的工作中,我遇到了一个问题,是关于一些操作数的数字提升。以下是演示代码: 在我看来,我以为Num1和Num2都会自动提升到两倍,然后计算结果为其中一个操作数是两倍,而结果震惊了我。我得到了一个负数。然后我看了JLS,它还说它应该做数字推广,见下文: "如果二进制运算符的操作数中至少有一个是浮点类型的,则该操作是浮点操作,即使另一个是整数。 如果数值运算符的操作数中至少有一个为double类型

  • 问题内容: 当我在Python 3.3.0中输入这些表达式时出现问题 好像需要大约浮点数(-3.33)?并在整数除法中四舍五入,但是在模运算中它做的事情完全不同。似乎它返回余数+/- 1并仅根据负操作数所在的位置切换符号。即使在查看本网站上的其他答案之后,我也完全感到困惑!我希望有人也能清楚地解释这一点!这本书说出了一些提示:回想一下这个神奇的公式a =(a // b)(b)+(a%b),但这似乎