c++ - preempt_disable/enable 和 raw_local_irq_save/restore 在基准测试中的作用

标签 c++ c kernel benchmarking inline-assembly

英特尔 ( link) 的以下论文描述了一种准确地对代码进行基准测试的方法。基准测试的核心内容如下(见第 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(); 

我在想:

  • raw_local_irq_saveraw_local_irq_restore 做什么?
  • preempt_disablepreempt_enable 有什么作用?
  • 他们在特定情况下的作用是什么?
  • 从基准测试代码中删除它们会产生什么后果?它会阻止正确的基准测试吗?会出什么问题?

最佳答案

在您提供的链接中,如果您阅读他们实际实现内核模块的第 2.2 节,您会看到一些评论 -

preempt_disable(); /*we disable preemption on our CPU*/

这是一个 Linux 内核 function这基本上禁止处理器将上下文切换到不同的进程。

第二次调用 -

raw_local_irq_save(flags); /*we disable hard interrupts on our CPU*/  
/*at this stage we exclusively own the CPU*/ 

这屏蔽了硬件上的所有中断。又是另一个 Linux 内核 function .

这两个一起意味着在基准测试完成之前,没有任何东西,即使是硬件中断也不会干扰处理器。这是为了确保对处理器和其他资源(如缓存、TLB 等)的独占访问。我想您可以理解为什么这对于正确的基准测试是必要的。

另外两个函数,顾名思义,在基准测试完成后重新启用抢占并恢复中断掩码。

至于会发生什么,如果删除这些调用,那么“某些东西”可能会中断您的基准测试过程,并且您的测量结果可能会出现非常大的差异。

关于c++ - preempt_disable/enable 和 raw_local_irq_save/restore 在基准测试中的作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48394211/

相关文章:

c - 用于套接字 SSL 的 Windows API

c - 为什么 gcc 说我有未声明的变量 'newNode'?

kernel - FreeBSD中如何动态切换到另一个内核?

c - 结构分隔变量

c - 从内核获取当前驱动器路径

C++17 部分推导指南

c - 为什么以下 C 代码要求输入两次?

c++ - 如何在C++中的子类的构造函数中初始化父类(super class)的const成员变量?

c++ - 为什么分配给 substr 调用的结果不是编译器错误?

c++ - atoi 转换返回单个数字值