Я читал о новой модели памяти C ++ 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
и этого другого потока?
Предполагая, что мое понимание правильное, меня все еще беспокоит одна вещь: когда я пишу код, какие причины побуждают меня выбрать уничтожение зависимости?