38

我正在阅读 K&R 并来到关于寄存器变量的小部分,并且想知道这里的人们是否有一些很好的实践示例。

从 K&R 的第 4.7 节:

寄存器声明看起来像
register int x;
注册字符 c;

需要明确的是,我只是希望看到一些很酷的代码示例。我(很确定我)理解主题,所以不需要输入详细的解释(除非你愿意)。

4

6 回答 6

83

使用现代编译器时没有很好的寄存器使用示例(阅读:过去 15 年以上,请注意这个答案来自 2008 年),因为它几乎从来没有任何好处,而且可能会做一些坏事。当您使用 register 时,您是在告诉编译器“我知道如何比您更好地优化我的代码”,而这几乎从来没有发生过。使用 register 时可能会发生以下三种情况之一:

  • 编译器会忽略它,这很可能。在这种情况下,唯一的危害是您不能在代码中获取变量的地址。
  • 编译器尊重您的请求,因此代码运行速度较慢。
  • 编译器尊重您的请求,代码运行得更快,这是最不可能的情况。

即使一个编译器在您使用寄存器时生成了更好的代码,也没有理由相信另一个编译器会这样做。如果你有一些关键代码编译器优化得不够好,你最好的选择可能是对那部分使用汇编程序,但当然首先要进行适当的分析以验证生成的代码确实是一个问题。

于 2008-11-24T18:43:50.800 回答
14

总的来说,我同意罗伯特的观点,但作为任何好的规则,这个规则也有例外。
如果您在深度嵌入式系统上工作,您可能比编译器更了解如何在您的特定硬件架构上为您的特定应用程序优化代码。

但在 99% 的情况下,罗伯茨的解释也适用于嵌入词。

于 2008-11-24T18:57:53.033 回答
4

我知道这是很久以前的事了,但这里有一个来自 heapsort 的子过程的实现,其中使用寄存器变量使算法更快,至少使用 gcc 4.5.2 来编译代码

inline  void max_heapify(int *H, int i){
    char OK = FALSE;
    register int l, r, max, hI;
    while(!OK){
        OK = TRUE;
        l = left(i);
        r = right(i);
        max = i;
        if(l <= H[SIZE] && H[l] > H[i]){
            max = l;
        }
        if(r <= H[SIZE] && H[r] > H[max]){
            max = r;
        }
        if(max != i){
            OK = FALSE;
            hI = H[i];
            H[i] = H[max];
            H[max] = hI;
            i = max;
        }
    }
}

我在属性之前测试了使用和不使用 register 关键字的算法,并执行它以在我的笔记本上对一个包含 50,000,000 个元素的随机数组进行排序,每个版本几次。

寄存器的使用将堆排序时间从 ~135s 降低到 ~125s。

我也只测试了 5,000,000 个元素,但执行的次数更多。

没有寄存器的版本从 11s 开始,但每次执行都会降低时间,直到达到 9,65s 并停止

带有寄存器的版本从 10s 开始,并将时间降低到 8,80s。

我认为这与缓存内存有关。尽管如此,寄存器似乎通过恒定因素使算法更快

由于这些变量在算法中被大量使用,通过确保它们在寄存器上而不是将这项工作留给编译器,在这种情况下会产生更好的结果。然而,它并没有改善那么多时间。

希望thhill对某人有所帮助,问候。

于 2013-06-15T00:19:50.160 回答
3

另一个常见的情况是在实现低级解释器时。在寄存器中保存一些状态,例如。虚拟机堆栈指针,可以显着减少内存访问并加快您的代码速度。

有关优化的示例,请参见vmgen — 高效虚拟机解释器的生成器(5.2 堆栈顶部缓存)。

于 2008-12-13T22:03:20.203 回答
1

首先,寄存器变量应该用于频繁使用的变量,例如循环控制变量,以通过最小化访问时间来提高性能。在这种情况下,您只能使用并且只能注册存储说明符,例如 fun (auto int a,auto int b) :error fun (register int a,register int b) :right only this will be run fun (static int a, static int b) :error fun (extern int a,extern int b) :error

于 2013-01-05T12:26:55.480 回答
0

嗯,这是一个需要多个答案的问题,因为有多个编码上下文:从高级语言的角度来看,中级和低级(下到汇编),因为 C 语言可以调用汇编例程。

使用汇编而不是 C 的原因是因为在开发过程中遇到的性能问题,所以是的,需要 register 关键字,但在许多情况下它不能按开发人员的预期工作

于 2018-10-21T11:58:33.443 回答