本帖最后由 xhackerustc 于 2024-5-10 00:17 编辑
#申请原创# @21小跑堂
whetstone benchmark简介
whetsone是一个浮点性能测试工具,主要用来测量cpu浮点运算性能的,使用了不少c库的math函数比如sin、cos、sqrt、exp和log,也有纯粹的浮点四则计算,也有分支测试和函数调用,所以也有部分整数运算,但重点应该集中在浮点上。测试结果的单位是KWIPS或MWIPS,越大越好。大家常用的源码版本来自https://netlib.org/benchmark/whetstone.c 或者https://github.com/kdlucas/byte-unixbench/blob/master/UnixBench/src/whets.c。来自unixbench的版本用得多一些,而且有pc、server和各种SBC数据做参考,所以笔者选择unixbench版本
测试工程的准备
whetstone依赖两部分:printf打印和计时,笔者使用cmake模板开发环境,这两部分都验证过,可参见笔者第一篇测评贴,这里不再赘述,只讲改动部分。
因为要计时,所以选择example中的用到systick的例子即project/at_start_f405/examples/cortex_m4/systick_interrupt,把这个目录复制一份到新目录project/at_start_f405/examples/whetstone/。再把从unixbench下载的whets.c拷贝到project/at_start_f405/examples/whetstone/src
修改project/at_start_f405/examples/whetstone/src/main.c中的systick_handler函数如下:
- volatile uint32_t ticks;
- void systick_handler(void)
- {
- ticks ++;
- }
修改main函数如下:
- extern int whets_main(int argc, char *argv[]);
- int main(void)
- {
- system_clock_config();
- /* config systick clock source */
- systick_clock_source_config(SYSTICK_CLOCK_SOURCE_AHBCLK_NODIV);
- /* config systick reload value and enable interrupt */
- systick_interrupt_config(MS_TICK);
- uart_print_init(115200);
- while(ticks < 2000);
- whets_main(1, NULL);
- for(;;)
- __WFI();
- }
在whets.c中加一行宏定义:
注意:cortex-m4仅支持单精度浮点,所以不要定义DP这个宏,当然我们下面可以改代码测试double运算性能。
whets.c中加入dtime的实现:- extern volatile unsigned int ticks;
- SPDP dtime()
- {
- return (float)ticks / 1000;
- }
whets.c中把main改成whets_main。
修改CMakeLists.txt(原始CMakeLists.txt在第一篇测试帖中)如下:
- <blockquote>diff --git a/CMakeLists.txt b/CMakeLists.txt
编译过程中会发现很多即使只用单浮点,gcc会报很多double-promotion的警告,说明这个whetstone的没完全做好单浮点修改,我们需要修改代码修正除printf处其余所有double-promotion警告,否则测试得到的浮点性能数据不准确,因为cortex-m4仅支持单浮点,double需要sw模拟。笔者的源码改动如下
- @@ -392,9 +392,9 @@
- count--;
- #ifndef UNIXBENCH
- - if (TimeUsed > 2.0)
- + if (TimeUsed > 2.0f)
- #else
- - if (TimeUsed > 0.5)
- + if (TimeUsed > 0.5f)
- #endif
- {
- count = 0;
- @@ -619,7 +619,7 @@
- e1[2] = (e1[0] - e1[1] + e1[2] + e1[3]) * t;
- e1[3] = (-e1[0] + e1[1] + e1[2] + e1[3]) * t;
- }
- - t = 1.0 - t;
- + t = 1.0f - t;
- }
- t = t0;
- }
- @@ -637,7 +637,7 @@
- {
- pa(e1,t,t2);
- }
- - t = 1.0 - t;
- + t = 1.0f - t;
- }
- t = t0;
- }
- @@ -698,10 +698,10 @@
- {
- for(i=1; i<n5; i++)
- {
- - x = t*atan(t2*sin(x)*cos(x)/(cos(x+y)+cos(x-y)-1.0));
- - y = t*atan(t2*sin(y)*cos(y)/(cos(x+y)+cos(x-y)-1.0));
- + x = t*atanf(t2*sinf(x)*cosf(x)/(cosf(x+y)+cosf(x-y)-1.0f));
- + y = t*atanf(t2*sinf(y)*cosf(y)/(cosf(x+y)+cosf(x-y)-1.0f));
- }
- - t = 1.0 - t;
- + t = 1.0f - t;
- }
- t = t0;
- }
- @@ -756,7 +756,7 @@
- {
- for(i=0; i<n8; i++)
- {
- - x = sqrt(exp(log(x)/t1));
- + x = sqrtf(expf(logf(x)/t1));
- }
- }
- }
编译&烧录
- mkdir build
- cd build
- cmake ..
- make
测试结果
由此可以得到at32f405的whetstone性能数据为234.666MWIPS,作为对比笔者一台i5-2520M老旧笔记本的whetstone性能数据为4927.64MWIPS。
强制只用软浮点看看软件模拟的性能如何
阅读libraries/cmsis/cm4/device_support/system_at32f402_405.c的SystemInit()函数发现如下这两行代码:
- #if defined (__FPU_USED) && (__FPU_USED == 1U)
- SCB->CPACR |= ((3U << 10U * 2U) | /* set cp10 full access */
- (3U << 11U * 2U) ); /* set cp11 full access */
- #endif
对于CPACR这个寄存器参考cortex-m4的TRM,简单说就是如果__FPU_USED宏未定义或定义为0,那么cortex-m4浮点就不会开启了。我们看看__FPU_USED的定义libraries/cmsis/cm4/core_support/core_cm4.h,笔者toolchain是gcc所以走如下代码:
- #elif defined ( __GNUC__ )
- #if defined (__VFP_FP__) && !defined(__SOFTFP__)
- #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
- #define __FPU_USED 1U
- #else
- #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
- #define __FPU_USED 0U
- #endif
- #else
- #define __FPU_USED 0U
- #endif
而__VFP_FP__宏应该来自gcc,选不同的float abi,会决定__VFP_FP__宏定义与否。综上只需修改CFLAGS从-mfloat-abi=hard变成-mfloat-abi=soft即可。
软件模拟浮点测试结果:
结果表明:单精度硬浮点性能大概是单精度软浮点的11倍。
如果反汇编生成elf文件也会发现很多的__eabi_xxx函数调用,这是软件模拟浮点运算用的。
mfloat-abi=hard + 双精度浮点性能如何
用原始下载的whets.c文件,只用加两行宏定义:
- #define UNIXBENCH
- /*PRECISION PRECISION PRECISION PRECISION PRECISION PRECISION PRECISION*/
- #define DP
测试截图:
cortex-m4仅支持单精度浮点,开启其硬浮点对双精度浮点无帮助(下面的测试可以证明此猜想),双精度浮点性能是很弱的。单精度硬浮点性能是双精度浮点的21倍
mfloat-abi=soft + 双精度浮点性能如何
开启cortex-m4的硬浮点与否,基本不影响双精度浮点性能,因为都是软件模拟的。
总结
0.本文首创在裸机环境中bring up whetstone benchmark,并在AT32F405平台上做了测试
1.就whetsone测试工具而言,cortex-m4单精度硬浮点的性能可达到单精度软浮点的11倍左右;
2.开启cortex-m4硬浮点,对双精度浮点运算没啥帮助;
3.就whetsone测试工具而言,cortex-m4单精度硬浮点的性能可达双精度浮点的21倍左右
综上cortex-m4的应尽可能使用单精度硬浮点。
|