c++ - OpenMP 指针

标签 c++ c++11 openmp

我正在尝试在我的程序中使用 OpenMP(我是使用 OpenMP 的新手),程序在两个地方返回错误。

这是一个示例代码:

#include <iostream>
#include <cstdint>
#include <vector>
#include <boost/multi_array.hpp>
#include <omp.h>

class CNachbarn {
public:
    CNachbarn () { a = 0; }
    uint32_t Get_Next_Neighbor() { return a++; }

private:
    uint32_t a;
};

class CNetwork {
public:
    CNetwork ( uint32_t num_elements_ );
    ~CNetwork();
    void Validity();
    void Clean();

private:
    uint32_t num_elements;
    uint32_t nachbar;

    std::vector<uint32_t> remove_node_v;
    CNachbarn *Nachbar;
};

CNetwork::CNetwork( uint32_t num_elements_  ) {
    num_elements = num_elements_;
    Nachbar = new CNachbarn();

    remove_node_v.reserve( num_elements );
}

CNetwork::~CNetwork() {
    delete Nachbar;
}

inline void CNetwork::Validity() {
    #pragma omp parallel for 
    for ( uint32_t i = 0 ; i < num_elements ; i++ ) {
        #pragma omp critical
        remove_node_v.push_back(i);
    }
}

void CNetwork::Clean () {
    #pragma omp parallel for
    for ( uint8_t j = 0 ; j < 2 ; j++ ) {
        nachbar = Nachbar->Get_Next_Neighbor();
        std::cout << "i: " << i << ", neighbor: " << nachbar << std::endl;
    }

    remove_node_v.clear();
}

int main() {
    uint32_t num_elements = 1u << 3;
    uint32_t i            = 0;
    CNetwork Network( num_elements );

    do {
        Network.Validity();
        Network.Clean();
    } while (++i < 2);

    return 0;
}

我想知道

  1. 如果#pragma omp critical 是push_back() 的一个好的解决方案? (是否解决了这个问题?)为每个线程定义自己的 vector 然后组合它们(使用 insert() )会更好吗?还是某种

  2. 在我的原始代码中,我在以下位置遇到运行错误:nachbar = Nachbar->Get_Next_Neighbor( &remove_node_v[i] ); 但在本例中没有。尽管如此,我还是希望 OpenMP 使用 CNachbarn 类作为核心数,因为 CNachbarn 是递归计算,不应受到其他线程的影响。问题是如何聪明地做到这一点? (我认为每次启动 for 循环时都定义 CNachbarn 并不明智,因为我在模拟中调用此函数的次数超过一百万次,时间很重要。

最佳答案

关于你的第一个问题: 您的函数 Validity 是在并行循环中实现低于串行性能的完美方法。但是,您已经给出了正确的答案。您应该为每个线程填充独立的 vector ,然后合并它们。

inline void CNetwork::Validity() {
#pragma omp parallel for 
for ( uint32_t i = 0 ; i < num_elements ; i++ ) {
    #pragma omp critical
    remove_node_v.push_back(i);
}
}

编辑: 可能的补救措施如下所示(如果您需要串行访问您的元素,则需要稍微更改一下循环)

inline void CNetwork::Validity() {
remove_node_v.reserve(num_elements);
#pragma omp parallel 
{
  std::vector<uint32_t> remove_node_v_thread_local;
  uint32_t thread_id=omp_get_thread_num();
  uint32_t n_threads=omp_get_num_threads();
  for ( uint32_t i = thread_id ; i < num_elements ; i+=n_threads ) 
    remove_node_v_thread_local.push_back(i);

  #pragma omp critical
  remove_node_v.insert(remove_node_v.end(), remove_node_v_thread_local.begin(), remove_node_v_thread_local.end()); 
}
}

您的第二个问题可以通过定义一个 CNachbarn 数组来解决,其大小为可能的最大 OMP 线程数,并从每个线程访问数组的不同元素,例如:

CNachbarn* meine_nachbarn=alle_meine_nachbarn[omp_get_thread_num()]

关于c++ - OpenMP 指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6508278/

相关文章:

c++ - 我应该如何在工厂类中存储弱指针列表?

c++ - "Not responding"在 COM 对象执行函数期间

c - 为什么要在 OpenMP 并行 block 内使用 OpenMP Single?

java - 共享库编译,但有 undefined symbol

c++ - 无法在 QtCreator 中使用 GDB 进行调试

c++ - 如何判断函数模板中 T 的赋值运算符是否抛出异常?

c++ - 按值迭代的无序映射

C++-11 用于异构对象的映射

C++返回值

c++ - 全局变量外部声明后的 Threadprivate 指令