C#中的寄存器

Mat*_*ler 6 c# clr memory-model cpu-registers

我们都知道堆栈和堆的想法,但我最近读到了第三个保存数据的选项:寄存器.

我很难找到关于这种类型的好文章,我发现的是:http://www.dotnetperls.com/method-parameter,以及C的很多内容,例如:http://igoro.com/存档/易失性-关键字在-C-存储器模型解释的/

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

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

volatile关键字表示某个字段可能被同时执行的多个线程修改.声明为volatile的字段不受编译器优化的约束,这些优化假定由单个线程进行访问.这可确保始终在字段中显示最新值.

那么Volatile也是如此吗?它告诉CLR不要使用CPU寄存器而是堆栈/堆,它可以被所有CPU /线程访问?

我很抱歉这个令人困惑的问题,但关于这个话题的信息确实很少.

Guf*_*ffa 6

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

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

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

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

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


usr*_*usr 5

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

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

当你写:

volatile int sharedVar = 0;

Console.WriteLine(sharedVar);
Console.WriteLine(sharedVar);
Run Code Online (Sandbox Code Playgroud)

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

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

寄存器是一个实现细节。CLR 没有在物理实现方面指定。我知道您想了解实施细节,这很好。不过,它们与 CLR 向程序员保证的内容无关。