你能告诉我如何taskset
在 Linux 上使用命令吗?
这是我的处理器的规格:
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Thread(s) per core: 2
Core(s) per socket: 2
Socket(s): 1
NUMA node(s): 1
Vendor ID: AuthenticAMD
CPU family: 21
Model: 16
Model name: AMD A8-4500M APU with Radeon(tm) HD Graphics
Stepping: 1
CPU MHz: 1900.000
CPU max MHz: 1900,0000
CPU min MHz: 1400,0000
BogoMIPS: 3792.85
Virtualization: AMD-V
L1d cache: 16K
L1i cache: 64K
L2 cache: 2048K
NUMA node0 CPU(s): 0-3
当我taskset -c 0-3
在运行 openflow 控制器的命令前面放置该命令时,cbench 测试的结果比我taskset -c 0
在相同命令前面使用命令(用于运行控制器)时更差。
怎么可能?我预期使用 4 个线程时的结果会比仅使用 1 个线程时更好?
答案1
这是一个复杂的主题,取决于许多变量,包括哪个调度程序、CPU 频率驱动程序和调节器、空闲状态延迟、处理器……
尽管已经投入了大量工作来使各种 CPU 频率缩放驱动程序正确响应工作负载,但在某些情况下,结果却出奇地糟糕。这种情况可能发生在多线程或单线程应用程序中。例如,ffmpeg 及其在 CPU 之间轮换的奇怪方式对于 CPU 频率缩放驱动程序来说是一个特别具有挑战性的应用程序。在我的 8 个 CPU 的计算机上,如果我将 phoronix ffmpeg 测试限制为 4 个 CPU 而不是 8 个,我会得到更好的结果。
让我们通过一个简单的单线程示例来研究一下。我有一个简单的 CPU 烧录程序,它将完成一小块工作,完成后,更高级别的脚本将启动另一个进程来执行另一小块工作,依此类推,进行一定数量的循环。如果我在不限制分配的 CPU 数量的情况下运行此作业,则需要 104 秒,但如果我将其限制为一个 CPU,则需要 54 秒。为什么会有如此反直觉和巨大的差异?因为在执行一个工作块期间,CPU 频率调节驱动器/调节器组合确实意识到 CPU 已满载并已开始提高 CPU 频率。然而,与此同时,工作块结束并启动下一个工作块。现在,调度程序实际上还不知道第一个工作块已经结束,因此它认为 CPU 已满载,因此决定将另一个 CPU 分配给新的工作块。第一个 CPU 进入深度空闲状态,不再影响所需的 CPU 工作频率。同时,新 CPU 仅开始根据负载提高其工作频率。这个循环不断进行,结果是 CPU 工作频率永远不会变得很高。
现在,在只为作业分配一个 CPU 的情况下,该 CPU 上永远不会出现负载间隙,最终它会达到最大工作频率,工作块完成得更快。
示例数据(始终是相同的作业,不涉及 IO 等待):
One CPU allocated:
(driver = intel_pstate; governor = powersave):
real 0m54.830s
user 0m48.112s
sys 0m0.272s
No restriction on CPU allocation (i.e. all 8 are available):
(driver = intel_pstate; governor = powersave):
real 1m54.938s
user 1m47.948s
sys 0m0.336s
No restriction on CPU allocation (i.e. all 8 are available):
(driver = intel_pstate; governor = performance):
real 0m52.851s
user 0m48.044s
sys 0m0.212s
那么为什么不一直使用性能调节器呢?因为,一般来说,这会不必要地浪费大量能源。只有这些特殊的奇怪用例才最好只使用性能调节器。