C6000代码层面优化(一)

2014年8月7日,看了一片很长见识的博文,关于DSP如何优化的,有一个问题没有搞通,“百度”一下关键字,居然搜查了一模一样的博文N片,现在也搞不懂这篇博文的原创作者是谁了。反正我感觉直接转摘过去,要是消化不掉,也没啥意思,所以我把我可以理解消化的就先记录下来吧。

一、双重循环或多重循环在保证功能的前提下,减少嵌套循环的层数,原因有二个,如下:

1)优化器优化时只在最内层循环中形成一个 pipeline,这样循环语句就不能充分利用C6 的软件流水线,而且对于内部循环的次数较少的情况,消耗在 prolog(填充)和eplog(排空)上的 cycle 数也是不可忽视的。

2) 一个 cycle 内使用两个乘法器,如果内层循环循环次数较少,运算量也不大,一个cycle 只使用一次乘法器,而事实上我们可以在,所以还可以充分利用另外的一个乘法器。
    备注:一个内层循环会形成一个pipeline,流水优化是在pipeline中,一个pipeline中代码运行的时间,会消耗一个或者多个cycle。

例子:FIR滤波器原始程序
  void fir2(const short input[], const short coefs[], short out[])
  {
  int i, j;
  int sum = 0;
  for (i = 0; i < 40; i++)
  {
    for (j = 0; j < 16; j++)
      sum += coefs[j] * input[i + 15 - j];
    out[i] = (sum >> 15);
  }

可以优化为:
 void fir2_u(const short input[], const short coefs[], short out[])
  {
  int i, j;
  int sum;
   for (i = 0; i < 40; i++)
   {
    sum = coefs[0] * input[i + 15];
     sum += coefs[1] * input[i + 14];
     sum += coefs[2] * input[i + 13];
     sum += coefs[3] * input[i + 12];
     sum += coefs[4] * input[i + 11];
     sum += coefs[5] * input[i + 10];
     sum += coefs[6] * input[i + 9];
     sum += coefs[7] * input[i + 8];
     sum += coefs[8] * input[i + 7];
     sum += coefs[9] * input[i + 6];
     sum += coefs[10] * input[i + 5];
     sum += coefs[11] * input[i + 4];
     sum += coefs[12] * input[i + 3];
     sum += coefs[13] * input[i + 2];
     sum += coefs[14] * input[i + 1];
     sum += coefs[15] * input[i + 0];
     out[i] = (sum >> 15);
   }

}

二、使用intrinsic函数,将16位扩展为32位
c6000编译器提供的intrinsic 可快速优化C代码,intrinsic用前下划线表示同调用函数一样可以调用它,即直接内联为C6000的函数。
例如,“aReg_ll = (Word40)_mpyu(L_var1, L_var2)>>16”中“_mpyu”就是一个intrinsics函数,它表示两个无符号数的高16位相乘,结果返回。

这些内联函数定义在CCS所在的C6000/CGTOOLS/Include目录下的C6X.h文件中。
下面这个例子是C6000的“Programmer‘s Guide”上提取的使用intrinsics优化C代码的例子。
源代码:
int dotprod(const short *a, const short *b, unsigned int N)
{
int i, sum = 0;
for (i = 0; i < N; i++)
sum += *(a+i) * *(b+i);
return sum;
}

改编后代码:
int dotprod(const int *a, const int *b, unsigned int N)
{
int i, sum1 = 0, sum2 = 0;
for (i = 0; i < (N >> 1); i++)
{
sum1 += _mpy (*(a+i), *(a+i));
sum2 += _mpyh(*(a+i), *(a+i));
}
return sum1 + sum2;
}

三、使用 const 可以限定目标

C6000编译器如果确定两条指令是不相关的,则安排它们并行执行。 关键字const可以指定一个变量或者一个变量的存储单元保持不变。
这有助于帮助编译器确定指令的不相关性。例如下例中,源代码不能并行执行,而结果改编后的代码可以并行执行。
void fir_fxd1(short input[], short coefs[], short out[])
{
int i, j;
for (i = 0; i < 40; i++)
{
for (j = 0; j < 16; j++)
out[i*16+j]= coefs[j] * input[i + 15 - j];
}
}
改编后的代码:
void fir_fxd2(const short input[], const short coefs[], short out[])
{
int i, j;
for (i = 0; i < 40; i++)
{
for (j = 0; j < 16; j++)
out[i*16+j]= coefs[j] * input[i + 15 - j];
}

}

四、if...else...语句的优化

如果在循环中出现if...else...语句,由于if...else...语句中有跳转指令,而每个跳转指令有5个延迟间隙,因此程序执行时间延长;另外,循环内跳转也使软件流水受到阻塞。直接使用逻辑判断语句可以去除不必要的跳转。
源代码:
if (sub (ltpg, LTP_GAIN_THR1) <= 0)
{
adapt = 0; 
}
else

if (sub (ltpg, LTP_GAIN_THR2) <= 0)
{
adapt = 1; 
}
else
{
adapt = 2; 
}
}

改编后的代码:
  adapt = (ltpg>LTP_GAIN_THR1) + (ltpg>LTP_GAIN_THR2);

本篇先写到这里,以上内容均属于个人理解,事例和文字来源网络,若有新的理解,将持续更新。

C6000代码层面优化(一)

时间: 2024-10-21 04:09:01

C6000代码层面优化(一)的相关文章

从代码层面优化系统性能应该怎么做?

我们以前看到的很多架构变迁或者演进方面的文章大多都是针对架构方面的介绍,很少有针对代码级别的性能优化介绍.本文将针对一些代码细节方面的东西进行介绍. 服务器环境 服务器配置:4 核 CPU,8G 内存,共 4 台 MQ:RabbitMQ 数据库:DB2 SOA 框架:公司内部封装的 Dubbo 缓存框架:Redis.Memcached 统一配置管理系统:公司内部开发的系统 问题描述 单台 40TPS,加到 4 台服务器能到 60TPS,扩展性几乎没有. 在实际生产环境中,经常出现数据库死锁导致整

零零好车代码层面优化系统开发性能应该怎么做?

我们以前看到的很多架构变迁或者演进方面的文章大多都是针对架构方面的介绍,很少有针对代码级别的性能优化介绍.本文将针对一些代码细节方面的东西进行介绍,欢迎大家吐槽以及提建议.服务器环境 服务器配置:4 核 CPU,8G 内存,共 4 台 MQ:RabbitMQ 数据库:DB2 SOA 框架:公司内部封装的 Dubbo 缓存框架:Redis.Memcached 统一配置管理系统:公司内部开发的系统 系统开发谢天华 135-0148-8501 问题描述 单台 40TPS,加到 4 台服务器能到 60T

Hive架构层面优化之四 常用复杂/低效的统计从源上给出,以避免上层作业过多计算

案例一:trackinfo,基础表处理常用的低性能UDF 背景描述:日志信息10分钟加载一次到实时日志表trackreal中(按小时分区),为了保证实时性,在加载的过程中并没有做任何的过滤处理,加载到trackreal表后再过滤非法数据.爬虫数据等,生成按天增量日志表trackinfo,然后根据不同的page_type来统计流量. 解决方案如下: select '首页', count(*) pv, #每条记录就是一条pv count(distinct session_id) uv #根据sess

C++ 代码性能优化 -- 循环分割提高并行性

对于一个可结合和可交换的合并操作来说,比如整数的加法或乘法, 我们可以通过将一组合并操作分割成 2 个或更多的部分,并在最后合并结果来提高性能. 原理: 普通代码只能利用 CPU 的一个寄存器,分割后可以利用多个寄存器. 当分割达到一个数量时,寄存器用完,性能不再提升,甚至会开始下降. 用代码来描述,如下: // 一般情况下的代码 for (i = 1; i < n+1; i++) { res = res OPER i; } // 循环分割后代码 for (i = 1; i < n; i+=2

Java代码性能优化技巧

流方面: private FileOutputStream writer; writer = new FileOoutputStream(fileName); 使用BufferedOutputStream 对写入FileOutputStream的数据进行缓存 //将writer的类型由FileOutputStream 变更为BufferedOutputStream //private FileOutputStream writer; private BufferedOutputStream wr

Hive参数层面优化之一控制Map数

1.Map个数的决定因素 通常情况下,作业会通过input文件产生一个或者多个map数: Map数主要的决定因素有: input总的文件个数,input文件的大小和集群中设置的block的大小(在hive中可以通过set dfs.block.size命令查看,该参数不能自定义修改): 文件块数拆分原则:如果文件大于块大小(128M),那么拆分:如果小于,则把该文件当成一个块. 举例一: 假设input目录下有1个文件a,大小为780M,那么hadoop会将该文件a分隔成7个块(6个128m的块和

Hive参数层面优化之二控制Reduce数

Reduce数决定中间或落地文件数,文件大小和Block大小无关. 1.Reduce个数的决定因素 reduce个数的设定极大影响任务执行效率,不指定reduce个数的情况下,Hive会猜测确定一个reduce个数,基于以下两个设定: 参数1:hive.exec.reducers.bytes.per.reducer(每个reduce任务处理的数据量,默认为1000^3=1G) 参数2:hive.exec.reducers.max(每个作业最大的reduce数,默认为999) 计算reducer数

Java 代码性能优化总结

35 个 Java 代码性能优化总结 前言 代码优化,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑的,就像大海里面的鲸鱼一样,它吃一条小虾米有用吗?没用,但是,吃的小虾米一多之后,鲸鱼就被喂饱了.代码优化也是一样,如果项目着眼于尽快无BUG上线,那么此时可以抓大放小,代码的细节可以不精打细磨:但是如果有足够的时间开发.维护代码,这时候就必须考虑每个可以优化的细节了,一个一个细小的优化点累积起来,对于代码的运行效率

Hive语法层面优化之一数据倾斜介绍

数据倾斜:数据分布不均匀,造成数据大量的集中到一点,造成数据热点: 由于数据并不是平均分配的,会导致各个节点上处理的数据量是不均衡的,所以数据倾斜是无法避免的: 造成数据倾斜的最根本原因:key分发不均匀造成的: 常见的数据倾斜的症状 1)  Map阶段快,reduce阶段非常慢: 2)  某些map很快,某些map很慢: 3)  某些reduce很快,某些reduce很慢: 4)  任务进度长时间维持在99%(或100%),查看任务监控页面,发现只有少量(1个或几个)reduce子任务未完成,