鲲鹏亲和优化## 使用数组加宽比较优化(array-widen-compare)

步骤 1 准备用例 test.c

#include <stdint.h>
#include <stdio.h>
#include <sys/time.h>
#define LEN 1024000
#define my_min(x, y) ((x) < (y) ? (x) : (y))
// 优化主体函数 (优化选项 -farray-widen-compare)
uint32_t
func (uint32_t len0, uint32_t len1, const uint32_t len_limit, const uint8_t *const pb, const uint8_t *const cur)
{
  uint32_t len = my_min(len0, len1);
  while (++len != len_limit)
    if (pb[len] != cur[len])
      break;
  return len;
}

int main()
{
 uint8_t pb[LEN] = {0};
 uint8_t cur[LEN] = {0};
 // 前期数据准备
 for(int i = 0; i< LEN-1; i++) {
  pb[i] = i*2+3;
 }
 pb[LEN-1] = 5;
 for(int i = 0; i< LEN-1; i++) {
  cur[i] = i*2+3;
 }
 cur[LEN-1] =6;
 uint32_t res = 0;
 struct timeval start, end;
 long time;
 gettimeofday(&start, NULL);
 // 主要循环
 for (int i = 0; i < 2000; i++) {
  res = func(0, 0, LEN-1, pb, cur);
 }
 gettimeofday(&end, NULL);
 // 计算循环执行时间
 time = (end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec);
 printf("\nRunning Time:%ld us\n", time);
 printf("res=%d\n", res);
 return 0;
}

步骤 2 对test.c进行原生编译

$ gcc -O3 test.c -o test_before

步骤 3 对test.c 进行添加选项编译

$ gcc -O3 -farray-widen-compare -o test_after

步骤 4 执行test_before

$ ./test_before
Running Time: 2744325 us
res=1023999

步骤 5 执行test_ after

$  ./test_after
Running Time: 425955 us
res=1023999

步骤 6 查看优化效果

从结果上看,编译增加array-widen-compare选项之后运行时间缩减约80%,同时最终结果保持一致,表明该优化选项在此类场景下能够取得显著提升。## 使用ccmp指令流水优化

步骤 1 准备用例test.c

int func (int a, int b, int c)
{
 while(1)
  {
   if(a-- == 0 || b >= c)
   {
     return 1;
   }
  }
}

步骤 2 对test.c原生编译为汇编代码

$ gcc -O -S test.c -o base.s

步骤 3 查看汇编代码

$ vim base.s

核心函数部分为

func:
.LFB0:
    .cfi_startproc
.L2:
    cmp   w1, w2
    cset  w3, ge
    cmp   w0, 0
    cset  w4, eq
    orr   w3, w3, w4
    sub   w0, w0, #1
    cbz   w3, .L2
    mov   w0, 1
    ret
    .cfi_endproc
.LFE0:

步骤 4 使用ccmp指令优化编译

$ gcc -O -fccmp2 -S test.c -o test.s

步骤 5 查看优化后的汇编代码

$ vim test.s

核心部分为

func:
.LFB0:
    .cfi_startproc
    b    .L2
.L3:
    mov   w0, w3
.L2:
    sub   w3, w0, #1
    cmp   w0, 0
    ccmp  w1, w2, 0, ne
    blt   .L3
    mov   w0, 1
    ret
    .cfi_endproc
.LFE0::

经过优化之后在arm64平台上能够使能ccmp指令。SPECCPU2017子项557提升约1%。

Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐