【问题标题】:How to use different threads to safely update C structure using openmp如何使用不同的线程使用 openmp 安全地更新 C 结构
【发布时间】:2013-12-05 17:55:38
【问题描述】:

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

我怎样才能使不同的线程都安全地写入全局结构(“动物园”)的成员,而不在动物园结构上实施锁?这 全局结构的值总是只会递增 (++),不会递减 (--)。在下面的代码中,在不使用 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();
}

【问题讨论】:

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

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


【解决方案1】:

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

你可以:

  1. 将变量 lionstigersbears 从结构中剥离出来(稍后我会解释原因)。
  2. 修改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;
}

最后,变量lionstigersbears 的总和应为45000。注意减少子句的使用和默认可访问性声明为shared。 OpenMP 缩减不能应用于结构的元素或整个结构,这就是我将zoo 扔掉的原因。

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

【讨论】:

  • 感谢您的代码,我现在知道如何进行此操作了。现在到那个 randomAnimalGenerator(),就在我完成冷聚变生成器之后。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-22
  • 2021-08-16
  • 1970-01-01
  • 2021-11-08
  • 1970-01-01
  • 2017-04-20
相关资源
最近更新 更多