OpenMP循环数组访问中的虚假共享

时间:2017-07-11 10:56:52

标签: c++ c performance openmp false-sharing

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

我需要将相同的数量减去数组的所有元素,并将结果写入另一个向量中。两个数组都使用malloc动态分配,第一个数组填充文件中的值。每个元素都是uint64_t类型。

#pragma omp parallel for
for (uint64_t i = 0; i < size; ++i) {
    new_vec[i] = vec[i] - shift;
}

shift是我要从vec的每个元素中删除的固定值。 sizevecnew_vec的长度,大约为200k。

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

我认为这可能是由虚假分享问题引起的,但我无法找到它。

1 个答案:

答案 0 :(得分:2)

您应该调整线程之间的迭代分配方式。使用schedule(static,chunk_size),您就可以这样做。

尝试使用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*/);

您的问题与Stream Triad benchmark所代表的问题非常相似。查看how to optimize that benchmark,您将能够几乎完全映射代码中的优化。