YSK*_*YSK 5 optimization gcc memory-barriers barrier
我一直在阅读编译器优化与 CPU 优化以及volatile与内存障碍的对比。
我不清楚的一件事是,我目前的理解是 CPU 优化和编译器优化是正交的。即可以彼此独立地发生。
但是,被认为有害的物品volatile表明volatile不应使用。Linus 的帖子也提出了类似的主张。IIUC 的主要原因是,将变量标记为在访问该变量时volatile禁用所有编译器优化(即,即使它们无害),同时仍不提供防止内存重新排序的保护。从本质上讲,重点是不应该小心处理数据,而是需要小心处理特定的访问模式。
现在,volatile 被认为是有害的文章给出了以下示例,说明等待标志的繁忙循环:
while (my_variable != what_i_want) {}
Run Code Online (Sandbox Code Playgroud)
并指出编译器可以优化访问,my_variable以便它只发生一次而不是在循环中。文章声称的解决方案如下:
while (my_variable != what_i_want)
cpu_relax();
Run Code Online (Sandbox Code Playgroud)
据说它cpu_relax充当编译器屏障(文章的早期版本说它是内存屏障)。
我在这里有几个差距:
1) 是否暗示 gcc 具有cpu_relax调用的特殊知识,并且它转换为对编译器和CPU的提示?
2)对于其他指令(例如之类的)是否也是如此smb_mb()?
3)考虑到cpu_relax它本质上定义为 C 宏,它是如何工作的?如果我手动扩展,cpu_relaxgcc 是否仍将其视为编译器障碍?我如何知道 gcc 尊重哪些调用?
4)cpu_relax就gcc而言,范围是什么?换句话说,gcc 看到cpu_relax指令时无法优化的读取范围是多少?从 CPU 的角度来看,范围很广(内存屏障在读或写缓冲区中放置一个标记)。我猜 gcc 使用较小的范围 - 也许是 C 范围?
是的,gcc 对它的语义cpu_relax或它扩展的任何内容都有特殊的了解,并且必须将其转换为硬件也尊重语义的东西。
是的,任何类型的内存防护原语都需要编译器和硬件的特别尊重。
查看宏扩展为什么,例如使用“gcc -E”进行编译并检查输出。您必须阅读编译器文档才能找出原语的语义。
内存栅栏的范围与编译器可能移动加载或存储的范围一样宽。从不跨子例程调用移动加载或存储的非优化编译器可能不需要过多关注表示为子例程调用的内存栅栏。跨翻译单元进行过程间优化的优化编译器需要在更大的范围内跟踪内存栅栏。
| 归档时间: |
|
| 查看次数: |
2997 次 |
| 最近记录: |