相关疑难解决方法(0)

C++ 11引入了标准化的内存模型.这是什么意思?它将如何影响C++编程?

C++ 11引入了标准化的内存模型,但究竟是什么意思呢?它将如何影响C++编程?

这篇文章(引用Herb SutterGavin Clarke)说,

内存模型意味着C++代码现在有一个标准化的库可以调用,无论是谁编译器以及它运行的平台.有一种标准方法可以控制不同线程与处理器内存的对话方式.

"当你谈论在标准中的不同内核之间分割[代码]时,我们正在谈论内存模型.我们将优化它,而不会破坏人们将在代码中做出的以下假设," Sutter说.

好吧,我可以在网上记住这个和类似的段落(因为我从出生以来就拥有自己的记忆模型:P),甚至可以发布作为其他人提出的问题的答案,但说实话,我并不完全明白这个.

C++程序员以前用于开发多线程应用程序,那么如果它是POSIX线程,Windows线程或C++ 11线程,它又如何重要呢?有什么好处?我想了解低级细节.

我也觉得C++ 11内存模型与C++ 11多线程支持有某种关系,因为我经常将这两者结合在一起.如果是,究竟是怎么回事?他们为什么要相关?

由于我不知道多线程的内部工作原理以及内存模型的含义,请帮助我理解这些概念.:-)

c++ multithreading memory-model language-lawyer c++11

1810
推荐指数
7
解决办法
21万
查看次数

我可以安全地使用OpenMP和C++ 11吗?

OpenMP标准仅考虑C++ 98(ISO/IEC 14882:1998).这意味着在C++ 03甚至C++ 11下没有标准的OpenMP支持用法.因此,任何使用C++> 98和OpenMP的程序都在标准之外运行,这意味着即使它在某些条件下工作,它也不太可能是可移植的,但绝对不能保证.

C++ 11具有自己的多线程支持,情况更糟,这很可能会在某些实现中与OpenMP发生冲突.

那么,将OpenMP与C++ 03和C++ 11一起使用有多安全?

可以安全地在一个相同的程序中使用C++ 11多线程和OpenMP但不交错它们(即在任何代码中没有传递给C++ 11并发特性的OpenMP语句,并且线程中没有C++ 11并发由OpenMP产生)?

我特别感兴趣的是我首先使用OpenMP调用一些代码,然后在相同的数据结构上使用C++ 11并发代码调用其他代码.

c++ openmp c++11

40
推荐指数
3
解决办法
8776
查看次数

为什么这个随机数生成器不是线程安全的?

我正在使用rand()函数生成0,1之间的伪随机数用于模拟目的,但是当我决定使我的C++代码并行运行时(通过OpenMP),我注意到rand()它不是线程安全的,也不是很均匀.

所以我转而使用在其他问题的许多答案中提出的(所谓的)更均匀的生成器.看起来像这样

double rnd(const double & min, const double & max) {
    static thread_local mt19937* generator = nullptr;
    if (!generator) generator = new mt19937(clock() + omp_get_thread_num());
    uniform_real_distribution<double> distribution(min, max);
    return fabs(distribution(*generator));
}
Run Code Online (Sandbox Code Playgroud)

但是我在我模拟的原始问题中看到了许多科学错误.既反对结果rand()也反对常识的问题.

所以我编写了一个代码,用这个函数生成500k随机数,计算它们的平均值并做200次并绘制结果.

double SUM=0;
for(r=0; r<=10; r+=0.05){   
    #pragma omp parallel for ordered schedule(static)
    for(w=1; w<=500000; w++){   
        double a;
        a=rnd(0,1);
        SUM=SUM+a;
    } 
    SUM=SUM/w_max;
    ft<<r<<'\t'<<SUM<<'\n';
    SUM=0;
}   
Run Code Online (Sandbox Code Playgroud)

我们知道如果不是500k,我可以无限次地做它,它应该是一个值为0.5的简单线.但是有了500k,我们的波动将在0.5左右.

使用单个线程运行代码时,结果是可以接受的:

在此输入图像描述

但这是2个线程的结果:

在此输入图像描述

3个主题:

在此输入图像描述

4个主题:

在此输入图像描述

我现在没有我的8线程CPU,但结果甚至值得.

正如你所看到的,它们都不均匀,并且在平均值附近波动很大.

这个伪随机生成器线程也不安全吗?

或者我在某个地方犯了错误?

c++ random multithreading openmp

11
推荐指数
2
解决办法
566
查看次数

std :: atomic可以安全地与OpenMP一起使用

我目前正在努力学习使用OpenMP,我有一个问题.做这样的事情是否安全:

  std::atomic<double> result;
  #pragma omp parallel for
  for(...)
  {
  result+= //some stuff;
  }
Run Code Online (Sandbox Code Playgroud)

或者我应该使用:

  double result;
  #pragma omp parallel for
  for(...)
  {
    double tmp=0;
    //some stuff;
    #pragma omp atomic
    result+=tmp;
  }
Run Code Online (Sandbox Code Playgroud)

谢谢 !

编辑:我知道处理的最简单的方法是使用数组,但我问,因为我很好奇

c++ atomic openmp c++11 stdatomic

9
推荐指数
1
解决办法
883
查看次数

在OpenMP中优雅的异常处理

OpenMP禁止通过异常离开openmp块的代码.因此,我正在寻找一种从openmp块获取异常的好方法,目的是在主线程中重新抛出它并在稍后处理.到目前为止,我能够提出的最好的是以下内容:

class ThreadException {
    std::exception_ptr Ptr;
    std::mutex         Lock;
public:
    ThreadException(): Ptr(nullptr) {}
    ~ThreadException(){ this->Rethrow(); }  
    void Rethrow(){
        if(this->Ptr) std::rethrow_exception(this->Ptr);
    }
    void CaptureException() { 
        std::unique_lock<std::mutex> guard(this->Lock);
        this->Ptr = std::current_exception(); 
    }   
};
//...
ThreadException except;
#pragma omp parallel
{
    try {
      //some possibly throwing code
    } 
    catch(...) { except.CaptureException(); }
}
Run Code Online (Sandbox Code Playgroud)

虽然这很好用,但是一旦ThreadException对象被销毁,就可以从并行部分重新抛出可能的异常,这个结构仍然有点笨拙用于放置try {}catch(...){}每个部分并且必须手动捕获异常.

所以我的问题是:有没有人知道更优雅(更简洁)的方式(如果是这样,它看起来像什么)?

c++ exception-handling openmp c++11

8
推荐指数
1
解决办法
2487
查看次数

重新排序操作和无锁数据结构

假设我们Container维护了一组int值,并为每个值指示了该值是否有效.无效值被认为是INT_MAX.最初,所有值都无效.第一次访问值时,将其设置为INT_MAX并将其标志设置为有效.

struct Container {
  int& operator[](int i) {
    if (!isValid[i]) {
      values[i] = INT_MAX; // (*)
      isValid[i] = true;   // (**)
    }
    return values[i];
  }
  std::vector<int> values;
  std::vector<bool> isValid;
};
Run Code Online (Sandbox Code Playgroud)

现在,另一个线程同时读取容器值:

// This member is allowed to overestimate value i, but it must not underestimate it.
int Container::get(int i) {
  return isValid[i] ? values[i] : INT_MAX;
}
Run Code Online (Sandbox Code Playgroud)

这是完全合法的代码,但是它行是至关重要的(*),并(**)在给定的顺序执行.

  1. 在这种情况下,标准是否保证线路按给定顺序执行?至少从单线程的角度来看,线路可以互换,不是吗?
  2. 如果没有,确保订单的最有效方法是什么?这是高性能的代码,所以我不能没有-O3,也不想使用volatile.

c++ gcc lock-free compiler-optimization c++14

0
推荐指数
1
解决办法
94
查看次数