16

我正在开发大型密集矩阵乘法代码。当我分析代码时,它有时会得到我四核系统峰值失败率的 75% 左右,而其他时候会得到大约 36%。执行代码之间的效率不会改变。它要么从 75% 开始并以该效率继续,要么从 36% 开始并以该效率继续。

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

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

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

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

我当前系统的一些细节: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

编辑: 这些选项也很好用(gemm 是我的可执行文件的名称)

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

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

1 回答 1

3

这不是您问题的直接答案,但可能值得研究:显然,超线程会导致您的缓存 thrash。您是否尝试过检查 valgrind 以查看导致您的问题的问题?在每个线程的堆栈顶部分配一些垃圾可能会有一个快速修复,这样您的线程就不会最终将彼此的缓存行踢出。

看起来您的 CPU 是 4 路组关联的,因此认为跨 8 个线程,您最终可能会得到一些非常不幸的对齐访问,这并不疯狂。如果您的矩阵在缓存大小的倍数上对齐,并且如果您有成对的线程访问区域的缓存倍数分开,则第三个线程的任何偶然读取都足以开始导致冲突未命中。

快速测试——如果您将输入矩阵更改为不是缓存大小的倍数(因此它们不再在边界上对齐)并且您的问题消失了,那么您很有可能正在处理冲突未命中。

于 2014-06-23T14:43:14.243 回答