2

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

我需要对数组的所有元素减去相同的数量并将结果写入另一个向量。两个数组都是动态分配的malloc,第一个数组是用文件中的值填充的。每个元素都是 type 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。

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

我认为这可能是由虚假共享问题引起的,但我找不到。

4

1 回答 1

3

您应该调整迭代在线程之间的拆分方式。有了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 基准测试所代表的非常相似。查看如何优化该基准,您将能够几乎准确地映射代码上的优化。

于 2017-07-11T12:03:51.940 回答