omp parallel for:线程无法分配值

时间:2018-10-26 20:54:59

标签: c++ parallel-processing openmp

我有一个由 OpenMP 并行化的for循环。我希望并行线程用myGlobal = set() generated_list = [(1,1), (21,22), (84,6)] myGlobal = myGlobal.union(set(generated_list)) print(myGlobal) generated_list = [(1,1), (21,22), (9,18), (71, 89), (13, 21)] myGlobal = myGlobal.union(set(generated_list)) print(myGlobal) 填充{(21, 22), (1, 1), (84, 6)} {(21, 22), (71, 89), (84, 6), (9, 18), (1, 1), (13, 21)} 的{​​{1}}。每个线程应写入其自己的向量条目。但是有时一项任务失败。这怎么会发生?

std::vector<bool>

向量可能最终看起来像这样: falses

3 个答案:

答案 0 :(得分:0)

问题是由于std::vector<bool>的存储方式所致。它是为提高空间效率而设计的,并且将元素存储在单个位中,而不是字节中。这意味着vec[0]vec[1],... vec[7]的分配都写入内存中的同一字节。由于您有多个线程写入同一个地址(实际上是一个读-修改-写序列),因此存在竞争条件。这可能导致一个线程的写操作被后续线程的写操作“撤消”。

此外,由于主内存的带宽限制,在这样的内存密集型循环中潜在的性能优势并不大。结合每个线程所需的缓存无效化,线程性能可能会低于单线程操作。

在这里完成了基本的基本操作(将内存设置为true)后,只需将其编码为标准的非OMP单线程循环即可。编译器将能够将其优化为合理的性能。

答案 1 :(得分:0)

根据标准,当同时修改同一容器中不同元素中包含的对象的内容时,需要所有标准容器来避免数据争用。 std::vector<bool>除外。 1201ProgramAlarm解释了原因。

std::vector<bool>在许多问题上都是臭名昭著的-最直接的解决方案是改用std::vector<char>。如果这样做的话,您的程序就可以了,尽管您不应期望在这种特定情况下使用OpenMP可以提高性能。

答案 2 :(得分:-1)

我的openmp生锈了,但是想到的是#pragma omp flush [(list)]

  openmp中的

flush指令可用于标识同步点,该点定义为程序执行过程中执行线程需要具有一致的内存视图的点。一致的内存视图具有 2 要求:所有内存读/写操作之前之后,必须在之前执行刷新指令之后。这通常称为内存围栏。第163页,Chandra,Dagum,Kohr,Maydan,McDonald,Menon的openmp中的并行编程; 2001

书中对此进行了更详细的描述,并提到了在任何同步点上未保留在缓冲区/寄存器中的变量,根据您发布的代码,您并没有这样做。

几乎没有代码发布,并且我不知道如何或何时检查vec[i],所以这是我的第一个猜测...然后检查linux操作系统的版本,C编译器,并且涉及到openmp版本...

但是我不希望操作系统升级,编译器升级或openmp版本升级能够更正您遇到的代码

非常类似于在执行标准printf("hello")时执行fflush(stdout)而没有遵循printf("hello\n")时执行标准\n时发生的情况。 {{1}}导致在所有被认为是理所当然的系统上发生固有的刷新。