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