【问题标题】:Inconsistent values of ARM PMU cycles counterARM PMU 周期计数器的值不一致
【发布时间】:2020-02-23 10:44:00
【问题描述】:

我正在尝试使用 pmu 在 linux 内核中测量我的代码的性能。 首先,我想测试 pmu,因此在内核中创建了简单的耦合操作循环。我将它置于禁用中断的自旋锁下,因此我的测试代码不能被抢占。然后我打印了循环计数器来检查这个循环需要多少 CPU 周期。但我在每次打印时看到的值非常不同:100、500、1000、200、... 我的问题是:为什么我每次都看到如此不同的价值观? PS:与循环计数器相反,pmu 的指令计数器是稳定的,我每次看到的值都相同。 我也尝试使用 arm 计时器,但它也显示了与 pmu 的周期计数器类似的不同值。 以下是我使用 ARM 计时器测量性能的方法:

unsigned long long ticks_start, ticks_end;
int i = 0, j;
unsigned long flags;

spin_lock_irqsave(&lock, flags);
while (i++ < 100) {
   j = 0;
   asm volatile("mrs %0, CNTPCT_EL0" : "=r" (ticks_start)); 
   while (j++ < 10000) {
      asm volatile ("nop");
   }
   asm volatile("mrs %0, CNTPCT_EL0" : "=r" (ticks_end));
   printk("ticks %d are: %llu\n", i, ticks_end - ticks_start);
}
spin_unlock_irqrestore(&lock, flags);

在真实设备上的输出是(皮质 A-57):

...
ticks 31 are: 2287
ticks 32 are: 2287
ticks 33 are: 2287
ticks 34 are: 1984
ticks 35 are: 457
ticks 36 are: 1604
ticks 37 are: 2287
...

【问题讨论】:

  • 请提供准确的代码,你测量的方式和内容
  • 你为什么希望它每次都一样?
  • @Alex Hoppus 我提供了 ARM 定时器代码 sn-p。
  • @old_timer 但我不明白为什么会有如此巨大的差异,例如。 100 然后 500... 这是什么原因?它在同一个 CPU 内核上的原子上下文中执行,但我每次都看到不同的值
  • @scopehmu 你应该提供组装

标签: c linux-kernel arm arm64 intel-pmu


【解决方案1】:

要在 Arm 上使用计时器和 PMU 之类的东西,您应该在读取 PMU 寄存器之前插入 isb 指令。架构允许处理器推测性地提前或延迟读取寄存器,因为它不依赖于nops 的内部循环。

所以试试这个:

asm volatile("isb; mrs %0, CNTPCT_EL0" : "=r" (ticks_end));

isb 将在让mrs 指令继续之前刷新管道。 CPU 也可能会进行热节流,但这不会影响您使用循环计数器进行的测量,但如果您正在读取通用计时器来测量时间,则会影响。

【讨论】:

    猜你喜欢
    • 2015-12-13
    • 2012-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-04
    • 1970-01-01
    • 2018-08-02
    • 2016-03-08
    相关资源
    最近更新 更多