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

如何使用不同的线程使用openmp安全地更新C结构,c,multithreading,parallel-processing,thread-safety,openmp,C,Multithreading,Parallel Processing,Thread Safety,Openmp,我正在写一本随机动画生成器。这是一个多线程C程序,使用VS2010,适用于Windows X64,将用于为动物园随机生成动物 如何使不同的线程都安全地写入全局结构(“zoo”)的成员,而不在zoo结构上实现锁?这个 全局结构的值将始终只递增(++),而不递减(--)。在下面的代码中,如果不使用OMP,狮子、老虎和熊的值都正确地为45000。但使用并行循环时,值不等于45000 有没有一种方法可以让Openmp将这些写操作安排到同一个变量,而不影响结构的私有版本 #define LIONS 1 #

我正在写一本随机动画生成器。这是一个多线程C程序,使用VS2010,适用于Windows X64,将用于为动物园随机生成动物

如何使不同的线程都安全地写入全局结构(“zoo”)的成员,而不在zoo结构上实现锁?这个 全局结构的值将始终只递增(++),而不递减(--)。在下面的代码中,如果不使用OMP,狮子、老虎和熊的值都正确地为45000。但使用并行循环时,值不等于45000

有没有一种方法可以让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
#定义老虎2
#定义熊3
//全局结构
结构
{
国际狮子会;
国际老虎;
内特熊;
}动物园;
void添加动物动物园(void)
{
int animalType=randomAnimalGenerator();
如果(animalType==LION)
++动物园;狮子;
其他的
if(animalType==老虎)
++动物园;老虎;
其他的
if(animalType==熊)
++动物园熊;
其他的
printf(“生成的未知动物类型”);
}
void myZooMaker(void)
{
#pragma-omp并行
对于(int i=0;i<45000;++i)
添加animalstozoo();
}

如果不进行重大重构,您的程序将无法正常工作。如前所述,该程序表现出一种规范的数据竞争,即多个线程同时更新一个共享数据结构,而无需协调

你可以:

  • 将变量
    lions
    tigers
    bears
    从结构中去掉(我稍后会解释原因)
  • 修改
    randomAnimalGenerator
    以适当的概率返回其中一只动物
  • 然后,这是一个近似值,因为我不是一个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;
    }
    
    int;
    国际老虎;
    内特熊;
    狮子=0;
    老虎=0;
    熊=0;
    #pragma omp parallel用于默认(共享)私有(i)缩减(+:狮子、+:老虎、+:熊)
    对于(int i=0;i<45000;++i)
    {
    int新动物;
    newAnimal=randomAnimalGenerator();
    如果(新动物==狮子)+狮子;
    如果(新动物==老虎)+老虎;
    如果(新动物==熊)+熊;
    }
    
    最后,变量
    狮子
    老虎
    的总和应为
    45000
    。注意reduce子句的使用和默认可访问性声明为
    shared
    。OpenMP缩减不能应用于结构的元素或结构作为一个整体,这就是我丢弃
    zoo
    的原因


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

    如果不进行重大重构,你的程序将无法正常工作。如前所述,该程序表现出一种规范的数据竞争,即多个线程同时更新一个共享数据结构,而无需协调

    你可以:

  • 将变量
    lions
    tigers
    bears
    从结构中去掉(我稍后会解释原因)
  • 修改
    randomAnimalGenerator
    以适当的概率返回其中一只动物
  • 然后,这是一个近似值,因为我不是一个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;
    }
    
    int;
    国际老虎;
    内特熊;
    狮子=0;
    老虎=0;
    熊=0;
    #pragma omp parallel用于默认(共享)私有(i)缩减(+:狮子、+:老虎、+:熊)
    对于(int i=0;i<45000;++i)
    {
    int新动物;
    newAnimal=randomAnimalGenerator();
    如果(新动物==狮子)+狮子;
    如果(新动物==老虎)+老虎;
    如果(新动物==熊)+熊;
    }
    
    最后,变量
    狮子
    老虎
    的总和应为
    45000
    。注意reduce子句的使用和默认可访问性声明为
    shared
    。OpenMP缩减不能应用于结构的元素或结构作为一个整体,这就是我丢弃
    zoo
    的原因


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

    那么我可以假设OpenMp会正确地安排事情,这样,如果两个或更多线程都在同一时刻尝试运行++zoo.lions,那么就不会有数据争用等问题了?我在文档中找不到任何与此相关的内容。让每个线程都写入相同的共享数据结构将是低效的。相反,您应该让每个线程写入数据结构的私有版本。然后在关键部分合并每个私有版本。这将是高效和安全的。实际上,我刚刚能够编写一个不同的案例,并发现这不是线程安全的。我已经编辑了我的qeustion。这应该是一个完整的c*******k,因为
    ++
    不能保证是原子的,而且您将有多个线程同时运行
    zoo
    。这几乎就是数据竞赛的定义。@HighPerformanceMark,是的,你是正确的,尽管我不确定什么是c*******k。我已经编辑了我的问题,但看起来我无法在并行循环中轻松实现这一点……或者至少这超出了我糟糕的编程技能……因此,我可以假设OpenMp将正确地安排事情,这样,如果两个或更多线程同时尝试运行++zoo.lions,数据竞赛就不会出现问题,等我在文档中找不到任何与此相关的内容。让每个线程都写入相同的共享数据结构将是低效的。相反,您应该让每个线程写入数据结构的私有版本。然后在关键部分合并每个私有版本。这将是高效和安全的。实际上,我刚刚能够编写一个不同的案例,并发现这不是线程安全的。我已经编辑了我的教程。那应该是一个完整的c