我试图了解volatile关键字在C ++中的工作方式。
我看了一下“易失性”在C ++中可以防止哪些优化?。查看可接受的答案,看起来像volatile禁用了两种优化
我在https://en.cppreference.com/w/cpp/language/as_if找到了类似的信息。
对易失性对象的访问(读取和写入)严格按照发生它们的表达式的语义来发生。特别是,它们不会相对于同一线程上的其他易失性访问而重新排序。
我编写了一个简单的C ++程序,该程序对数组中的所有值求和,以比较Plain ints和volatile int的行为。请注意,部分和不会不稳定。
数组由不合格的ints 组成。
int foo(const std::array<int, 4>& input)
{
auto sum = 0xD;
for (auto element : input)
{
sum += element;
}
return sum;
}
Run Code Online (Sandbox Code Playgroud)
阵列由挥发性的int小号
int bar(const std::array<volatile int, 4>& input)
{
auto sum = 0xD;
for (auto element : input)
{
sum += element;
}
return sum;
}
Run Code Online (Sandbox Code Playgroud)
当我查看生成的汇编代码时,仅在纯ints的情况下使用SSE寄存器。据我所知,使用SSE寄存器的代码既没有优化读取,也没有对读取进行重新排序。循环已展开,因此也没有分支。我能解释代码源为何不同的唯一原因是:在发生累积之前,可以对易失性读进行重新排序吗?显然,sum它不是挥发性的。如果这种重新排序不好,是否存在可以说明问题的情况/示例?
使用clang9生成的代码
foo(std::array<int, 4ul> const&): # @foo(std::array<int, 4ul> const&)
movdqu (%rdi), %xmm0
pshufd $78, %xmm0, %xmm1 # xmm1 = xmm0[2,3,0,1]
paddd %xmm0, %xmm1
pshufd $229, %xmm1, %xmm0 # xmm0 = xmm1[1,1,2,3]
paddd %xmm1, %xmm0
movd %xmm0, %eax
addl $13, %eax
retq
bar(std::array<int volatile, 4ul> const&): # @bar(std::array<int volatile, 4ul> const&)
movl (%rdi), %eax
addl 4(%rdi), %eax
addl 8(%rdi), %eax
movl 12(%rdi), %ecx
leal (%rcx,%rax), %eax
addl $13, %eax
retq
Run Code Online (Sandbox Code Playgroud)
volatileC ++中的关键字是从C继承而来的,在C语言中,该关键字被用作一般通用方法,以指示编译器应在哪些地方允许读写对象可能具有它不知道的副作用。由于不同平台上可能引起的副作用的种类会有所不同,因此该标准的问题在于,应由哪些津贴来弥补编译器作者关于如何最好地为客户服务的判断。
Microsoft的8088/8086和更高版本的x86编译器经过数十年的设计,可支持使用volatile对象来构建可保护“普通”对象的互斥体的实践。举一个简单的例子:如果线程1做类似的事情:
ordinaryObject = 23;
volatileFlag = 1;
while(volatileFlag)
doOtherStuffWhileWaiting();
useValue(ordinaryObject);
Run Code Online (Sandbox Code Playgroud)
线程2定期执行以下操作:
if (volatileFlag)
{
ordinaryObject++;
volatileFlag=0;
}
Run Code Online (Sandbox Code Playgroud)
那么对的访问volatileFlag将向Microsoft的编译器发出警告,即他们应避免对任何对象上的任何先前动作与以后的动作进行交互做出假设。volatile其他语言(例如C#)中的限定符也遵循此模式。
不幸的是,clang和gcc都不包含volatile以这种方式处理的任何选项,而是要求程序员使用特定于编译器的内在函数来产生与Microsoft仅使用volatile适合于此目的的Standard关键字才能实现的语义相同的语义。[根据该标准的作者,“ volatile对象也是在多个进程之间共享的变量的适当模型。”-请参阅http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5 .10.pdf第 76 ll。25-26]
| 归档时间: |
|
| 查看次数: |
143 次 |
| 最近记录: |