如何使用不同的线程使用openmp安全地更新C结构

时间:2013-12-05 17:55:38

标签: c multithreading parallel-processing thread-safety openmp

我正在写一个randomAnimalGenerator。它是一个多线程的C程序,使用VS2010,用于Windows X64,将用于为动物园随机生成动物。

如何使不同的线程安全地写入全局结构(“zoo”)的成员,而不在动物园结构上实现锁定?该 全局结构的值将始终仅递增(++),而不递减( - )。在下面的代码中,不使用OMP,狮子,老虎和熊每个正确地具有45,000的值。但是使用并行循环时,值不等于45,000。

有没有办法让Openmp将这些写入计划到同一个变量而不会搞乱制作该结构的私有版本?

#define LIONS 1
#define TIGERS 2
#define BEARS 3

// global struct
struct 
{
    int lions;
    int tigers;
    int bears;
} zoo;


void addAnimalsToZoo(void)
{
    int animalType = randomAnimalGenerator();

    if (animalType == LION)
        ++zoo.lions;
    else
    if (animalType == TIGER)
        ++zoo.tigers;
    else
    if (animalType == BEAR)
        ++zoo.bears;
    else
        printf("unknown animal type generated\n");
}


void myZooMaker(void)
{

    #pragma omp parallel for
    for (int i = 0; i < 45000; ++i)
        addAnimalsToZoo();
}

1 个答案:

答案 0 :(得分:1)

如果没有重大的重构,您的程序将无法正常运行。如前所述,该程序展示了规范的数据竞争,多个线程同时更新共享数据结构而没有协调。

你可以:

  1. 从结构中删除变量lionstigersbears(我稍后会解释原因)。
  2. 修改randomAnimalGenerator以适当的概率返回其中一只动物。
  3. 然后,这是近似的,因为我不是一个C程序员,沿着这些行重写

    int lions;
    int tigers;
    int bears;
    
    lions = 0;
    tigers = 0;
    bears = 0;
    
    #pragma omp parallel for default(shared) private(i) reduction(+:lions, +:tigers, +:bears)
    for (int i = 0; i < 45000; ++i)
    {
        int newAnimal;
        newAnimal = randomAnimalGenerator();
        if (newAnimal==LION) ++lions;
        if (newAnimal==TIGER) ++tigers;
        if (newAnimal==BEAR) ++bears;
    }
    

    并且在此末尾变量lionstigersbears应该总和为45000。请注意使用reduction子句和默认可访问性声明为shared。 OpenMP减少不能应用于结构元素或整个结构,这就是我抛弃zoo的原因。

    我不保证代码是正确的,但你应该明白这一点。