C ++ 17: Как получить индекс рабочего элемента параллельно STL - PullRequest
0 голосов
/ 16 октября 2018

Есть ли способ узнать идентификатор / индекс рабочего элемента в параллельных алгоритмах?

Это было бы полезно, например, при генерации йоты:

std::vector<int> vec(max_size);
std::for_each(std::execution::par, vec.begin(), vec.end(), 
   [](int& elem) {
    elem = work_item_index;
});

, но как вычислитьэто work_item_index значение эффективно?

Ответы [ 3 ]

0 голосов
/ 16 октября 2018

Вы работаете в диапазоне, включающем индекс.

std::vector<int> vec(max_size);
auto indexed_vec = ranges::view::zip(vec, ranges::view::indices(vec));
std::for_each(std::execution::par, indexed_vec.begin(), indexed_vec.end(), 
   [](std::tuple<int&, int> elem) {
    std::get<0>(elem) = std::get<1>(elem);
});
0 голосов
/ 23 декабря 2018

На самом деле это не стандартизировано.Это зависит от параллельного движка, который используется для распараллеливания алгоритмов.Например, omp_get_thread_num() для OpenMP.

Однако, если вы просто хотите получить индекс текущего элемента обработки вектора, вы можете использовать counting_iterator.Как только это также нестандартизированная функция, вы можете использовать ее из библиотек: Boost , TBB , Intel's Parallel STL

std::vector<int> vec(max_size);
auto first = vec.begin();
std::for_each(std::execution::par, counting_iterator<int>(0), counting_iterator<int>(max_size), 
   [first](int& work_item_index) {
    first[work_item_index] = work_item_index;
});
0 голосов
/ 16 октября 2018

РЕДАКТИРОВАТЬ: Этот подход не гарантированно работает, так как на идентичность элемента (т.е. адрес) нельзя полагаться при параллельном выполнении.

Правильное решение - связать диапазон итератора с диапазоном индексов., как показано в ответе Калет.

Вы можете использовать арифметику указателей:

int* beg = vec.data();
std::for_each(std::execution::par, vec.begin(), vec.end(), 
   [beg](int& elem) {
    elem = &elem - beg;
});

Очевидно, это работает только для контейнеров, которые хранят элементы непрерывно.

...