【问题标题】:Simplest example of parallel run using OpenMP使用 OpenMP 并行运行的最简单示例
【发布时间】:2021-04-26 04:56:59
【问题描述】:

考虑以下代码结构,

int n = 0;

  #pragma omp parallel for collapse(2)
  for (int i = 0; i < 3; i++)
     for(int j = 0; j < 3; j++)
       n++;

以上是我尝试在需要大量时间的代码中实现的类似事物的最简单演示。因此,主要目标是并行化循环以减少运行时间。

我是 OpenMP 新手,只知道一些命令,仅此而已。现在在我上面写的代码中,最终的结果是错误的(n = 9 是正确的答案)。我猜,循环试图同时访问相同的内存位置。

现在有人可以给出一个最简单的解决方案。请注意,我对此非常陌生。任何与此相关的阅读材料也会有所帮助。谢谢。

【问题讨论】:

    标签: c++ c multithreading parallel-processing openmp


    【解决方案1】:

    我猜,循环试图访问相同的内存位置 同时。

    TL,DR : 是的,在变量n 的更新期间,您有一个竞态条件。一种解决方法是使用 OpenMP 缩减子句。

    我是 OpenMP 新手,只知道一些命令,仅此而已。现在在 我上面写的代码,最终结果出错(n = 9 是 正确答案)。

    更长的答案:

    #pragma omp parallel for 将创建一个parallel region,并使用default chunk sizedefault schedule 为该区域的threads 分配它所包含的循环的迭代,即通常 static。但是请记住,default scheduleOpenMP 标准的不同具体实现之间可能会有所不同。

    您可以从OpenMP 5.1 阅读更正式的描述:

    worksharing-loop 结构指定一个或一个的迭代 更多相关的循环将由线程中的线程并行执行 团队在他们的隐含任务的背景下。 迭代是 分布在团队中已经存在的线程中 执行工作共享循环区域所在的并行区域 绑定

    Moreover,

    并行循环结构是指定并行循环的快捷方式 包含带有一个或多个相关联的循环构造的构造 循环,没有其他语句。

    或者非正式地,#pragma omp parallel for 是构造函数 #pragma omp parallel#pragma omp for 的组合。

    因此,您的代码中发生的情况是,您有多个线程同时修改 n 的值,要解决此问题,您应该使用 OpenMP 缩减子句,从 OpenMP 标准可以阅读:

    归约子句可用于执行某些形式的递归 并行计算 (...)。 用于并行和工作共享 构造,创建每个列表项的私有副本,每个列表项一个 隐式任务,好像使用了 private 子句。 (...) 这 然后按上面指定的方式初始化私有副本。在结束时 指定缩减子句的区域,原始列表 通过将其原始值与最终值组合来更新项目 每个私有副本,使用指定的组合器 减少标识符。

    有关 reduction 子句如何工作的更详细说明,请查看SO Thread

    所以要解决代码中的 race-condition,只需将其更改为:

     int n = 0;
    
      #pragma omp parallel for collapse(2) reduction(+:n)
      for (int i = 0; i < 3; i++)
         for(int j = 0; j < 3; j++)
            n++;
    

    【讨论】:

    • 非常感谢您提供的信息!
    猜你喜欢
    • 1970-01-01
    • 2013-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    相关资源
    最近更新 更多