【问题标题】:Registers in C#C#中的寄存器
【发布时间】:2014-08-03 21:59:31
【问题描述】:

我们都知道堆栈和堆的概念,但我最近读到了第三种保存数据的方法:寄存器。

我很难找到关于这种类型的好文章,我找到的是:http://www.dotnetperls.com/method-parameter,还有很多 C 的东西,例如:http://igoro.com/archive/volatile-keyword-in-c-memory-model-explained/

目前我掌握的唯一真实信息:每个 CPU 都有自己的寄存器,可用于保存数据,以尽可能快的方式访问数据,例如在 for 循环中。

据我所知,这种注册是由 CLR 完成的。然后我想起了这个 volatile-keyword,如果我们看一下 MSDN:

volatile 关键字表示一个字段可能被 同时执行的多个线程。是的字段 声明的 volatile 不受编译器优化的影响 假设由单个线程访问。这确保了最 字段中始终存在最新值。

Volatile 就是这样吗?它告诉CLR不要使用CPU寄存器,而是使用堆栈/堆,所有CPU/线程都可以访问?

很抱歉我的问题令人困惑,但是关于这个主题的信息真的很少。

【问题讨论】:

  • 人们过于关注堆和堆栈(有时,就像这里一样,寄存器)。在 99.99% 的情况下,您不太可能需要知道您正在使用的对象的实际存储位置。
  • 当你在做某事时,可以把寄存器想象成你大脑的记忆,把堆栈想象成你桌子上需要处理的一堆文件。那么你桌上的那套书籍,你当前正在使用的信息可能被称为缓存,而你的图书馆相当于 DRAM。

标签: c# clr cpu-registers memory-model


【解决方案1】:

这句话具有误导性,因为它不是对 volatile 保证的精确定义。在编译器优化方面没有指定易失性。此外,在 ARM 上限制编译器是不够的。 CPU 也必须受到限制。我建议你研究一下 volatile 保证的具体内容。

volatile 阻止寄存器的使用甚至是不正确的。易失性加载保证易失性变量的读取频率与程序读取的频率完全相同,并且顺序相同。

当你写作时:

volatile int sharedVar = 0;

Console.WriteLine(sharedVar);
Console.WriteLine(sharedVar);

JIT 必须准确读取两次。但它仍然可以使用寄存器来存储读取的值。

如果 CLR 可以证明 sharedVar 从未被写入并且始终具有值 0,它甚至可以删除读取。它可能必须在某些地方插入内存屏障而不是读取,因为volatile 访问具有一定的顺序保证。但是根本不需要物理上的负载。 (当前的 JIT 没有做这个优化。)

寄存器是一个实现细节。 CLR 在物理实现方面没有具体说明。我了解您想了解实施细节,这很好。不过,它们对于 CLR 向程序员保证的内容并不重要。

【讨论】:

    【解决方案2】:

    “每个 CPU 都有自己的寄存器”

    每个 CPU 都有一组寄存器,用于大多数涉及任何数据的操作。通常一条指令将一些数据从内存加载到寄存器中,然后另一条指令对寄存器中的数据进行一些计算。

    CPU 有一些用于数据的寄存器,一些用于指针的寄存器,以及一些跟踪程序执行的特殊寄存器,如指令指针、堆栈指针和标志寄存器。

    由于 CPU 有多个寄存器,JIT 编译器有时可以使用其中的一些作为局部变量的存储。寄存器不是在堆栈上分配变量,而是专用于保存变量的值。

    volatile 关键字不会影响寄存器用于存储的方式。如果一个变量可以被不同的线程访问,那么它就不是存储在寄存器中的候选变量。实际上,它只是存储在寄存器中的范围有限且寿命短的局部变量。

    【讨论】:

    • 您确定要注册吗? stackoverflow.com/questions/72275/…,见 Erics 评论:“C#,“volatile”不仅意味着“确保编译器和抖动不会对该变量执行任何代码重新排序或注册缓存优化”
    • @MatthiasMüller:这适用于缓存寄存器中的值,而不是将值存储在寄存器中。缓存值是存储在堆栈/堆中的值,也临时保存在寄存器中。
    • volatile 几乎可以保证 JIT 不会使用寄存器来保存变量,因为不能保证不同的线程将在同一个内核上运行。因此,将变量声明为 volatile 将告诉编译器和 JIT 避免将寄存器用于可能修改变量值的任何内容。在大多数架构中,寄存器的使用几乎是不可避免的,但更改将写入内存以满足volatile 约束。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-23
    • 2012-06-15
    • 1970-01-01
    • 1970-01-01
    • 2010-12-22
    • 1970-01-01
    相关资源
    最近更新 更多