Как распараллелить обычный цикл for с использованием стандартной библиотеки C ++ - PullRequest
3 голосов
/ 25 апреля 2019

Я чувствую себя глупо, когда спрашиваю об этом, но я просто не могу найти не замысловатый способ сделать это.

У меня есть следующий цикл:

for (int i = 0; i < count; ++i) {
  if (myFunc(i))
    continue;

  myOtherFunc(i);
}

Распараллелить это с OpenMP тривиально: просто добавьте #pragma omp parallel for перед циклом.

Я хотел сравнить производительность OMP (и его различных расписаний) с параллельной реализацией MSVC <algorithms> (т.е. с использованием C ++ 17политика исполнения).Простая идея заключалась бы в использовании std::for_each, но я не могу найти хороший способ превратить этот супер-простой цикл for в любую подходящую вещь <algorithm>, в которую я могу бросить политику выполнения.

Примечательно, что вы не можете просто сделать

std::for_each(std::execution::par, 0, count, [](int i){ /*...*/ });

, потому что вы должны предоставить итераторов (то есть что-то, что дает аргумент i, когда разыменовывается ).

  • Я мог бы std::iota в std::vector из int только для того, чтобы у меня был диапазон индексов для перебора.Это было бы абсурдно.

  • Я мог бы использовать std::generate_n с некоторым фиктивным итератором вывода, который отбрасывает все, что ему назначено.Так как я не думаю, что это доступно в std, мне пришлось бы сам написать полный фиктивный итератор.И это, конечно, было бы глупо, несмотря ни на что.А для получения правильного индекса, вероятно, потребуется ручное отслеживание с std::atomic<int>, потому что вы не знаете свой текущий индекс.

  • У меня действительно нет контейнеразациклить.Я имею в виду, что где-то глубоко внутри этих функций есть контейнеры, но о реструктуризации всего, чтобы я мог использовать итераторы для некоторого контейнера в этом цикле, не может быть и речи.

  • 15 минут поиска различных описаний этого мне ни к чему не привели.

Есть ли способ сопоставить самый простой и простой цикл for с <algorithm>инструменты, в которых нет глупости?

1 Ответ

5 голосов
/ 25 апреля 2019

Если вы используете , вы можете использовать boost::irange), чтобы создать цикл подсчета, подобный этому:

auto ints = boost::irange(0, count);
std::for_each_n(POLICY, ints.begin(), boost::size(ints), [](int i)
{
  if (!myFunc(i)) {
    myOtherFunc(i);
  }
}
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...