我一直在odroid-xu3上使用perf stat
和cpufreq-set
进行小型实验,这是一个带有Exynos芯片的嵌入式设备(A7和A15 ARM内核的异构处理器)。我使用BLAS lvl3基准测试来运行我的实验,并且我已经使用taskset
实用程序将任务固定到A15核心。我还仔细检查过它是一个单线程实现。
希望在高频或低频运行时循环次数应该相同,但我可以看到一个小的变化,例如分别在400MHz,1000MHz和1600MHz下运行GEMM内核(矩阵乘法,100次运行)结果如下:
7166620830 cycles
17.923790714 seconds time elapsed
7235173436 cycles
7.237463382 seconds time elapsed
7428037080 cycles
4.643897351 seconds time elapsed
你可以看到,即使持续时间与频率并不是真正的线性关系(至少与测量的周期数一致......)。一个假设是任务有点内存限制但我在单精度实现方面有类似的结果......你知道这可能是什么原因吗?
编辑:矩阵是400个样本大,我使用环境变量OPENBLAS_LOOP(openblas基准测试)来运行它100次。我试图避免其他应用程序运行,我不知道有0%的负载,但它是关闭的。你建议我停止一些特别的东西吗?由于它已经是超过100次实验的平均值,因此在相同频率下的变化非常低(<0.1%),并且当我改变频率时存在大约4%的差异,并且对于最高频率它总是更大的周期数,因此它它看起来不像是“嘈杂”,看起来像是在高频下会发生其他事情。
答案 0 :(得分:0)
CPU周期不仅需要计算,还需要从内存中等待数据。 (是的,GEMM是BLAS3,Roofline model scale具有非常好的算术强度和低内存读/写量,但仍有内存访问,并且它们的延迟与CPU频率不成线性。)
尝试不仅检查CPU周期,还要检查应该更稳定的指令计数器(如果为CPU实现此perf计数器),还要排除内核模式(它可能每隔100 Hz或300 Hz就像调度程序那样有一些周期性任务)从:u
后缀计数:
perf stat -e cycles:u,instructions:u,task-clock:u ./program
(还尝试查找为您的内核实现的一些缓存未命中事件或内存访问事件,检查核心文档中的原始编码并使用-e rHHHH
找到十六进制代码)
当您更改CPU时钟频率时,您可能(或可能不)也会影响内存控制器/内存总线频率(这特定于您的SoC和引导配置)。 DRAM内存(可能是“exynos 5422”SoC中的LPDDR3)有许多时序,这些时序是以内存总线频率计算的,但实际上它们来自实际内存数据库频率和延迟。
大多数时序在绝对(ns)时序中都是相同的(或接近),但有一个时钟会影响你的代码周期:memory refresh timing - DRAM内存仅在很短的时间内保留数据(充电)从数据单元泄漏),例如每32微秒(ms)或64 ms完全刷新(这与高温一起变化,通常有两个值 - 低温和高温)。 使用完整数据库刷新命令, time 的某些部分将无法访问,例如2%或5%(我没有确切的值)。
更改CPU频率时,不会更改刷新频率(数据应始终稳定并按内存芯片数据表的要求刷新)。但是使用400 MHz CPU,您的计算时间会更长,并且会看到更多刷新;并且1600 MHz的计算时间很短,刷新次数也会减少。其他影响 - 某些内存请求可能会停止等待刷新结束。
因此,有一些非线性元素具有不同的贡献(一些是负的,另一些是低频率的循环):
最后一个效果在您的结果中看起来最显着 - 低MHz的低周期,高MHz的高周期。对于高频CPU,可能会停止更多周期,从存储器等待几十纳秒到预充电/激活行/选择列。使用低频率,相同ns的内存延迟将转换为低速CPU周期。