我想找个更好的办法取消我的线程。在我的方法中,我使用一个共享变量,如果设置了这个变量,我只会抛出一个继续。这很快就完成了我的线程,但理论上线程一直在产卵和结束,这似乎不太优雅。那么,是否有更好的方法来解决这个问题(break
不受我的OpenMP支持)?
我必须使用Visual,所以我的OpenMP Lib已经过时了,这是无法避免的。因此,我认为#omp cancel
将无法工作
int progress_state = RunExport;
#pragma omp parallel
{
#pragma omp for
for (int k = 0; k < foo.z; k++)
for (int j = 0; j < foo.y; j++)
for (int i = 0; i < foo.x; i++) {
if (progress_state == StopExport) {
continue;
}
// do some fancy shit
// yeah here is a condition for speed due to the critical
#pragma omp critical
if (condition) {
progress_state = StopExport;
}
}
}
发布于 2019-01-21 16:12:13
您应该以“如果请求取消的话,在所有剩余的迭代中只使用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
来沉默已签名的->无符号转换警告。因此,除非您有这种模式导致性能问题的具体证据,否则没有什么理由不使用它。
https://stackoverflow.com/questions/54293086
复制相似问题