2011-06-28 60 views
1

我想在我的程序中使用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. 如果OMP的#pragma关键是push_back()好的解决办法? (解决这个问题吗?)为每个线程定义自己的向量然后将它们合并(使用insert())会更好吗?或某种lock

  2. 在我原来的代码中,我得到一个运行错误:nachbar = Nachbar->Get_Next_Neighbor(&remove_node_v[i]);但在这个例子中没有。虚空越少,我想OpenMP使用核心数CNachbarn类,因为CNachbarn是递归计算,不应该受其他线程的影响。问题是如何聪明地做到这一点? (我不认为这是明智的,每次我开始for循环,因为我调用这个函数多万元时代在我的模拟和时间是非常重要的定义CNachbarn

+3

请发布一个*最小示例*,说明您的问题。你在这里把所有的工作都交给我们。 –

+0

1.你真的需要一个载体吗?看起来你可以使用简单的数组来消除关键部分,如果有可能向memset中引入某种“无效”值。然后,您可以扫描该数组并将所有非无效值推送至矢量。根据任务大小的不同,它可以给你一个很大的提升或者根本没有提升,但是我相信你不会使用OMP进行非耗时的循环。 –

+0

@Konrad,我上传了一个工作示例 – Eagle

回答

4

关于你的第一个问题: 你功能有效性是实现以下串行性能的并行循环一个完美的方式。然而,你已经给出了正确的答案应填写独立矢量为每个线程,之后将它们合并

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); 
} 
} 

编辑:。一可能的补救措施可能看起来像这样(如果你r equire到元素串行访问,你需要改变回路中的位)

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()); 
} 
} 

你的第二个问题可以解决通过定义的OMP的最大线程数可能规模,并获得不同的CNachbarn数组从每个线程的阵列元素,如:

CNachbarn* meine_nachbarn=alle_meine_nachbarn[omp_get_thread_num()] 
+0

我想在每个线程中使用带有push_back的本地std :: vector,然后将所有本地std :: vectors组合到remove_node_v std :: vector中。我怎么能这样做? – Eagle

+0

我编辑了答案以提供可能的解决方案 – FFox