Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ OpenMP reduction子句不适用于大的long int for循环计数_C++_Openmp_Atomic - Fatal编程技术网

C++ OpenMP reduction子句不适用于大的long int for循环计数

C++ OpenMP reduction子句不适用于大的long int for循环计数,c++,openmp,atomic,C++,Openmp,Atomic,下面是一段代码: #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_M

下面是一段代码:

#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=100000000升;
班级计数器{
公众:
计数器():n(0),n(0){
void运算符()()
{
如果(n==INT_MAX)
{
#pragma omp原子更新
++N;
#pragma omp原子写入
n=1;
}
其他的
{    
#pragma omp原子更新
++n;
}
}
long int GetTotalCount()
{
返回(静态施法(n)+静态施法(n)*静态施法(INT_MAX));
}

friend std::ostream&operator检查中有一个竞争条件:

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

除此之外,您还必须对if检查本身进行原子化读取,尽管仅此还不够


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

检查中有竞争条件:

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

除此之外,您还必须对if检查本身进行原子化读取,尽管仅此还不够


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

如果要添加int n;#pragma omp atomic read x=n;如果(n==int_MAX){…},它没有帮助。如果存在竞态条件,为什么代码在N=10^9 ans更小的情况下正常工作?是的,如回答中所述,仅原子地读取检查是不够的。竞态条件从来都不需要实际导致可检测问题。竞态条件在随机条件下表现为问题是很常见的或者完全模糊的条件。但是,在你的情况下,这很简单:只要
n
没有线程会首先进入有问题的if分支。哦,当然。但是我该怎么做才能让代码正常工作呢?你写过我可以使用实际的OpenMP缩减。你的意思是摆脱#pragma omp原子更新和#pragma omp原子写入吗e和使用simd行的#pragma omp parallel中的reduce(+:N,N)子句?是的,您可以对足够大的
N
类型使用
reduce(+:N)
,或者声明自定义reduce。对于后者,我认为您可以通过实现兼容的“大数”来使用
+
类,该类支持从int和自身上的
运算符+
进行初始化。如果这不起作用,请使用
声明约简
。如果要添加int n;#pragma omp atomic read x=n;如果(n==int\u MAX){…},它没有帮助。如果存在竞态条件,为什么代码在N=10^9 ans更小的情况下正常工作?是的,如回答中所述,仅原子地读取检查是不够的。竞态条件从来都不需要实际导致可检测问题。竞态条件在随机条件下表现为问题是很常见的或者完全模糊的条件。但是,在你的情况下,这很简单:只要
n
没有线程会首先进入有问题的if分支。哦,当然。但是我该怎么做才能让代码正常工作呢?你写过我可以使用实际的OpenMP缩减。你的意思是摆脱#pragma omp原子更新和#pragma omp原子写入吗e和使用simd行的#pragma omp parallel中的reduce(+:N,N)子句?是的,您可以对足够大的
N
类型使用
reduce(+:N)
,或者声明自定义reduce。对于后者,我认为您可以通过实现兼容的“大数”来使用
+
类,该类支持从int和自身上的
运算符+
初始化。如果这不起作用,请使用
声明缩减
。您的问题标题提到“OpenMP缩减子句”。但是,显示的代码中没有。您的问题标题提到“OpenMP缩减子句”。但是,显示的代码中没有。