После прочтения документации я все еще не понимаю, как использовать par_unseq
. Я знаю, что ничего не могу сказать о порядке выполнения из-за потоковой передачи и векторизации, но могу ли я полагаться на порядок выходных данных?
transform([x0, x1, x2], f) == [f(x0), f(x1), f(x2)]]
Другими словами, этот тест когда-нибудь потерпит неудачу?
std::vector<int> xs = {1, 2, 3, 4};
std::vector<int> ys(xs.size());
std::transform(
std::execution::par_unseq,
cbegin(xs), cend(xs),
begin(ys),
[](int x) { return x*x; });
std::vector<int> expected = {1, 4, 9, 16};
ASSERT_EQ(expected , ys);
Нет, ваш тест никогда не потерпит неудачу, потому что даже если порядок выполнения изменится,
ys[0...3] = xs[0...3] * xs[0...3] = {1*1, 2*2, 3*3, 4*4};
не изменится.
Стандарт, [alg.transform], гласит:
Effects: Assigns through every iterator
i
in the range[result,result + (last1 - first1))
a new corresponding value equal toop(*(first1 + (i - result))
orbinary_op(*(first1 + (i - result)), *(first2 + (i - result)))
.
и (спасибо, @Caleth), [алгоритмы.parallel.overloads]:
Unless otherwise specified, the semantics of
ExecutionPolicy
algorithm overloads are identical to their overloads without.
Итак, да, вы можете положиться на порядок вывода.
У вас также есть «Если не указано иное, семантика перегрузок алгоритма ExecutionPolicy идентична их перегрузкам без» в [алгоритмы.parallel.overloads]
Спасибо, en.cppreference.com/w/cpp/algorithm/transform не упоминает об этом поведении, но кажется, что стандарт очень ясен по этому поводу.
Насколько я понимаю, порядок выходов
std::transform
является частью его спецификации и не должен меняться независимо от выбранной политики выполнения.