OpenMP中预先分配的私有std :: vector并行化为C++中的循环

Max*_*low 6 c++ for-loop openmp stdvector

我打算使用缓冲区std::vector<size_t> buffer(100),在循环并行化的每个线程中使用一个缓冲区,如此代码所示:

std::vector<size_t> buffer(100);
#pragma omp parallel for private(buffer)
for(size_t j = 0; j < 10000; ++j) {
    // ... code using the buffer ...
}
Run Code Online (Sandbox Code Playgroud)

此代码不起作用.虽然每个线程都有一个缓冲区,但它们的大小为0.

如何在每个线程的开头分配缓冲区?我还能用#pragma omp parallel for吗?我可以比这更优雅地做到这一点:

std::vector<size_t> buffer;
#pragma omp parallel for private(buffer)
for(size_t j = 0; j < 10000; ++j) {
    if(buffer.size() != 100) {
        #pragma omp critical
        buffer.resize(100);
    }
    // ... code using the buffer ...
}
Run Code Online (Sandbox Code Playgroud)

Mys*_*ial 9

拆分OpenMP区域,如此问题所示.

然后在外部区域内声明向量,但在for循环本身之外.这将为每个线程创建一个本地向量.

#pragma omp parallel
{
    std::vector<size_t> buffer(100);

#pragma omp for
    for(size_t j = 0; j < 10000; ++j) {
    {

        // ... code using the buffer ...

    }
}
Run Code Online (Sandbox Code Playgroud)


cur*_*uin 9

问题和接受的答案已经存在了一段时间,这里有一些进一步的信息,提供了对openMP的额外见解,因此可能对其他用户有所帮助.

在C++中,privatefirstprivate子句以不同方式处理类对象:

从OpenMP应用程序接口v3.1:

private:新的列表项已初始化,或者具有未定义的初始值,就好像它是在没有初始化程序的情况下本地声明的那样.调用类型的不同私有变量的任何默认构造函数的顺序是未指定的.

firstprivate:对于类类型的变量,调用复制构造函数来执行列表变量的初始化.

ie private调用默认构造函数,而firstprivate调用相应类的复制构造函数.

默认构造函数std::vector构造一个没有元素的空容器,这就是缓冲区大小为0的原因.

要回答这个问题,这将是另一个解决方案,无需拆分OpenMP区域:

std::vector<size_t> buffer(100, 0);  
#pragma omp parallel for firstprivate(buffer)
for (size_t j = 0; j < 10000; ++j) {
  // use the buffer
}
Run Code Online (Sandbox Code Playgroud)

编辑一般关于私有变量的警告:线程堆栈大小是有限的,除非显式设置(环境变量OMP_STACKSIZE)编译器相关.如果使用具有大内存占用量的私有变量,则堆栈溢出可能会成为问题.