2013-06-28 68 views
2

我有一个长时间运行的模拟程序,我计划使用OpenMP来并行加速一些代码。我是OpenMP的新手,并有以下问题。C++ OpenMP写入共享数组/矢量的特定元素

鉴于仿真是一个随机之一,我具有以下数据结构和我需要捕获接种剂[编辑:编辑一些代码]:的年龄特异性计数

class CAgent { 
    int ageGroup; 
    bool isSeed; 
    /* some other stuff */ 
}; 

class Simulator { 
    std::vector<int> seed_by_age; 
    std::vector<CAgent> agents; 
    void initEnv(); 
    /* some other stuff */ 
}; 

void Simulator::initEnv() { 
    std::fill(seed_by_age.begin(), seed_by_age.end(), 0); 

    #pragma omp parallel 
    { 
      #pragma omp for 
      for (size_t i = 0; i < agents.size(); i++) 
      { 
       agents[i].setup(); // (a) 
       if (someRandomCondition()) 
       { 
        agents[i].isSeed = true; 
        /* (b) */ 
        seed_by_age[0]++; // index = 0 -> overall 
        seed_by_age[ agents[i].ageGroup - 1 ]++; 
       } 
      } 
    } // end #parallel 
} // end Simulator::initEnv() 

作为可变seed_by_age是在线程中共享,我知道我必须妥善保护它。所以在(b)中,我使用了#pragma omp flush(seed_by_age[agents[i].ageGroup])但是编译器在'['token'之前抱怨“错误:预计')'

我并没有做减法,如果可能的话我尽量避免使用'critical'指令。那么,我在这里错过了什么吗?我如何正确保护矢量的某个元素?

非常感谢,我欣赏任何建议。

  • 发展盒:2核心CPU,目标平台4-6芯
  • 平台:Windows 7中,64位
  • MinGW的4.7.2 64位(rubenvb构建)

回答

2

您只能使用flush变量,而不是数组的元素,并且绝对不能与C++容器类的元素一起使用。 std::vector的索引运算符会导致调用operator[],这是一种内联函数,但仍是函数。

因为你的情况std::vector::operator[]返回一个简单的标量类型的引用,你可以使用atomic update结构来保护更新:

#pragma omp atomic update 
seed_by_age[0]++; // index = 0 -> overall 
#pragma omp atomic update 
seed_by_age[ agents[i].ageGroup - 1 ]++; 

至于没有使用还原,每个线程倒是seed_by_age[0]当条件内该循环被满足,从而使所有其他核心中的相同缓存线无效。访问其他向量元素也会导致相互缓存失效,但假设代理程序在年龄组之间或多或少地平均分配,则不会像向量中的第一个元素那样严重。因此,我建议你做类似的事情:

int total_seed_by_age = 0; 

#pragma omp parallel for schedule(static) reduction(+:total_seed_by_age) 
for (size_t i = 0; i < agents.size(); i++) 
{ 
    agents[i].setup(); // (a) 
    if (someRandomCondition()) 
    { 
     agents[i].isSeed = true; 
     /* (b) */ 
     total_seed_by_age++; 
     #pragma omp atomic update 
     seed_by_age[ agents[i].ageGroup - 1 ]++; 
    } 
} 

seed_by_age[0] = total_seed_by_age; 
1
#pragma omp flush(seed_by_age[agents[i]].ageGroup) 

尝试关闭所有的括号,它将修复编译器错误。

+0

ageGroup不是seed_by_age(它是一个向量)的成员, –

0

恐怕,您的#pragma omp flush语句不足以保护您的数据并防止出现竞争情况。 如果someRandomCondition()在只有非常有限的情况下为true,则可以使用临界区来更新矢量而不会失去太多速度。另外,如果你的向量seed_by_age的大小不是太大(我认为),比离开并行块之前你合并的每个线程有一个私有版本的矢量可能是有效的。