1

假设我们有以下代码模式:

main(){

   sometype data;

   #pragma omp parallel for
   for(i=0; i< n; i++){

     read data;

     do some calculations that would be used in order to update the data;

     #pragma omp critical{
        update data;
      }
   }
}

我知道我们需要一个临界区来更新数据,因为同时进行两次更新可能会导致损坏,但是如果一个线程在临界区内更新数据而另一个线程正在尝试读取数据会发生什么?

我在网上看到了一些例子,其中阅读被认为是多线程系统中的安全操作,但是我不确定在上述情况下它有多安全。如果它不安全,为了使其安全,应该采取什么适当的措施?

先感谢您

4

2 回答 2

2

当一个线程正在写入(更新)数据而其他线程正在从中读取数据时,您的示例中将出现竞争条件。您所读到的“阅读被认为是安全的”是指仅同时读取相同的数据,而不对其进行修改。

您必须用#pragma omp barriers 包围您的关键部分以确保安全更新。

如果您只需要一个线程来更新所有数据,请考虑使用#pragma omp single子句。#pragma omp critical临界区会被所有线程一一执行。

于 2013-04-05T21:42:14.413 回答
1

这实际上取决于您期望保持一致的内容、运行的架构以及对数据进行的更新类型。

通常,如果您在一个线程中更新某些数据,您应该阻止另一个线程使用或更新该数据。

在典型的现代处理器中,单个操作仅在读取输入和存储结果时是原子的。因此,如果另一个处理器在读取输入和写入结果之间更新相同的数据,则结果是未定义的。但是读取/写入的数据(假设正确对齐)将是一致的。从编译器来看,对齐几乎总是“正确的”,因此该特定数据应该没有问题。但是假设我们有一个包含 10 个值的数组:

10.1
10.2
10.3
10.4
10.5
10.6
10.7
10.8
10.9
11.0   

我们通过向每个值添加 1.0 来“更新”它。

11.1
11.2
11.3
11.4

---- 这里另一个线程“中断”并开始使用数组进行计算“

10.5
10.6
10.7
10.8
10.9
11.0   

现在,当然,计算的第一部分将使用“新”值完成,第二部分使用“旧”值。这可能不是你想要的。

您不会看到 -1.8812121E-64 的读数,因为您的代码读取了“半更新”值或类似的值。

从多个线程中读取是安全的,但是一旦任何线程开始写入,您必须确保另一个线程根本没有读取数据。

于 2013-04-05T21:48:42.897 回答