首页 > 解决方案 > 与 asm volatile 相比,我们需要使用一些运行时内存围栏机制

问题描述

假设我们有这样一段 c++ 代码:

auto t1 = getSystemTime(); // Statement 1
foo();                     // Statement 2
auto t2 = getSystemTime(); // Statement 3

auto elapsedTime = t2 - t1;

据我了解,编译器可能会优化代码,这意味着它只有在不违反 as-if 规则的情况下才可能重新排序执行顺序。比如下面代码的执行顺序

c = a + b;
d = e + f;

可以重新排序为

d = e + f;
c = a + b;

因此,上面的代码可以重新排序如下:

auto t1 = getSystemTime(); // Statement 1
auto t2 = getSystemTime(); // Statement 3
foo();                     // Statement 2

auto elapsedTime = t2 - t1;

这会产生完全不同的结果。

在谷歌搜索这个问题后,我得到了这个:__asm__ __volatile__ ("" ::: "memory");. 如果我是对的,通过这一行,我们可以禁用编译器的优化,这样执行顺序就不会被重新排序。

如果我正确使用它,代码将如下所示:

__asm__ __volatile__ ("" ::: "memory");
auto t1 = getSystemTime(); // Statement 1
foo();                     // Statement 2
auto t2 = getSystemTime(); // Statement 3

auto elapsedTime = t2 - t1;

但是,在阅读了一些文档后,我发现这__asm__ __volatile__ ("" ::: "memory");只是编译时,而不是运行时。

现在我很困惑。如果__asm__ __volatile__ ("" ::: "memory");仅在编译时工作,是否意味着它完全没用,因为执行顺序仍然可以在运行时更改?如果是这样,是否有其他机制来禁止在运行时重新排序?或者没有任何其他机制,因此执行顺序仍然可以在运行时重新排序,但__asm__ __volatile__ ("" ::: "memory");我们可以降低重新排序的概率?

此外,我们在 C++11 中有内存顺序,内存顺序可以帮助解决这个问题吗?

标签: c++c++11compiler-optimizationmemory-barriers

解决方案


推荐阅读