gcc - 由于 OpenMP : how to bind threads to cores 的超线程导致性能不佳

标签 gcc openmp scheduler hyperthreading

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

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

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

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

如何在没有线程迁移的情况下将线程绑定(bind)到每个内核,这样我就不必在 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

编辑:
These options也很好用(gemm 是我的可执行文件的名称)
numactl -C 0,1,2,3 ./gemm


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

最佳答案

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

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

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

关于gcc - 由于 OpenMP : how to bind threads to cores 的超线程导致性能不佳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24368576/

相关文章:

database - 如何有效地存储计划日期?

Heroku 时钟进程 : how to ensure jobs weren't skipped?

c++ - 概念没有按预期解决歧义。代码示例有什么问题?

c++ - 未定义对 `__stack_chk_fail' 的引用

c++ - 如何向编译器指示指针参数已对齐?

根据条件选择 OpenMP pragma

c++ - 如何通过递归使用 OpenMP

c++ - Portaudio 不会使用 macports GCC 4.8 进行编译(-arch 命令选项无法识别/错误的寄存器名称错误)

multithreading - Prange 减慢 Cython 循环速度

mysql - 在 MySQL 中安排事件