依赖于CPU体系结构?

依赖于CPU体系结构?,c,visual-studio,compilation,cpu,cpu-architecture,C,Visual Studio,Compilation,Cpu,Cpu Architecture,我想确定下面的代码是否允许CPU获取不安全的_变量两次?假设编译器不会因为volatile和_ReadWriteBarrier(在VS上)而对代码进行重新排序或优化。这里不能使用互斥,我只关心潜在的双取的情况 我不是CPU设计方面的专家,但我关心的是潜在的双取:推测性执行(性能优化技术,包括分支预测和预取技术)、寄存器和内存位置重命名以及在一个或两个CPU内使用重排序缓冲区和存储缓冲区?请让我知道这里是否有可能进行双重提取 int function(void* Data) { size_

我想确定下面的代码是否允许CPU获取不安全的_变量两次?假设编译器不会因为volatile和_ReadWriteBarrier(在VS上)而对代码进行重新排序或优化。这里不能使用互斥,我只关心潜在的双取的情况

我不是CPU设计方面的专家,但我关心的是潜在的双取:推测性执行(性能优化技术,包括分支预测和预取技术)、寄存器和内存位置重命名以及在一个或两个CPU内使用重排序缓冲区和存储缓冲区?请让我知道这里是否有可能进行双重提取

int function(void* Data) {
    size_t _varSize = ((volatile DATA *)Data)->unsafe_variable;
    // unsafe_variable is in some kind of shared memory and can change at any time
    _ReadWriteBarrier();
    // this does not prevent against CPU optimisations (MemoryBarrier would)
    if (_varSize > x * y) { return FALSE;}
    size_t size = _varSize - t * q;
    function_xy(size);
    return TRUE;
}

C语言中没有任何东西指定这个级别的内存系统行为,也没有任何关于线程的内容,因此没有确定的答案

为了确定,您需要CPU、操作系统和编译器的详细信息

然而,我怀疑任何现代建筑都不会从记忆中提取两次来满足你提到的任何目的,只要计算不被中断。第一个之后的任何引用都将被缓存


但是,如果在
unsafe_变量
提取开始后但在
\u varSize
可以使用之前存在上下文切换,则可以想象,当此线程继续时,提取可能会重新启动。

访问易失性内存位置在C标准C11 5.1.2.3/2中算作副作用:

访问易失性对象、修改对象、修改文件或调用函数 也就是说,这些手术都是副作用。”

而且编译器不允许生成导致额外副作用的代码。明确不允许生成导致额外访问易失性变量的代码(C11 5.1.2.3/6)


但是你使用的是VC++,所以所有的赌注都没有了。它几乎没有遵循任何标准。如果可能的话,我建议使用严格符合标准的C编译器。

文章中提到了大量关于线程的内容。关于上下文切换的情况,您提出了一个很好的观点。有可能在IF之后有一个硬件上下文切换吗?我相信寄存器会被保存。对于读者Lundin:C语言标准不包含thread这个词。您可能正在考虑Posix标准,它包含用于线程的C API,但不是C标准的一部分。我同意,如果该值一直到达寄存器,则不会重新启动提取。我在炒作,当中断发生时,内存系统可能只是获取的一部分,而这个中间状态可能会被转储。我知道一个事实,例如字符串指令在某些体系结构中需要重新启动,这意味着回迁可以发生多次。正如你所说,加载一个单词时,这似乎不太可能。但这是可以想象的。VC++似乎与volatile一起工作,就像它与_ReadWriteBarrier()一起工作一样,它会阻止编译器优化/重新排序。我更关心的是CPU优化,它可能会允许在这里进行双重提取。@Bookix编译器不允许生成执行多个
数据访问的代码,因为这将违反C标准。编译器是为特定CPU编写/移植的,因此编译器负责确保多核中的指令缓存不会破坏代码的预期行为。这似乎不能回答这个问题。问题不是关于编译器,而是关于CPU推测性读取和类似功能。@请阅读注释1。不能允许编译器忽略它所针对的系统。
int function(void* Data) {
    size_t _varSize = ((volatile DATA *)Data)->unsafe_variable;
    // unsafe_variable is in some kind of shared memory and can change at any time
    _ReadWriteBarrier();
    // this does not prevent against CPU optimisations (MemoryBarrier would)
    if (_varSize > x * y) { return FALSE;}
    size_t size = _varSize - t * q;
    function_xy(size);
    return TRUE;
}