C++ C/C++;Openmp:如果另一个线程同时更新数据,线程是否可能读取损坏的数据?

C++ C/C++;Openmp:如果另一个线程同时更新数据,线程是否可能读取损坏的数据?,c++,parallel-processing,openmp,C++,Parallel Processing,Openmp,假设我们有以下代码模式: 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; } }

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

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;
      }
   }
}
main(){
某些类型的数据;
#pragma-omp并行
对于(i=0;i
我知道我们需要一个关键部分来更新数据,因为同时进行两次更新可能会导致损坏,但是如果一个线程在关键部分内更新数据,而另一个线程试图读取数据,会发生什么情况

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


提前感谢您

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

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

如果只需要一个线程来更新所有数据,请考虑使用
#pragma omp single
子句而不是
#pragma omp critical

关键部分将由所有线程逐个执行。

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

通常,如果更新一个线程中的某些数据,则应防止另一个线程使用或更新该数据

在典型的现代处理器中,在读取输入和存储结果时,单个操作只是原子操作。因此,如果另一个处理器在读取输入和写入结果之间更新相同的数据,则结果是未定义的。但是读/写的数据是一致的(假设对齐正确)。从编译器来看,对齐几乎总是“正确”的,因此该特定数据段应该没有问题。但假设我们有一个由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
----在这里,另一个线程“中断”并开始使用数组进行计算”

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

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


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

在另一个线程写入数据时读取数据永远都不安全。多个读卡器只要锁定所有写卡器就安全。使用openmp可以实现这一点吗?如何锁定writers当写入发生的块在其他地方时?我是OpenMP新手,不幸的是,我还没有找到任何描述这一点的示例。谢谢。请参阅提供的答案Ixanezis。虽然您对线程安全的担忧是有效的(同时读取和写入是UB),但您是否考虑过删除共享状态?这取决于您的sometype是什么,以及您执行的更新操作-拥有数据的私有副本,然后对其运行缩减可能更有效-正是这样做的。这将消除每次迭代中线程之间的争用。共享数据基本上是一个无序的映射其中,值是字符串,键是向量。每个线程将被分配一个键,并且必须读取指定的向量,以检查是否必须进行最终会更改向量的计算。如果必须进行此计算(正如我所说,在读取指定向量后即知道此计算),然后线程进行计算并更新向量。因为整个过程相当混乱,我想发布一个更简单的版本。谢谢你的回答。不过我有几个问题。在这种情况下,安全更新意味着什么?是否意味着如果另一个线程读取数据,数据将永远不会损坏?#pragma omp barrier和#pragma omp single之间的另一个区别是前者允许更多线程同时更新数据(例如,如果您有一个数组,并且希望更新不同的单元格)后者只允许一个线程更新数据?安全更新的意思是,是的,消除了数据损坏的可能性,确保所有线程在数据更新开始之前都已完成读取。那么,您认为
#pragma omp barrier
#pragma omp single
之间的区别是什么意思?这些都是事实出于不同的目的。
barrier
确保所有线程先到达带有
#pragma omp barrier
的行,然后再一起继续。
single
子句只允许一个线程进入该节,其他线程只需跳过它。如果数据更新也可以并行执行,则不同的线程更新dif在不同的单元格中,您既不需要
单个
,也不需要
关键
子句。只需将您的阅读和更新部分拆分为
屏障
即可。非常感谢您的解释,这也让我更清楚了。
10.5
10.6
10.7
10.8
10.9
11.0