简体   繁体   English

如何停止OpenMP 2.0的并行区域

[英]How to stop parallel region of OpenMP 2.0

I look for a better way to cancel my threads. 我正在寻找一种取消线程的更好方法。 In my approach, I use a shared variable and if this variable is set, I just throw a continue. 在我的方法中,我使用一个共享变量,如果设置了此变量,我将抛出一个继续。 This finishes my threads fast, but threads keep theoretically spawning and ending, which seems not elegant. 这样可以快速完成我的线程,但是从理论上讲线程会不断产生和结束,这似乎并不优雅。 So, is there a better way to solve the issue ( break is not supported by my OpenMP)? 因此,是否有更好的方法来解决此问题(OpenMP不支持break )?

I have to work with Visual, so my OpenMP Lib is outdated and there is no way around that. 我必须使用Visual,所以我的OpenMP Lib已过时,无法解决。 Consequently, I think #omp cancel will not work 因此,我认为#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;
    }
  }
}

You should do it the simple way of "just continue in all remaining iterations if cancellation is requested". 您应该采用“如果要求取消,仅在所有剩余的迭代中continue进行”的简单方法。 That can just be the first check in the outermost loop (and given that you have several nested loops, that will probably not have any measurable overhead). 那可能只是最外层循环中的第一个检查(并且假设您有多个嵌套循环,则可能没有任何可测量的开销)。

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;
        }
      }
    }
  }
}

Generally speaking, OMP will not suddenly spawn new threads or end existing ones, especially not within one parallel region. 一般来说,OMP不会突然产生新线程或终止现有线程,尤其是不在一个并行区域内。 This means there is little overhead associated with running a few more tiny iterations. 这意味着与运行更多小的迭代相关的开销很小。 This is even more true given that the default scheduling in your case is most likely static , meaning that each thread knows its start and end index right away. 鉴于您的情况下默认调度很可能是static ,这更加正确,这意味着每个线程都立即知道其起始索引和结束索引。 Other scheduling modes would have to call into the OMP runtime every iteration (or every few iterations) to request more work, but that won't happen here. 其他调度模式将不得不在每次迭代(或每几次迭代)中调用OMP运行时以请求更多工作,但这不会在这里发生。 The compiler will basically see this code for the threaded work: 编译器基本上将看到以下代码用于线程工作:

// 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.
}

You might try a non-atomic thread-local "should I cancel?" 您可以尝试使用非原子线程本地“我应该取消吗?” flag that starts as false and can only be changed to true (which the compiler may understand and fold into the loop condition). 该标志以false开头,并且只能更改为true (编译器可以理解并折叠成循环条件)。 But I doubt you will see significant overhead either way, at least on x86 where int is atomic anyway. 但是我怀疑您是否会以任何方式看到大量开销,至少在x86上无论如何int都是原子的。

which seems not elegant 看起来不太优雅

OMP 2.0 does not exactly shine with respect to elegance. OMP 2.0在优雅方面并不完全闪耀。 I mean, iterating over a std::vector requires at least one static_cast to silence signed -> unsigned conversion warnings. 我的意思是,遍历std::vector至少需要一个static_cast才能使有符号->无符号转换警告静音。 So unless you have specific evidence of this pattern causing a performance problem, there is little reason not to use it. 因此,除非您有具体的证据证明这种模式会导致性能问题,否则没有理由不使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM