【发布时间】:2022-10-06 01:29:16
【问题描述】:
我正在尝试使用 std::chrono::steady_clock 在 Raspberry Pi 4 上对一段 DSP 代码进行基准测试,但我得到的结果很奇特。因为 GNU 分析工具不能在 Raspberry Pi 上工作,所以我坚持使用基准测试来评估代码优化,所以这是一件大事。
什么会导致性能在基准程序的执行之间变化 10%,而在程序的同一执行中多次运行相同的测试时保持一致的 +/-1%?
约 6 秒基准测试的结果相差约 10%。但奇怪的是,对于基准测试的特定执行,差异似乎是粘性的。每次运行程序时,我都会连续运行 3 次基准测试,并获得大致相同的结果 +/- 1%。但是当我重新运行程序时,三个基准测试的结果与前一次运行的结果相差 +/- 10%,但新运行的三个结果中的每一个都是 +/- 1%。
例如:
Run 1:
9:21:37. Performance: 0.0912333 x realtime
9:21:42. Performance: 0.0910667 x realtime
9:21:47. Performance: 0.0910667 x realtime
Run 2:
9:20:15. Performance: 0.106667 x realtime
9:20:21. Performance: 0.1062 x realtime
9:20:28. Performance: 0.106117 x realtime
每次运行的结果在这两个极端之间大致随机变化。但这里的特殊之处在于,每次运行程序时执行的三个测试之间的结果一致为 +/- 1%。
我是一位经验丰富的程序员,所以我知道基准测试会有所不同。但是对于我正在尝试做的事情来说,~10% 的差异是行不通的。而且我无法提出一个合理的理论来解释为什么差异会从调用到调用。
被测代码是一种机器学习算法 (LSTM->Dense),使用手动优化的 Neon 内在函数来生成实时音频。执行的大部分(约 90%)是使用手动优化的 neon 内在函数的矩阵和向量算术。数据占用空间约为 13kb(适合 L1 d-cache)。代码足迹未知,但可能不适合 L1 i-cache。大多数代码流水线都很漂亮,因此代码可能会在接近 L1 缓存带宽限制的情况下运行。到目前为止,优化已导致从 ~0.18 x 实时提高到 0.093 x 实时。我认为可能还有大约 15% 的改进可用,但此时时间不准确正在阻碍。被测代码被执行了 3 次,耗时约 0.3 倍,因此实际上需要进一步优化批判的.
已检查的事项:
-
不是 NEON 对齐问题。所有矩阵、矩阵行和向量都是 16 字节对齐的(在调试编译中使用断言检查)。
-
不是 CPU 频率问题。 CPU 缩放调控器已设置为
performance,所有 CPU 都以 1.8Ghz 运行。 -
我不认为这与进程之间的缓存竞争有关。当通过 VNC 连接时,HTOP 表示空闲时 CPU 使用率约为 6%,通过 ssh 连接时约为 0.3%(wifi 请求者)。通过 SSH 连接时,模式不会发生显着变化。
-
我认为它不会因代码运行在哪个 CPU 内核上而有所不同——尽管我只能使用 HTOP 确定代码在特定运行中运行在哪个内核上,这并不完全确定.测试运行似乎偶尔会转移到不同的 CPU 内核,但在大多数情况下,它们似乎在每次执行运行的 3 次测试期间在单个随机选择的内核上运行。
-
我不认为这是热节流。 CPU温度是非常适中的47C。而且我认为 Raspberry PI 4s 在达到 80C 之前不会热油门。
-
矢量操作依赖于 GCC 编译器自动矢量化,已正确注释严格声明,并验证产生了最佳的霓虹矢量化(具有比我用霓虹内在函数产生的更好的指令调度)。
-
不是计时器分辨率问题。对
std::chrono::steady_clock::now()的连续调用会产生 37 到 56ns 之间的增量。 -
时钟选择没有问题。 stable_clock、system_clock 和 high_resolution_clock 都表现出相同的行为。
验证cpu频率:
$ cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
performance
performance
performance
performance
$ cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq
1800000
1800000
1800000
1800000
我不知道的事情,你可能可以帮助:
-
如何在树莓派上实现 std::chrono::steady_clock。它基于CPU时钟计数器吗?任何细节表示赞赏。
-
热节流是否反映在 /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq 中。我认为是,但我不确定。
-
我显然失踪了某物重要的。
技术细节:
- 树莓派 4b 8GB
- Linux raspberrypi 5.15.61-v8+ #1579 SMP PREEMPT Fri Aug 26 11:16:44 BST 2022 aarch64 GNU/Linux
- gcc 版本 10.2.1 20210110 (Debian 10.2.1-6)
- 测试在 catch2 测试框架下运行。
-
您是否检查过数据的对齐方式是否因运行而异。它与缓存或向量大小的对齐方式是否完全不同?
-
@John:我想是的。我的矩阵和向量代码保证矩阵行和向量的 16 字节对齐。 ,并且有一些断言保护矩阵和向量计算,以确保对齐正确。
标签: c++ linux gcc raspberry-pi4 high-resolution-clock