32

在查看 Clang 和 g++ C++11 实现状态时,我注意到一些奇怪的事情:
它们支持 C++11 原子,但它们不支持 C++11 内存模型。
我的印象是你必须有 C++11 内存模型才能使用原子。那么对原子和内存模型的支持到底有什么区别呢?
缺乏内存模型支持是否意味着使用std::atomic<T>arent seq 的合法 C++11 程序一致?

参考资料:
http ://clang.llvm.org/cxx_status.html
http://gcc.gnu.org/gcc-4.7/cxx0x_status.html

4

3 回答 3

15

问题之一是“内存位置”的定义,它允许(并强制编译器支持)通过不同的锁锁定不同的结构成员。有一个关于由此引起的 RL 问题的讨论。

基本上问题在于有这样的struct定义:

struct x {
    long a;
    unsigned int b1;
    unsigned int b2:1;
};

b2编译器也可以通过覆盖自由地实现写入b1(显然,从报告来看,确实如此)。因此,必须将这两个字段锁定为一个。然而,作为 C++11 内存模型的结果,这是被禁止的(好吧,并不是真的被禁止,但编译器必须确保同时更新b1并且b2不干扰;它可以通过锁定或对每个此类更新进行 CAS 处理来做到这一点,好吧,在某些架构上生活很困难)。引用报告:

我向我们的 GCC 人员提出了这个问题,他们对我说:“C 不提供这样的保证,如果它们共享自然对齐的字长内存区域,你也不能用不同的锁可靠地锁定不同的结构字段。C+ +11 内存模型可以保证这一点,但这没有实现,也没有使用 C++11 编译器构建内核。”

很好的信息也可以在wiki中找到。

于 2012-07-06T09:43:55.620 回答
11

我猜这些情况下的“缺少内存模型”只是意味着优化器是在 C++11 内存模型发布之前编写的,并且现在可能执行无效的优化。验证针对内存模型的优化非常困难且耗时,因此 clang/gcc 团队尚未完成这一点也就不足为奇了。

缺乏内存模型支持是否意味着使用 std::atomic 的合法 C++11 程序与 seq 不一致?

是的,这是一种可能。更糟糕的是:编译器可能会将数据竞争引入(根据 C++11 标准)无竞争程序,例如通过引入推测写入。

例如,用于执行此优化的几个 C++ 编译器:

for (p = q; p = p -> next; ++p) {
    if (p -> data > 0) ++count;
}

可以优化为:

register int r1 = count;
for (p = q; p = p -> next; ++p) {
    if (p -> data > 0) ++r1;
}
count = r1;

如果p->data都是非负数,则原始源代码没有写入count,但优化后的代码会写入。这可能会在其他无竞争的程序中引入数据竞争,因此 C++11 规范不允许此类优化。现有编译器现在必须验证(并在必要时调整)所有优化。

有关详细信息,请参阅并发内存模型编译器后果

于 2012-07-03T17:12:00.093 回答
0

与其说他们不支持内存模型,不如说他们(还)不支持标准中用于与内存模型交互的 API。该 API 包含许多互斥锁。

然而,一段时间以来,Clang 和 GCC 在没有正式标准的情况下尽可能地了解线程。您不必担心优化会将事情转移到原子操作的错误方面。

于 2012-07-02T18:55:15.560 回答