Я читал о новой модели памяти С++ 11, и я пришел к функции std::kill_dependency
(& sect; 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
и этого другого потока?
Предполагая, что мое недооценка верна, все еще есть одна вещь, которая меня беспокоит: когда я пишу код, какие причины приведут меня к выбору убить зависимость?