这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 企业专区 » Renesas » 【CPKCORRA8D1B评测】---Helium优化对比测试

共4条 1/1 1 跳转至

【CPKCORRA8D1B评测】---Helium优化对比测试

助工
2024-11-18 19:36:55     打赏

      经过进一步的编码,我忽然发现无法使用coremark做效率改善验证了,原因是CoreMark的矩阵乘操作,存在大量的格式转换,而且输出不是定点小数或者与输入一致格式的数据,导致无法直接调用矢量运算指令,以 matrix_mul_const为例:

      乘法运算就涉及到16bit转换为32bit的操作,而矢量运算的造数据那一步,就需要load固定bit数的数据,即16bit数据如果要转换成32bit数据矢量,那就得先把数据转换成32bit的,然后再去操作,这种操作很明显的增加了运算量,反而无法判断出提升幅度。

     另外,由于输入输出数据不是按照定点小数的方式设计的,导致输出数据的格式要求和输入数据的格式要求不一致,无法使用矢量乘除操作去加速并输出。

     即使MATDAT和MATRES定义成浮点行,在coremark里,也是需要经过格式转换才能使用,导致无法进行下一步操作。

     而这么看的话,测试矢量运算的提升效果,不能直接从coremark上去入手了,而是需要改用cmsis-dsp来做验证了。

代码修改

开启CMSIS-DSP

   这个修改需要在RASC中操作,具体操作:

       不在调试用的电脑前,晚点给出具体图片,操作是在components选项中勾选DSP后生成工程

2.jpg

增加测试代码

    经过观察,CMSIS-DSP的测试代码,所引用的底层计算接口都存在Helium加速和完全无加速的版本,因此完全可以把CMSIS-DSP测试代码再封装一遍,替换CoreMark入口,达到测试目的。具体修改如下:

移植测试代码

   从CMSIS-DSP库中提取测试代码文件(.c和.h文件),在CMSIS-DSP代码中的路径为:Examples/ARM。

   由于CMSIS-DSP所有例程入口都是main,因此需要把main改为其他函数名,以保证不与现有工程冲突。另外,例程中存在大量的同名变量,因此需要把这些变量尽可能声明成static类型,一方冲突,另外,几个data.c的文件需要更名成.h文件,由对应的代码#include进去。

   最终改完后的目录结构如下:

1.jpg

   至于细节,由于修改点比较多,这里就不一一展示了,有兴趣的话可以访问CPKCOR_RA8D1B_TEST: cpkcor_ra8d1测试helium工程c查看。

增加测试入口文件

   增加测试文件dsp_test.h和dsp_test.c,用于运行实际测试和结果输出代码,具体内容如下:

dsp_test.c

#include "dsp_test.h"

#include "arm_math.h"
#include "system_tick.h"


 // 单项测试入口声明
extern int32_t arm_matrix_main(void);
extern int32_t arm_bayes_main(void);
extern int32_t class_marks_main();
extern int32_t arm_fft_bin_main(void);
extern int32_t arm_fir_main(void);
extern int32_t graphic_equalizer_main(void);
extern int32_t arm_svm_main(void);
extern int32_t arm_linear_interp_main(void);
extern int32_t arm_variance_main(void);
extern int32_t arm_sin_cos_main(void);
extern int32_t arm_signal_converge_main(void);
extern int32_t arm_dotproduct_main(void);
extern int32_t arm_convolution_main(void);

 // 测试执行结构体定义
struct dsp_test_t {
  int32_t (*func)(void);
  char *name;
  unsigned long retry;
};

 // 具体测试项
struct dsp_test_t dsp_test[] = {
    {arm_bayes_main, "arm_bayes_main", 100000},
    {arm_convolution_main, "arm_convolution_main", 10000},
    {arm_dotproduct_main, "arm_dotproduct_main", 200000},
    {arm_fft_bin_main, "arm_fft_bin_main", 2500},
    {arm_fir_main, "arm_fir_main", 5000},
    {arm_linear_interp_main, "arm_linear_interp_main", 200000},
    {arm_matrix_main, "arm_matrix_main", 100000},
    {arm_signal_converge_main, "arm_signal_converge_main", 200},
    {arm_sin_cos_main, "arm_sin_cos_main", 50000},
    {arm_svm_main, "arm_svm_main", 300000},
    {arm_variance_main, "arm_variance_main", 300000},
    {class_marks_main, "class_marks_main", 200000},
    {graphic_equalizer_main, "graphic_equalizer_main", 2500},
};

 // 测试执行函数
void dsp_test_func(void) {
  unsigned long i;
  unsigned int j;
  TIMING_FORMAT tick_start = 0, tick_end = 0;

#if defined(ARM_MATH_MVEF) || defined(ARM_MATH_MVEI)
  printf("Helium version\n\r");
#else
  printf("Normal version\n\r");
#endif

  for (j = 0; j < sizeof(dsp_test) / sizeof(struct dsp_test_t); j++) {
    tick_start = systick_get();
    for (i = 0; i < dsp_test[j].retry; i++) {
      dsp_test[j].func();
    }
    tick_end = systick_get();
    printf("%s use: %ums\n\r", dsp_test[j].name, tick_end - tick_start);
  }
  printf("test done\n\r");

  while (1) {
    ;
  }
}

dsp_text.h

#ifndef __DSP_TEST_H_
#define __DSP_TEST_H_

void dsp_test_func(void);

#endif

去掉coremark并添加测试代码入口

//#include "coremark.h"
#include "dsp_test.h"


......

void hal_entry(void) {
  ......
  
  // coremark_main();

  dsp_test_func();

}

......

测试结果

   开关helium功能的选项在此位置,选择Not Used代表完全不开启Helium,选择Integer + Floating Point代表开启Helium定点部分和浮点部分。

1.jpg

开启helium

Helium version
arm_bayes_main use: 1748ms
arm_convolution_main use: 1176ms
arm_dotproduct_main use: 1347ms
arm_fft_bin_main use: 1332ms
arm_fir_main use: 1271ms
arm_linear_interp_main use: 1898ms
arm_matrix_main use: 1701ms
arm_signal_converge_main use: 1333ms
arm_sin_cos_main use: 1186ms
arm_svm_main use: 1468ms
arm_variance_main use: 1536ms
class_marks_main use: 1702ms
graphic_equalizer_main use: 1254ms
test done

关闭helium

Normal version
arm_bayes_main use: 2032ms
arm_convolution_main use: 1215ms
arm_dotproduct_main use: 824ms
arm_fft_bin_main use: 2015ms
arm_fir_main use: 3194ms
arm_linear_interp_main use: 1885ms
arm_matrix_main use: 2703ms
arm_signal_converge_main use: 1936ms
arm_sin_cos_main use: 716ms
arm_svm_main use: 1825ms
arm_variance_main use: 2456ms
class_marks_main use: 2116ms
graphic_equalizer_main use: 1866ms
test done

统计后的提升量

1.jpg

测试视频

   测试过程视频:https://www.bilibili.com/video/BV1PBBkYaEYL/

结论

   从测试数据上看,大部分运算都出现了正向的优化,优化程度不一,最明显的优化点应该是fir计算,因为fir算法从逻辑上来说,是最为契合矢量运算的要求的。

       负优化的部分,arm_sin_cos_main和arm_dotproduct_main两个部分是让我感觉最不可思议的地方,两个函数在实现上,主要调用的都是arm_mult_f32 和 arm_add_f32。在使用helium优化前,一个循环做一次计算,采用矢量运算后,一次循环做了四次乘或加的运算,照理来说,应该是正向优化才对,但实际效果却是负优化,有些没想明白原因。

       另外,由于测试函数是件计算和初始化部分都放在一起实现的,因此显示的优化程度并不代表实际的优化程度,实际的优化程度,正向和负向都会更大,因为数据初始化部分并未加入helium运算,开不开helium,理论上效果都是一样的,除非编译器在开启helium时,自动做了代码转矢量运算的操作。






关键词: CPKCOR     RA8D1B     评测     Helium         

助工
2024-11-18 19:38:03     打赏
2楼

工程师
2024-11-19 09:46:16     打赏
3楼

学习下新知识


工程师
2024-11-19 10:19:11     打赏
4楼

6666


共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]