是什么导致Cortex-A72上带有-O0而不是-O3的简单紧密循环的周期如此高的变化?
我正在围绕获取一段代码的高度一致的运行时进行一些实验。我当前正在计时的代码是一个相当随意的CPU约束工作负载: int cpu_workload_external_O3(){ int x = 0; for(int ind = 0; ind < 12349560; ind++){ x = ((x ^ 0x123) + x * 3) % 123456; } return x; } 我已经编写了一个内核模块,该模块禁用中断,然后运行上述功能的10次尝试,通过获取前后时钟周期计数器的差值来计时每次尝试。其他注意事项: 该机器是ARM Cortex-A72,具有4个插槽,每个插槽具有4个内核(每个插槽都有自己的L1缓存) 时钟频率缩放关闭 不支持超线程 机器几乎没有运行,除了一些简单的系统进程 换句话说,我相信大多数/所有系统可变性的原因都可以解决,尤其是当通过禁用了中断的内核模块运行时spin_lock_irqsave(),代码在运行时应该获得几乎相同的性能(可能对性能造成很小的影响)在第一次运行时,首先将某些指令拉入缓存,仅此而已)。 的确,当使用编译基准测试代码时-O3,我平均看到了大约135,845,192个周期中的最多200个周期,并且大多数测试花费的时间完全相同。但是,当使用编译时-O0,范围从262,710,916上升至158,386个周期。范围是指最长和最短运行时间之间的差。而且,对于-O0代码而言,哪个试验是最慢/最快的试验并没有太多的一致性-违反直觉,在某些情况下,最快的试验是最先的,而最慢的试验是在后的! 那么:是什么原因导致-O0代码的可变性如此高的上限?看一下程序集,似乎-O3代码将所有内容(?)存储在寄存器中,而-O0代码中有很多引用sp,因此似乎正在访问内存。但是即使那样,我也希望所有内容都可以放入L1缓存中,并且在确定的访问时间内就可以坐在那里。 码 被基准测试的代码在上面的代码段中。组件在下面。两者都编译时gcc 7.4.0没有标记,除了-O0和-O3。 -O0 0000000000000000 <cpu_workload_external_O0>: 0: d10043ff sub sp, sp, …