繁体   English   中英

OpenMP 缩减子句不适用于大的 long int for 循环计数

[英]OpenMP reduction clause does not work for a big long int for loop count

有以下一段代码:

#include <iostream>
#include <fstream>
#include <limits>
#include <chrono>
#include <omp.h>

const long int N=1000000000L;

class Counter {
public:
  Counter():n(0),N(0){}
  void operator()()
  {
    if(n==INT_MAX)
    {
  #pragma omp atomic update
      ++N;
  #pragma omp atomic write
      n=1;
    }
    else
    {    
  #pragma omp atomic update
      ++n;
    }
  }
  long int GetTotalCount()
  {
    return (static_cast<long int>(n)+static_cast<long int>(N)*static_cast<long int>(INT_MAX));
  }
  friend std::ostream & operator<<(std::ostream & o, Counter & counter)
  {
    o<<counter.GetTotalCount()<<" ("<<counter.N<<","<<counter.n<<") = "
     <<static_cast<long int>(counter.N)*static_cast<long int>(counter.INT_MAX)+static_cast<long int> 
       (counter.n)
 <<std::endl;
return o;
  }
private:
  const int INT_MAX=std::numeric_limits<int>::max();
  int n;
  int N;
};

int main(int argc, char **argv)
{
  const auto begin = std::chrono::steady_clock::now();
  Counter counter;
#pragma omp parallel for simd
  for(long int i=0; i<N; ++i)
  {
    if(i%2==0) counter();
  }
  const auto end = std::chrono::steady_clock::now();
  std::cout<<"N="<<N<<std::endl;
  std::cout<<"Total count="<<counter;
  auto time = std::chrono::duration_cast<std::chrono::milliseconds>(end-begin).count();
  std::cout<<"t="<<time<<" ms"<<std::endl;
  return 0;
}

它适用于所有 N <=1000000000 并给出以下 output:

N=1000000000

总计数=500000000 (0,500000000) = 500000000

t=11297 毫秒

但是如果要使 N 大 10 倍,则 output 不正确(第 2 行):

N=10000000000

总计数=705032704 (0,705032704) = 705032704

t=112660 毫秒

这里的第二行必须是

总计数=500000000 (2,500000000) = 705032706

我不明白为什么程序在 N=1e10 处无法正常运行,尽管 N 是long int

您在检查中有一个竞争条件:

if(n==INT_MAX)
{
    // Nothing prevents another thread to read n here and enter the same branch
    #pragma omp atomic update
    ++N;
    #pragma omp atomic write
    n=1;
}

因此,两个线程可能都决定同时重置n和递增N

除此之外,您还必须以原子方式读取n以获取 if 检查本身,尽管仅此还不够。

总体而言,您最好使用实际的 OpenMP 缩减或自定义构建的缩减以及支持实际原子操作的足够大的数据类型。

暂无
暂无

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

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