Vin*_*ent 2 c c++ benchmarking kernel inline-assembly
英特尔 (链接)的以下论文描述了一种对代码进行准确基准测试的方法。基准测试的核心内容如下(参见第 31 页):
preempt_disable();
raw_local_irq_save(flags);
asm volatile (
"CPUID\n\t"
"RDTSC\n\t"
"mov %%edx, %0\n\t"
"mov %%eax, %1\n\t": "=r" (cycles_high), "=r" (cycles_low):: "%rax", "%rbx", "%rcx", "%rdx"
);
/*call the function to measure here*/
asm volatile(
"CPUID\n\t"
"RDTSC\n\t"
"mov %%edx, %0\n\t"
"mov %%eax, %1\n\t": "=r" (cycles_high1), "=r" (cycles_low1):: "%rax", "%rbx", "%rcx", "%rdx"
);
raw_local_irq_restore(flags);
preempt_enable();
Run Code Online (Sandbox Code Playgroud)
我想知道:
raw_local_irq_save和raw_local_irq_restore做什么?preempt_disable和preempt_enable做什么?在您提供的链接中,如果您阅读了他们实际实现内核模块的第 2.2 节,您会看到有一些评论 -
preempt_disable(); /*we disable preemption on our CPU*/
Run Code Online (Sandbox Code Playgroud)
这是一个 Linux 内核函数,它基本上禁止处理器将上下文切换到不同的进程。
第二个电话——
raw_local_irq_save(flags); /*we disable hard interrupts on our CPU*/
/*at this stage we exclusively own the CPU*/
Run Code Online (Sandbox Code Playgroud)
这会屏蔽硬件上的所有中断。又一个 Linux 内核函数。
这两者一起意味着在基准测试完成之前,没有任何东西,即使是硬件中断也不会干扰处理器。这是为了确保对处理器和其他资源(如缓存、TLB 等)的独占访问。我假设您可以理解为什么这对于正确的基准测试是必要的。
其他两个函数,顾名思义,在基准测试完成后重新启用抢占并恢复中断掩码。
至于会发生什么,如果删除这些调用,那么“某些东西”可能会中断您的基准测试过程,并且您的测量结果可能会出现非常大的差异。