由于OpenMP的超线程导致性能不佳:如何将线程绑定到核心

时间:2014-06-23 14:31:17

标签: gcc openmp scheduler hyperthreading

我正在开发大型密集矩阵乘法代码。当我对代码进行分析时,它有时会获得我的四个核心系统中大约75%的峰值触发器,而其他时间则大约为36%。在执行代码之间效率不会改变。它要么从75%开始并继续保持这种效率,要么从36%开始并继续保持这种效率。

我已将问题追溯到超线程以及我将线程数设置为4而不是默认值8的事实。 当我在BIOS中禁用超线程时,我的效率始终保持在75%左右(或者至少我从未看到大幅下降到36%)。

在我调用任何并行代码之前,我会omp_set_num_threads(4)。在运行代码之前,我还尝试了export OMP_NUM_THREADS=4,但它似乎是等效的。

我不想在BIOS中禁用超线程。我想我需要将四个线程绑定到四个核心。我已经测试了GOMP_CPU_AFFINITY的一些不同情况,但到目前为止,我仍然存在效率为36%的问题。 超线程和核心的映射是什么?例如线程0和线程1对应同一个核心和线程2,线程3对应另一个核心吗?

如何在没有线程迁移的情况下将线程绑定到每个核心,这样我就不必在BIOS中禁用超线程了?也许我需要考虑使用{{3 }}?

我当前系统的一些细节:Linux内核3.13,GCC 4.8,Intel Xeon E5-1620(四个物理内核,八个超线程)。

编辑: 到目前为止,这似乎运作良好

export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7"

export GOMP_CPU_AFFINITY="0-7"

编辑: 这似乎也运作良好

export OMP_PROC_BIND=true

编辑: sched_setaffinity也运行良好(gemm是我的可执行文件的名称)

numactl -C 0,1,2,3 ./gemm

taskset -c 0,1,2,3 ./gemm

1 个答案:

答案 0 :(得分:3)

这不是您问题的直接答案,但可能值得查看:apparently, hyperthreading can cause your cache to thrash。您是否尝试过检查valgrind以查看导致问题的问题?在每个线程的堆栈顶部分配一些垃圾可能会有一个快速的解决办法,这样你的线程就不会最终踢掉每个其他缓存线。

It looks like your CPU is 4-way set associative因此,在8个主题中,您最终可能会遇到一些非常不幸的对齐访问,这并不是疯狂的。如果你的矩阵对齐的是缓存大小的倍数,并且如果你有多个线程访问区域的缓存多次,那么第三个线程的任何偶然读取都足以开始导致冲突未命中。

进行快速测试 - 如果您将输入矩阵更改为不是缓存大小的倍数(因此它们不再在边界上对齐)并且您的问题消失,那么& #39;你很有可能处理冲突失误。