【问题标题】:CPU Architecture dependent?CPU架构依赖?
【发布时间】:2012-06-14 01:10:35
【问题描述】:

我想确定以下代码是否允许 CPU 获取 unsafe_variable 两次?假设由于 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 visual-studio compilation cpu cpu-architecture


    【解决方案1】:

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

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

    但是,我怀疑任何现代架构都会从内存中获取两次以服务于您提到的任何目的,前提是计算不会中断。第一个之后的任何引用都将被缓存。

    但是,如果在开始 unsafe_variable 提取之后但在可以使用 _varSize 之前存在上下文切换,则可以想象,当该线程继续时,提取可能会重新启动。

    【讨论】:

    • C standard 提到了很多关于线程的内容。
    • 您就上下文切换的情况提出了一个很好的观点。是否可以在 IF 之后进行硬件上下文切换?
    • 我相信寄存器会被保存。
    • 致读者 Lundin:C 语言标准不包含单词 thread。您可能正在考虑 Posix 标准,它包含用于线程的 C API,但不是 C 标准的一部分。 open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
    • 我同意,如果该值一直到达寄存器,则不会重新启动提取。我假设当中断发生时内存系统可能只是获取的一部分,并且可能会转储此中间状态。我知道一个事实,例如字符串指令在某些体系结构中会重新启动,这意味着提取可能会发生不止一次。当你说加载一个单词时,这似乎不太可能。但这是可以想象的。
    【解决方案2】:

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

    "访问 volatile 对象、修改对象、修改文件或调用函数 做任何这些操作都是副作用”

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

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

    【讨论】:

    • VC++ 似乎和 _ReadWriteBarrier() 一样适用于 volatile,它会阻止编译器优化/重新排序。我更关心的是 CPU 优化可能允许在这里进行双重提取。
    • @Bookix 不允许编译器生成执行多次Data 访问的代码,因为这会违反 C 标准。编译器是为特定 CPU 编写/移植的,因此编译器负责确保多核中的指令缓存不会破坏代码的预期行为。
    • 这似乎无法回答这个问题。问题不在于编译器,而在于 CPU 推测读取和类似功能。
    • @Read the comment 1 line up。不能允许编译器忽略它所针对的系统。
    猜你喜欢
    • 2012-03-15
    • 2015-02-24
    • 2017-09-08
    • 2014-07-14
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-31
    相关资源
    最近更新 更多