Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ OpenMP循环阵列访问中的错误共享_C++_C_Performance_Openmp_False Sharing - Fatal编程技术网

C++ OpenMP循环阵列访问中的错误共享

C++ OpenMP循环阵列访问中的错误共享,c++,c,performance,openmp,false-sharing,C++,C,Performance,Openmp,False Sharing,我想利用OpenMP使我的任务并行 我需要将相同的量减去一个数组的所有元素,然后将结果写入另一个向量。这两个数组都动态分配了malloc,第一个数组由文件中的值填充。每个元素的类型均为uint64\u t #pragma omp parallel for 对于(uint64_t i=0;i

我想利用OpenMP使我的任务并行

我需要将相同的量减去一个数组的所有元素,然后将结果写入另一个向量。这两个数组都动态分配了
malloc
,第一个数组由文件中的值填充。每个元素的类型均为
uint64\u t

#pragma omp parallel for
对于(uint64_t i=0;i
其中,
shift
是我要从
vec
的每个元素中删除的固定值
size
vec
new_-vec
的长度,约为200k

我在Arch Linux上使用
g++-fopenmp
编译代码。我使用的是Intel Core i7-6700HQ,使用8个线程。当我使用OpenMP版本时,运行时间要高出5到6倍。当我运行OpenMP版本时,我可以看到所有的内核都在工作


我认为这可能是由于错误的共享问题造成的,但我找不到它。

您应该调整迭代在线程之间的分配方式。使用
schedule(静态、块大小)
您可以这样做

尝试使用chunk_size值乘以64/sizeof(uint64_t)以避免上述错误共享:

[ cache line n   ][ cache line n+1 ]
[ chuhk 0  ][ chunk 1  ][ chunk 2  ]
实现这样的目标:

[ cache line n   ][ cache line n+1 ][ cache line n+2 ][...]
[ chunk 0                          ][ chunk 1             ]
您还应该以与缓存线对齐的方式分配向量。这样可以确保第一个块和后续块也正确对齐

#define CACHE_LINE_SIZE sysconf(_SC_LEVEL1_DCACHE_LINESIZE) 
uint64_t *vec = aligned_alloc( CACHE_LINE_SIZE/*alignment*/, 200000 * sizeof(uint64_t)/*size*/);

您的问题与所代表的问题非常相似。签出后,您将能够几乎准确地映射代码上的优化。

您的内存带宽有限,因为您尝试进行的并行计算非常简单,基本上只是在内存位置之间移动数据。添加线程将导致内存缓存未命中/抖动和预取失败。这样做的结果是代码运行速度变慢。在现代PC上,大约有1.5个线程会使内存总线饱和。@RichardCritten,这不是真的。高端处理器的带宽上限设计为需要使用多线程来饱和它们。查看我答案上的链接。你如何衡量执行时间?@hristoilev我正在使用
perf stat-r200
来计算执行时间的平均值。你能给出一个计算结果吗?循环的绝对执行时间是多少秒?这是代码中唯一的OpenMP区域吗?它在一个程序运行中执行了多少次?这可能是OpenMP的开销。除此之外,对流的深入讨论包括线程数量的选择及其在核心之间的分布。每个核心有多个线程几乎肯定会减慢速度。设置omp parallel时是否维护simd矢量化?您可以使用
omp for simd
请求多线程和矢量化,omp for simd
是您正在使用的和
omp simd
的组合。检查一下。编译器可能能够在没有任何提示的情况下对其进行矢量化,但如果您有可能指定它,那么最好也使用该子句。GCC的默认循环计划是
static
,因此,在大约25000条缓存线中,有7条缓存线可能在线程之间共享,而在每个线程大约25000条缓存线中,有多达8条缓存线可能被错误共享。问题很可能是使用
clock()
来测量Linux上的执行时间,这里有无数类似的问题。除了维护simd矢量化,使用非临时存储以获得高效的多线程执行也很重要。正如赫里斯托所说,如果你把所有线程的时间加起来,你肯定会看到它随着线程数的增加而增加。