我正在尝试用std::chrono::steady_clock在Raspberry Pi 4上测试一段DSP代码,但是我得到的结果很奇怪。因为GNU分析工具不适用于Raspberry Pi,所以我不得不用基准来评估代码优化,所以这是一件很重要的事情。
什么会导致基准程序的执行之间性能相差10%,而当相同的测试在同一程序的执行中多次运行时,会保持+/- 1%的一致性?
对于~6秒基准测试的结果变化约为10%.但奇怪的是,对于基准测试的特定执行而言,差异似乎很棘手。每次运行程序时,我都会连续运行三次基准测试,得到的结果大致相同-- +/- 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->稠密),它使用手工优化的neon本质来生成实时音频.执行的大部分(~90%)是使用手工优化的neon本质的矩阵和向量算法。数据占用约13 is (适合在L1 d-缓存中使用)。代码占用是未知的,但可能不适合L1 i-缓存。大部分代码管道漂亮,所以代码可能运行接近L1缓存带宽限制。到目前为止,优化已使实时性从~0.18倍提高到0.093倍。我认为可能还有另外15%的改进,但时机不准确在这一点上受到了阻碍。测试中的代码被执行了三次,占用了0.3x的实时时间,因此进一步的优化实际上是至关重要的。
检查过的东西:
performance,所有CPU在1.8Ghz.上运行。
连接时,模式没有明显的变化。
,
std::chrono::steady_clock::now()的连续调用会产生37到56 and的增量。验证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我不知道你也许能帮上忙的事情:
热节流是否反映在/sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq.中的
技术细节:
GNU/Linux
)
发布于 2022-10-05 17:29:16
最后找出了问题的根源。这个问题似乎是对L1缓存内容的非常温和的竞争,大概是来自某个后台系统过程。
性能计数器表现出与基准测试相同的奇怪行为:每次启动测试程序时,连续运行3次,基准测试结果的方差为1%;但启动到启动的结果相差约10%。
奇怪的是,测试运行之间的性能差异是一致的,并且持续了几秒钟。但是,考虑到L1缓存的干扰有多小,很难猜测有一百多个正在运行的系统进程会干扰基准测试,为什么会出现这种非常不幸的模式,特别是因为它们可以在任何调度程序优先级下运行。
性能计数器测量的结果说明了这个问题:每迭代2,995条指令,平均有30个额外的L1数据缓存丢失,占基准测试结果的10%的方差。令人惊讶的是。
我无法猜测什么样的系统进程会以在18秒内保持一致的速率污染L1数据缓存,但在较大的时间范围内会有所不同。
好消息是:测试中的代码非常接近最优。(一个具有两个实质性乘法和大量向量化ArcTan和Sigmoid函数调用的LSTM单元),它设法使用75%以上的可用缓存内存带宽,并在每个时钟周期发出几乎两个指令。哇哦!
试验数据
测试代码的每次迭代平均性能计数器度量。该程序的每次启动运行三次~6秒基准。
良好的测试程序运行:
CpuClk : 1,694
L1D Access : 1,244
L1D Miss : 6
L1I Miss : 0
Instructions: 2,995
L2 Access : 12
L2 Miss : 0
---
CpuClk : 1,694
L1D Access : 1,244
L1D Miss : 6
L1I Miss : 0
Instructions: 2,995
L2 Access : 12
L2 Miss : 0
---
CpuClk : 1,693
L1D Access : 1,244
L1D Miss : 6
L1I Miss : 0
Instructions: 2,995
L2 Access : 12
L2 Miss : 0糟糕的运行:
CpuClk : 1,797
L1D Access : 1,244
L1D Miss : 37
L1I Miss : 0
Instructions: 2,995
L2 Access : 78
L2 Miss : 0
---
CpuClk : 1,794
L1D Access : 1,244
L1D Miss : 37
L1I Miss : 0
Instructions: 2,995
L2 Access : 78
L2 Miss : 0
---
CpuClk : 1,797
L1D Access : 1,244
L1D Miss : 37
L1I Miss : 0
Instructions: 2,995
L2 Access : 78
L2 Miss : 0https://stackoverflow.com/questions/73910282
复制相似问题