我正在开发大型密集矩阵乘法代码。当我对代码进行分析时,它有时会获得我的四个核心系统中大约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
答案 0 :(得分:3)
这不是您问题的直接答案,但可能值得查看:apparently, hyperthreading can cause your cache to thrash。您是否尝试过检查valgrind以查看导致问题的问题?在每个线程的堆栈顶部分配一些垃圾可能会有一个快速的解决办法,这样你的线程就不会最终踢掉每个其他缓存线。
It looks like your CPU is 4-way set associative因此,在8个主题中,您最终可能会遇到一些非常不幸的对齐访问,这并不是疯狂的。如果你的矩阵对齐的是缓存大小的倍数,并且如果你有多个线程访问区域的缓存多次,那么第三个线程的任何偶然读取都足以开始导致冲突未命中。
进行快速测试 - 如果您将输入矩阵更改为不是缓存大小的倍数(因此它们不再在边界上对齐)并且您的问题消失,那么& #39;你很有可能处理冲突失误。