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

标签 c++ stl openmp stdvector

我有一个长时间运行的模拟程序,我计划使用 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)中,我使用了>

我不是在做缩减,如果可能的话,我尽量避免使用“关键”指令。那么,我在这里遗漏了什么吗?如何正确保护 vector 的特定元素?

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

  • 开发盒: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],从而使所有其他内核中的同一缓存行无效。访问其他 vector 元素也会导致相互缓存失效,但假设代理或多或少地平均分布在年龄组中,它不会像 vector 中第一个元素的情况那样严重。因此,我建议您执行以下操作:

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;

关于C++ OpenMP 写入共享数组/vector 的特定元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17359104/

相关文章:

C++如何将 map 迭代器仅公开给 map 的值

c++ - C++ 标准库必须支持对 friend 是谁挑剔的类吗?

C++ 并行编程函数调用

c++ - C++ 中的 PID Controller 和传递函数

c++ - DirectShow 源过滤器

c++ - 如何从文件中读取文本行并将它们放入数组中

java - JNI : How to handle the creation/removal of wrapped C++ object

iostream 的 C++ 包装器类,使用流修饰符,如 std::endl 和 operator<<

c - 并行程序的时间计算

c++ - 在并行 omp 循环中同时写入同一内​​存