`std :: kill_dependency`做什么,为什么要使用它呢? [英] What does `std::kill_dependency` do, and why would I want to use it?
问题描述
我一直在阅读关于新的C ++ 11内存模型,我来了 std :: kill_dependency
函数(§ 29.3 / 14-15 )。我很难理解为什么我会使用它。
I've been reading about the new C++11 memory model and I've come upon the std::kill_dependency
function (§29.3/14-15). I'm struggling to understand why I would ever want to use it.
我在 N2664提案,但它没有太大帮助。
I found an example in the N2664 proposal but it didn't help much.
它首先显示没有 std :: kill_dependency
的代码。这里,第一行在第二行中携带依赖性,其带有对索引操作的依赖性,然后将依赖性携带到 do_something_with
函数中。
It starts by showing code without std::kill_dependency
. Here, the first line carries a dependency into the second, which carries a dependency into the indexing operation, and then carries a dependency into the do_something_with
function.
r1 = x.load(memory_order_consume);
r2 = r1->index;
do_something_with(a[r2]);
还有另一个使用 std :: kill_dependency
破坏第二行和索引之间的依赖关系。
There is further example that uses std::kill_dependency
to break the dependency between the second line and the indexing.
r1 = x.load(memory_order_consume);
r2 = r1->index;
do_something_with(a[std::kill_dependency(r2)]);
据我所知,这意味着索引和调用 do_something_with
在第二行之前没有依赖顺序。根据N2664:
As far as I can tell, this means that the indexing and the call to do_something_with
are not dependency ordered before the second line. According to N2664:
这允许编译器将调用重新排序为
do_something_with
例如通过执行预测a [r2]
的值的推测优化。
This allows the compiler to reorder the call to
do_something_with
, for example, by performing speculative optimizations that predict the value ofa[r2]
.
为了调用 do_something_with
,需要值 a [r2]
。如果假设编译器知道数组用零填充,它可以优化对 do_something_with(0);
的调用,并相对于其他两个指令,因为它喜欢。它可以产生以下任意:
In order to make the call to do_something_with
the value a[r2]
is needed. If, hypothetically, the compiler "knows" that the array is filled with zeros, it can optimize that call to do_something_with(0);
and reorder this call relative to the other two instructions as it pleases. It could produce any of:
// 1
r1 = x.load(memory_order_consume);
r2 = r1->index;
do_something_with(0);
// 2
r1 = x.load(memory_order_consume);
do_something_with(0);
r2 = r1->index;
// 3
do_something_with(0);
r1 = x.load(memory_order_consume);
r2 = r1->index;
我的理解是否正确?
do_something_with
通过其他方式与另一个线程同步,这对于 x.load
的顺序意味着什么,调用和这个其他线程?
If do_something_with
synchronizes with another thread by some other means, what does this mean with respect to the ordering of the x.load
call and this other thread?
假设我的转义是正确的,还有一件事是错误的:当我写代码时,什么原因导致我选择杀死依赖项?
Assuming my understading is correct, there's still one thing that bugs me: when I'm writing code, what reasons would lead me to choose to kill a dependency?
推荐答案
memory_order_consume的目的是确保编译器不做某些不幸的优化,例如,考虑下面的代码:
The purpose of memory_order_consume is to ensure the compiler does not do certain unfortunate optimizations that may break lockless algorithms. For example, consider this code:
int t;
volatile int a, b;
t = *x;
a = t;
b = t;
$ b
A conforming compiler may transform this into:
a = *x;
b = *x;
因此,a可能不等于b。它也可以:
Thus, a may not equal b. It may also do:
t2 = *x;
// use t2 somewhere
// later
t = *x;
a = t2;
b = t;
使用 load(memory_order_consume)
要求正在加载的值的使用不会在使用点之前移动。换句话说,
By using load(memory_order_consume)
, we require that uses of the value being loaded not be moved prior to the point of use. In other words,
t = x.load(memory_order_consume);
a = t;
b = t;
assert(a == b); // always true
标准文档考虑的情况是,您可能只想订购某些字段结构。示例是:
The standard document considers a case where you may only be interested in ordering certain fields of a structure. The example is:
r1 = x.load(memory_order_consume);
r2 = r1->index;
do_something_with(a[std::kill_dependency(r2)]);
这指示编译器允许有效地执行此操作:
This instructs the compiler that it is allowed to, effectively, do this:
predicted_r2 = x->index; // unordered load
r1 = x; // ordered load
r2 = r1->index;
do_something_with(a[predicted_r2]); // may be faster than waiting for r2's value to be available
或者甚至:
predicted_r2 = x->index; // unordered load
predicted_a = a[predicted_r2]; // get the CPU loading it early on
r1 = x; // ordered load
r2 = r1->index; // ordered load
do_something_with(predicted_a);
如果编译器知道 do_something_with
t更改r1或r2的载荷结果,然后它可以将其一直向上抬起:
If the compiler knows that do_something_with
won't change the result of the loads for r1 or r2, then it can even hoist it all the way up:
do_something_with(a[x->index]); // completely unordered
r1 = x; // ordered
r2 = r1->index; // ordered
这允许编译器在其优化中有一点自由。
This allows the compiler a little more freedom in its optimization.
这篇关于`std :: kill_dependency`做什么,为什么要使用它呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!