Я читал о новой модели памяти C ++ 11 и наткнулся на функцию std :: kill_dependency
(§29.3 / 14-15). Я изо всех сил пытаюсь понять, почему я вообще захочу его использовать.
Я нашел пример в предложении N2664 , но это не сильно помогло.
Все начинается с показа кода без std :: kill_dependency
. Здесь первая строка переносит зависимость во вторую, которая переносит зависимость в операцию индексирования, а затем переносит зависимость в функцию do_something_with
.
r1 = x.load(memory_order_consume);
r2 = r1->index;
do_something_with(a[r2]);
Существует еще один пример, который использует std :: kill_dependency
, чтобы разорвать зависимость между второй строкой и индексацией.
r1 = x.load(memory_order_consume);
r2 = r1->index;
do_something_with(a[std::kill_dependency(r2)]);
Насколько я могу судить, это означает, что индексация и вызов do_something_with
не являются зависимостями, упорядоченными до вторая линия. Согласно N2664:
Это позволяет компилятору переупорядочить вызов
do_something_with
, например, путем выполнения спекулятивных оптимизаций, которые предсказывают значениеa [r2]
.
Для вызова do_something_with
необходимо значение a [r2]
. Если, гипотетически, компилятор «знает», что массив заполнен нулями, он может оптимизировать этот вызов do_something_with (0);
и изменить порядок этого вызова относительно двух других инструкций по своему усмотрению. Это может привести к любому из:
// 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
и этот другой поток?
Предполагая, что мое понимание верное, меня все еще беспокоит одна вещь: когда я пишу код, какие причины могут побудить меня решить убить зависимость?