如何在 Linux X86_64 中测试英特尔超线程的性能
How to test performance of Intel HyperThreading in Linux X86_64
我正在尝试找出 Intel HT 在 Linux X86_64 中对性能的影响。
是否有众所周知的工具或现成的代码来进行此测试?
如果没有,我的测试计划如下,
场景 1:
线程 1:高优先级,运行 在 CoreN 线程 0 中,休眠 1 秒。
线程 2:中优先级,运行 在 CoreN 线程 0 中,增加一个整数计数器。
线程 3 和 4 与线程 1 和 2 是相同的线程,但将 运行 在 CoreN 线程 1 中。
1 秒后,线程 1 和 3 将分别打印线程 2 和 4 增加的计数器。
场景 2:
然后将线程3和4移动到不同的核心,运行 1秒再次检查计数器。
预期整数相加在场景 2 中的性能优于场景 1。
我的测试计划检查 Intel HT 性能影响是否合理?
如果您的工作负载本质上是固定数量的线程,且多于物理内核的数量,那么您的测试方式可能有意义。因此,您需要将竞争同一核心(上下文切换)的 2 个线程与共享同一物理核心的逻辑核心的两个线程进行比较。
这不正常,大多数多线程工作负载可以将自己划分为可变数量的线程,因此您可以选择与您的内核相匹配的线程数。
通常您会使用 N 个线程执行类似 x265
的操作,其中 N 是您拥有的物理核心数。 (例如 ffmpeg -preset slow -c:v libx265 -x265-params pools=4
表示一个 4 核的 NUMA 池)。理想情况下,在启动时禁用 HT,或者让每个 HT 对中的一个核心脱机,因此 Linux 永远不会将两个线程调度到同一个物理核心上。
然后使用 2N 个线程,让所有逻辑核心保持忙碌,看看扩展到更多线程是否有助于或损害您的工作负载的吞吐量。 (隐藏停顿与通过竞争高速缓存占用空间/内存带宽来创建更多停顿。)
在我的测试中,无需 打扰离线核心,在具有双通道 DDR4-2666、1080p x265 的 i7-6700k Skylake 上,只有 pools=4 与 pools=8在 pools=8 与 pools=4 的情况下,以 -preset 较慢的速度进行编码可提高约 20%。
但是 8 个线程使用明显更多的内存带宽(根据 intel_gpu_top -l
显示集成内存控制器 read/write 带宽),并使交互使用明显更加缓慢。 (要么是因为对 L3 缓存的额外竞争,要么是因为没有空闲的逻辑内核来安排任务,或者两者兼而有之。)
或者,如果您想 micro 基准测试 运行 两个简单的循环长时间相互对抗(而不是像 x265 这样的真实程序的指令组合或 BLAS SGEMM,或 make -j8
编译,或其他),然后是的,您将编写简单的循环并 运行 它们在 perf stat
下以查看现实是否与您可能从具有前端与后端(尤其是不同的特定端口)与延迟瓶颈的代码。
请参阅 https://whosebug.com/tags/x86/info and especially https://agner.org/optimize/ - Agner 的微体系结构指南提供了有关 CPU 核心的不同部分如何在超线程之间共享的相当详细的信息。 (例如,ROB 和存储缓冲区是静态分区的,缓存和执行单元是竞争共享的,前端交替,除非一个线程被停顿。)
我正在尝试找出 Intel HT 在 Linux X86_64 中对性能的影响。
是否有众所周知的工具或现成的代码来进行此测试?
如果没有,我的测试计划如下,
场景 1:
线程 1:高优先级,运行 在 CoreN 线程 0 中,休眠 1 秒。
线程 2:中优先级,运行 在 CoreN 线程 0 中,增加一个整数计数器。
线程 3 和 4 与线程 1 和 2 是相同的线程,但将 运行 在 CoreN 线程 1 中。
1 秒后,线程 1 和 3 将分别打印线程 2 和 4 增加的计数器。
场景 2:
然后将线程3和4移动到不同的核心,运行 1秒再次检查计数器。
预期整数相加在场景 2 中的性能优于场景 1。
我的测试计划检查 Intel HT 性能影响是否合理?
如果您的工作负载本质上是固定数量的线程,且多于物理内核的数量,那么您的测试方式可能有意义。因此,您需要将竞争同一核心(上下文切换)的 2 个线程与共享同一物理核心的逻辑核心的两个线程进行比较。
这不正常,大多数多线程工作负载可以将自己划分为可变数量的线程,因此您可以选择与您的内核相匹配的线程数。
通常您会使用 N 个线程执行类似 x265
的操作,其中 N 是您拥有的物理核心数。 (例如 ffmpeg -preset slow -c:v libx265 -x265-params pools=4
表示一个 4 核的 NUMA 池)。理想情况下,在启动时禁用 HT,或者让每个 HT 对中的一个核心脱机,因此 Linux 永远不会将两个线程调度到同一个物理核心上。
然后使用 2N 个线程,让所有逻辑核心保持忙碌,看看扩展到更多线程是否有助于或损害您的工作负载的吞吐量。 (隐藏停顿与通过竞争高速缓存占用空间/内存带宽来创建更多停顿。)
在我的测试中,无需 打扰离线核心,在具有双通道 DDR4-2666、1080p x265 的 i7-6700k Skylake 上,只有 pools=4 与 pools=8在 pools=8 与 pools=4 的情况下,以 -preset 较慢的速度进行编码可提高约 20%。
但是 8 个线程使用明显更多的内存带宽(根据 intel_gpu_top -l
显示集成内存控制器 read/write 带宽),并使交互使用明显更加缓慢。 (要么是因为对 L3 缓存的额外竞争,要么是因为没有空闲的逻辑内核来安排任务,或者两者兼而有之。)
或者,如果您想 micro 基准测试 运行 两个简单的循环长时间相互对抗(而不是像 x265 这样的真实程序的指令组合或 BLAS SGEMM,或 make -j8
编译,或其他),然后是的,您将编写简单的循环并 运行 它们在 perf stat
下以查看现实是否与您可能从具有前端与后端(尤其是不同的特定端口)与延迟瓶颈的代码。
请参阅 https://whosebug.com/tags/x86/info and especially https://agner.org/optimize/ - Agner 的微体系结构指南提供了有关 CPU 核心的不同部分如何在超线程之间共享的相当详细的信息。 (例如,ROB 和存储缓冲区是静态分区的,缓存和执行单元是竞争共享的,前端交替,除非一个线程被停顿。)