1

我一直在使用 odroid-xu3 进行小型实验perf statcpufreq-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% 的差异,而且最高频率的周期数总是更大,所以确实如此看起来不像它更“嘈杂”,它看起来像是在高频发生了其他事情。

4

1 回答 1

0

CPU 周期不仅需要用于计算,还需要用于等待内存中的数据。(是的,GEMM 是 BLAS3,在Roofline 模型规模上具有非常好的算术强度和少量的内存读取/写入,但仍然存在内存访问,并且它们的延迟与 CPU 频率不成线性关系。)

不仅要检查 CPU 周期,还要检查应该更稳定的指令计数器(如果为您的 CPU 实现了这个性能计数器),还要从计数中排除内核模式(它可能每 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) 时序中将相同(或接近),但有一个会影响您的代码周期:内存刷新时序- DRAM 内存仅在短时间内保留数据(数据单元的电荷泄漏) ,例如每 32 微秒 (ms) 或 64 ms 完全刷新一次(这会随着温度的变化而变化,通常有两个值 - 低温和高温)。使用完整的数据库刷新命令,它将在一段时间内无法访问,例如 2% 或 5%(我没有确切的值)。

更改 CPU 频率时,您不会更改刷新频率(数据应始终保持稳定并按照内存芯片数据表的要求刷新)。但是使用 400 MHz CPU,您的计算时间会更长,并且会看到更多刷新;并且 1600 MHz 的计算时间很短,并且会看到更少的刷新。其他影响 - 一些内存请求可能会停止等待刷新结束。

所以,有一些非线性元素具有不同的贡献(一些是负的,另一些是低频率周期的正):

  • CPU 频率和 DRAM 刷新(绝对时间要求)显然不是线性效应;
  • CPU 频率和 Linux 内核周期性任务(它们计划每秒运行几次,而不是每十亿个 cpu 周期)
  • 实际数据访问DRAM 时序( RAS,CAS ) 以 ns 为单位测量(但在内存总线周期中设置和报告),1600 MHz CPU 可能有 100 个周期来从内存中获取第一个字节,但 400 MHz CPU 可能有 60 个周期来获取从内存中获取第一个字节。

最后一个效果在您的结果中看起来最显着 - 低 MHz 的低周期,高 MHz 的高周期。使用高频 CPU 可能会停止更多的周期来等待从内存到预充电/激活行/选择列的几十纳秒。在低频下,相同 ns 的内存延迟将转换为少量的慢 CPU 周期。

于 2017-05-30T05:08:44.687 回答