2016-12-03 298 views
0

目前我正在对两个32位微控制器进行性能比较。我使用Dhrystone基准测试在两个微控制器上运行。一个微控制器具有4KB I-cache,而第二个控制器具有8KB I-cache。两款微控制器都使用相同的工具链。尽可能多地在两个微控制器上保持相同的静态和运行时间设置。但具有4KB缓存的微控制器比8KB缓存微控制器更快。两款微控制器都来自同一家厂商,并且基于相同的CPU。32位微控制器上的Drhystone基准测试

任何人都可以提供一些信息,为什么具有4KB缓存的微控制器比其他更快?

回答

0

基准测试通常是无用的。 dhrystone是最古老的之一,在管道和编译器优化过多之前,dhrystone可能已经有了一点价值。我想我大概在15年前就开始使用dhrystone了。

这是微不足道的证明,该代码

.globl ASMDELAY 
ASMDELAY: 
    sub r0,r0,#1 
    bne ASMDELAY 
    bx lr 

这主要是两个指令,可广泛应用于执行时间,如果你了解现代处理器的工作变化在同一芯片上。看到这个简单的技巧是关闭缓存和预取器等,并将此代码放置在偏移量为0x0000的地方,用一些值调用它。将其置于0x0004重复,然后在0x0008处重复。继续这样做。你可以在减法和分支之间放置一个,两个等等。尝试在各种偏移量。

然后,如果您在闪存的处理器外部预取了预取,请打开各个对齐的高速缓存,然后打开和关闭这些对齐。

那么,改变你的时钟,尤其是那些你必须根据时钟速率调整等待状态的MCU。

在单个MCU上,您将会看到基本上两条指令在执行时间上差异很大。在某些情况下,让我们说比其他人长20倍。

现在拿一个小程序或dhrystone程序的一小部分。为你的单片机编译,你看到了多少指令?在编译命令行中对主要优化和其他变体进行较小的修改,代码更改的次数。如果两条指令在执行时间内调用20次,可以得到200条指令或2000条指令有多差?它会变得很糟糕。

如果您现在使用的编译器选项带有dhrystone程序,请进入引导程序,添加一个nop(导致整个二进制文件在闪存中移动一条指令)再次运行。加两个,三个,四个。你还没有比较在一个系统上运行基准测试的不同mcus。

运行有和没有d缓存,有和没有i缓存,如果你有每个这些。如果你有一个闪存预取,打开和关闭闪存预取,如果你有一个写入缓冲,你可以打开和尝试。仍然保留在相同的编译器相同的选项相同的单片机。

将dhrystone源代码中的不同功能,并重新安排在源代码中。而不是Proc_1,Proc_2,Proc_3使其成为Proc_1,Proc_3,Proc_2。再次做所有以上。重新安排,重复。

在离开这个MCU之前,您现在应该看到,完全未修改的相同源代码的执行时间(除了重新安排函数之外)可以并且将具有大不相同的执行时间。

如果您然后开始更改编译器选项或保持相同的源代码并更改编译器,您将看到更多的执行时间差异。

dhrystone基准测试今天或回来的时候怎么可能每个平台都有一个结果?简单的说,这个结果只是一个广泛的范围,并不代表该平台。

因此,如果您尝试比较两个不同的硬件平台,它是来自同一供应商或不同供应商的不同MCU的同一个ARM内核。假设(这不是一个安全的假设),即使假设使用了相同的verilog编译和合成,它也具有相同的编译/编译选项。您可以根据手臂提供的选项进行相同的核心更改。无论如何,在两个实例或两个不同的供应商包装相同的核心,供应商如何是同一个供应商,你会看到变化。然后采取一个完全不同的核心,不管是另一只手臂还是一个mips等等,如何比较使用这种程序的用户如何获得任何价值?这些程序本身在每个平台上的差异很大?

你不能。你可以做的就是用基准测试来衡量一个事物比另一个更好,一台计算机比另一台计算机快,一台编译器比另一台编译器快。为了销售电脑或编译器。 Sprint的覆盖率在Verizons的百分之一之内......是否告诉我们有用的东西?不。

如果你想从等式中消除编译器,并且如果它们真的是相同的“CPU”,来自ARM的源代码的同一个版本,构建方式相同,那么它们应该获取相同的内容,但大小缓存是其中的一部分,所以它可能已经是不同的cpu实现,因为缓存的宽度或深度会影响事物。在软件中,它就像需要一个32位的指针而不是一个16位的指针(17位而不是16位,但是你不能在逻辑上有17位)。不管怎么说,如果你为一个地址空间编译一段时间的测试代码,这个地址空间对于两个平台来说都是相同的,那么你可以根据需要使用相同的二进制代码,注意C库调用strcpy,等等也必须在平台之间相同的空间相同,以消除编译器和对齐从而搞砸你。这可能会或可能不会使赛场水平。

如果你想相信这些是相同的cpu,那么关掉这些缓存,通过这样做来消除编译器的变化。看看他们是否执行相同的。将程序复制到内存并运行内存,消除闪存问题。我假设你有他们两个同样的闪存相同的等待状态?

如果他们是相同的CPU和芯片供应商已与这两个芯片使内存系统采取相同数量的时钟说ram访问,这是真的一样的cpu,你应该能够得到相同的通过消除优化(缓存,闪存预取,对齐)。

你可能看到的是某种形式的代码与编译器与缓存行之间的代码在内存中的对齐方式,或者它可能简单得多,它可能只是缓存中的差异,命中和未命中工作和4KB比这个特定程序的8KB更幸运,以某种方式编译,以特定方式在内存中对齐等。

通过上面简单的两条指令循环,很容易看出一些原因在同一个系统上,性能会有所不同,如果你的现代cpu一次获取8条指令,并且你的循环太靠近该提取的尾端,那么预取可能会认为它需要获取另外8个超出那些时钟周期的成本。当然,当你准确地跨越两条“获取线”时,我将这两条指令称为它们,即使使用缓存,每循环也要花费更多的周期。当这两条指令接近高速缓存行时(因为您改变每次测试的对齐方式)时会发生同样的问题,最终需要两次高速缓存行读取而不是一次读取这两条指令。至少第一次通过那里是额外的缓存行读取。第一次使用的额外时钟是您可以使用像这样的简单基准测量时看到的东西,同时玩对齐。

Michael Abrash,禅宗的汇编语言。有一个epub/etc你可以从本书的github中构建。当这本书出来时,8088已经过时了,如果你看到8088的东西,那么你完全忽略了这一点。它适用于当今最先进的处理器,如何查看问题,如何测试,如何计时以及如何解释结果。到目前为止我所提到的所有东西,以及我所知道的所有我没有提到过的东西,都来自书中的知识,尽管我已经这么做了几十年。

所以再次如果你已经真正消除了编译器,对齐,CPU,与该CPU相关联的内存系统等,并且它只有缓存的大小不同。然后,它可能与高速缓存行如何根据代码与两个高速缓存的高速缓存行对齐来获取命中和未命中有关。一个是击中更多,缺少和/或更好地驱逐这个特定的二进制文件。您可以尝试重新安排函数,添加nops,或者如果不能获得引导程序,则在二进制文件的较低地址处添加整个函数或更多代码(另一个printf等),导致链接器将测试中的代码滑动到不同的地址改变了程序如何与高速缓存行对齐。由于被测代码中的函数非常大(需要执行几条指令),您必须开始修改程序,以便相对于缓存行获得更精细的二进制调整。

如果您调整对齐方式,或者根据重新排列的函数重新排列二进制文件,那么您绝对应该在两个平台上看到执行时间差异。

底线基准不真的告诉你很多,结果有更多的消极臭味,而不是积极的喜悦。如果没有重新编写特定的基准测试或应用程序,只需在一个平台(即一切都相同,但高速缓存的大小或两个完全不同的体系结构)上做得更好,即使您尝试通过对齐来改变结果,开启关闭预取,写入缓冲,分支预测等。拉出所有可能出现的技巧可能会有所不同,从x到y另一个从n到m,也许在范围中有一些重叠。对于这两种平台,除了缓存大小外,我希望能找到一种组合,其中A有时比B快,至少有一种组合的情况B比A快,同时打开和关闭相同的功能在那个比较。如果/当您切换到某个其他应用程序/基准测试时,这一切都会重新开始,没有理由假定dhrystone结果可以预测任何其他待测代码。唯一重要的程序,尤其是MCU是最终构建的应用程序。只需记住更改一行代码,或者甚至在引导程序中添加单个nop可以在性能方面产生显着的结果,有时几个TIMES从单个nop慢或更快。