如何在C ++程序中以拓扑考虑实现多核HT的亲和性?

时间:2011-10-18 17:54:50

标签: c++ multicore affinity hyperthreading

我正在开发一些具有可变数量线程的C ++多核程序,我想知道如何设置一个合适的(实际上是“最好的”)亲和力。我使用Boost-threads,所以我可以调用get_hardware_concurrency()来了解有多少逻辑内核。到目前为止,我写了一个映射“第n个线程到第n个逻辑核心”,但由于多插槽处理器和超线程,它并不是最聪明的事情。我的程序总是像SIMD一样,所以线程之间没有任何共享,如果是HT计算机,我想以我能想象的最聪明的方式将线程绑定到逻辑核心:第一个物理上的第一个逻辑核心,第2个物理上的第1个逻辑,...,第1个物理上的第1个逻辑,第1个物理上的第2个逻辑,依此类推。

我发现了很多内容,讨论了如何发现HT是否启用(CPUID)以及如何确定逻辑和物理内核PER包。我知道我必须处理一些汇编代码,它并没有吓到我,但我真的找不到如何知道有关逻辑内核,物理内核和软件包的完整信息以及操作系统如何处理所有这些信息。

我能够最简洁:我怎么知道OS(Windows和Linux)引用的线程的确切位置(物理核心和包)为第N个?

4 个答案:

答案 0 :(得分:5)

这是一个代码片段,它将为您提供Linux上的CPU拓扑。

#!/bin/bash
function filter {
  cat /proc/cpuinfo | grep -E "$1.*: [0-9]*" | sed -e 's/^.*: //g'
}

CPU_ID=`filter processor`
SOCKET_ID=(`filter 'physical id'`)
CORE_ID=(`filter 'core id'`)

for cpu_id in $CPU_ID; do
    echo "cpu $cpu_id: socket${SOCKET_ID[$cpu_id]}_core${CORE_ID[$cpu_id]}"
done

如果我在启用了HT的核心i7上运行它,我会得到以下输出:

cpu 0: socket0_core0
cpu 1: socket0_core1
cpu 2: socket0_core2
cpu 3: socket0_core3
cpu 4: socket0_core0
cpu 5: socket0_core1
cpu 6: socket0_core2
cpu 7: socket0_core3

在这里你可以看到cpu 0和4在同一个核心上,即核心0上的HT线程。

将此与sched_setaffinity或pthread_setaffinity_np(3)结合使用,可以将进程映射到一组CPU。您也可以使用taskset(1)而不使用任何代码行。

答案 1 :(得分:3)

对于Windows:GetLogicalProcessorInformationSetThreadAffinityMask

还有GetCurrentProcessorNumber(),但是当你没有将它们固定到特定的CPU时,操作系统经常交换线程,所以这对你自己的目的没有帮助。

答案 2 :(得分:1)

在linux上,请查看man pages for sched_setaffinity

答案 3 :(得分:1)

LIKWID工具套件可以方便地处理多核环境中的拓扑和亲和性问题。它包含用于确定拓扑,将线程固定到内核以及测量硬件性能指标的工具:

http://code.google.com/p/likwid

只要代码中的线程机制基于pthread并且应用程序是动态链接的,likwid-pin就可以将线程绑定到资源而无需更改源代码。