我想利用OpenMP使我的任务并行。
我需要将相同的数量减去数组的所有元素,并将结果写入另一个向量中。两个数组都使用malloc
动态分配,第一个数组填充文件中的值。每个元素都是uint64_t
类型。
#pragma omp parallel for
for (uint64_t i = 0; i < size; ++i) {
new_vec[i] = vec[i] - shift;
}
shift
是我要从vec
的每个元素中删除的固定值。 size
是vec
和new_vec
的长度,大约为200k。
我在Arch Linux上使用g++ -fopenmp
编译代码。我使用的是英特尔酷睿i7-6700HQ,我使用8个线程。使用OpenMP版本时,运行时间高出5到6倍。我可以看到,当我运行OpenMP版本时,所有核心都在工作。
我认为这可能是由虚假分享问题引起的,但我无法找到它。
答案 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,您将能够几乎完全映射代码中的优化。