C ++ OpenMP写入共享数组/矢量的特定元素

我有一个长期运行的模拟程序,我打算使用OpenMP来并行加速一些代码。 我是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])但是编译器抱怨“error:expected”)''''token'

如果可能的话,我不会进行缩减,并且尽量避免使用“严格”指令。 那么,我在这里错过了什么吗? 我如何正确保护矢量的某个元素?

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

  • 开发箱:2核CPU,目标平台4-6核
  • 平台:Windows 7,64位
  • MinGW 4.7.2 64位(rubenvb构建)

  • 你只能对变量使用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;
    

    #pragma omp flush(seed_by_age[agents[i]].ageGroup)
    

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


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

    链接地址: http://www.djcxy.com/p/79263.html

    上一篇: C++ OpenMP writing to specific element of a shared array/vector

    下一篇: Data Attribute in OpenMP's task