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代码层面优化(一)的更多相关文章
- Java开发代码性能优化总结
代码优化,可能说起来一些人觉得没用.可是我觉得应该平时开发过程中,就尽量要求自己,养成良好习惯,一个个小的优化点,积攒起来绝对是有大幅度效率提升的.好了,将平时看到用到总结的分享给大家. 代码优化的目 ...
- Java开发中程序和代码性能优化
现在计算机的处理性能越来越好,加上JDK升级对一些代码的优化,在代码层针对一些细节进行调整可能看不到性能的明显提升, 但是我觉得在开发中注意这些,更多的是可以保持一种性能优先的意识,对一些敲代码时间比 ...
- 通过从代码层面分析Linux内核启动来探知操作系统的启动过程
通过从代码层面分析Linux内核启动来探知操作系统的启动过程 前言说明 本篇为网易云课堂Linux内核分析课程的第三周作业,我将围绕Linux 3.18的内核中的start_kernel到init进程 ...
- Python 代码性能优化技巧(转)
原文:Python 代码性能优化技巧 Python 代码优化常见技巧 代码优化能够让程序运行更快,它是在不改变程序运行结果的情况下使得程序的运行效率更高,根据 80/20 原则,实现程序的重构.优化. ...
- Android代码内存优化建议-OnTrimMemory优化
原文 http://androidperformance.com/2015/07/20/Android代码内存优化建议-OnTrimMemory优化/ OnTrimMemory 回调是 Androi ...
- JAVA_eclipse 保留Java文件时自动格式化代码和优化Import
Eclipse 保存Java文件时自动格式化代码和优化Import Eclipse中format代码的快捷方式是ctrl+shift+F,如果大家想保存 java文件的时候 自动就格式化代码+消除不必 ...
- JavaScript代码性能优化总结
JavaScript 代码性能优化总结 尽量使用源生方法 javaScript是解释性语言,相比编译性语言执行速度要慢.浏览器已经实现的方法,就不要再去实现一遍了.另外,浏览器已经实现的方法在算法方面 ...
- Html代码seo优化最佳布局实例讲解
搜索引擎对html代码是非常优化的,所以html的优化是做好推广的第一步.一个符合seo规则的代码大体如下界面所示. 1.<!–木庄网络博客–> 这个东西是些页面注释的,可以在这里加我的& ...
- 利用封装、继承对Java代码进行优化
注:本文实例分别可以在oldcastle(未优化的代码)和newcastle(优化后的代码)中查看,网址见文末 城堡游戏: 城堡中有多个房间,用户通过输入north, south, east, wes ...
随机推荐
- 读取 java.nio.ByteBuffer 中的字符串(String) 写入方式flash.utils.ByteArray.writeUTF
通过研究ByteArray的写入格式以及方法说明,可以发现writeUTF是先使用2位写入字符串的长度,然后在其后写入字符串编码. flash.utils.ByteArray.writeUTF(val ...
- C#动手实践:Kinect V2 开发(2):数据源工作原理及红外源Demo
Kinect体系架构
- .NET并行编程1 - 并行模式
设计模式——.net并行编程,清华大学出版的中译本. 相关资源地址主页面: http://parallelpatterns.codeplex.com/ 代码下载: http://parallelpat ...
- 设置树莓派3 B+的静态IP
修改/etc/dhcpcd.conf 文件 sudo vim /etc/dhcpcd.conf interface eth0 static ip_address= static routers=192 ...
- js产生随机数函数
函数: //产生随机数函数 function RndNum(n){ var rnd=""; for(var i=0;i<n;i++) rnd+=Math.floor(Math ...
- 燕十八MySQL优化学习笔记
观察 show status; 里面的这三个参数;Queries Threads_connected Threads_running判断周期性变化 -------------------------- ...
- class中new与未new的区别 类对象占用空间--转载
转载自http://blog.sina.com.cn/shuiwuhendeboke 颗颗的博客 (1)作用域不同 不用new:作用域限制在定义类对象的方法中,当方法结束时,类对象也被系统释放了 ...
- Java 反射 getDeclareFields getModifiers setAccessible(true)
示例代码: public static Map<String, Object> dtoToMap(Object obj, String pre, String las ...
- logstash 配置 logstash-forwarder (前名称:lumberjack)
logstash-forwarder(曾名lumberjack)是一个用go语言写的日志发送端, 主要是为一些机器性能不足,有性能强迫症的患者准备的. 主要功能: 通过配置的信任关系,把被监控机器的日 ...
- WinForm控件TreeView 只部分节点显示 CheckBox
WinForm控件TreeView 只部分节点显示 CheckBox 用过asp.net的应该知道,要在treeview中实现上述功能可以使用ShowCheckBox 属性指定那些节点显示check ...