Вы должны сделать это простым способом "просто continue
во всех оставшихся итерациях, если запрашивается отмена". Это может быть просто первая проверка в самом внешнем цикле (и учитывая, что у вас есть несколько вложенных циклов, которые, вероятно, не будут иметь измеримых накладных расходов).
std::atomic<int> progress_state = RunExport;
// You could just write #pragma omp parallel for instead of these two nested blocks.
#pragma omp parallel
{
#pragma omp for
for (int k = 0; k < foo.z; k++)
{
if (progress_state == StopExport)
continue;
for (int j = 0; j < foo.y; j++)
{
// You can add break statements in these inner loops.
// OMP only parallelizes the outermost loop (at least given the way you wrote this)
// so it won't care here.
for (int i = 0; i < foo.x; i++)
{
// ...
if (condition) {
progress_state = StopExport;
}
}
}
}
}
Вообще говоря, OMP не будет внезапно создавать новые потоки или завершать существующие, особенно в пределах одного параллельного региона. Это означает, что при выполнении еще нескольких крошечных итераций возникают небольшие накладные расходы. Это еще более верно, учитывая, что планирование по умолчанию в вашем случае, скорее всего, static
, что означает, что каждый поток знает свой начальный и конечный индексы сразу. Другие режимы планирования должны вызывать во время выполнения OMP каждую итерацию (или каждые несколько итераций) для запроса дополнительной работы, но здесь этого не произойдет. Компилятор в основном увидит этот код для многопоточной работы:
// Not real omp functions.
int myStart = __omp_static_for_my_start();
int myEnd = __omp_static_for_my_end();
for (int k = myStart; k < myEnd; ++k)
{
if (progress_state == StopExport)
continue;
// etc.
}
Вы можете попробовать не-атомный локальный поток "я должен отменить?" флаг, который начинается с false
и может быть изменен только на true
(что компилятор может понять и сложить в условие цикла). Но я сомневаюсь, что в любом случае вы увидите значительные издержки, по крайней мере, на x86, где int
в любом случае атомарен.
что выглядит не элегантно
OMP 2.0 не совсем сияет в отношении элегантности. Я имею в виду, что для итерации по std::vector
требуется как минимум один static_cast
, чтобы заставить подпись замолчать -> предупреждения о преобразовании без знака. Поэтому, если у вас нет конкретных доказательств того, что этот шаблон вызывает проблемы с производительностью, нет особых причин не использовать его.