📄 jpeg.txt
字号:
?????????...
MzForm
StatusBar
guanchanghui的专栏
-------展翅飞翔-----------guanchanghui
CSDN | 技术中心 | BLOG首页 | 我的首页 | 我的文章 | 联系作者 | 聚合 | | 搜索 | 登录 197篇原创: 0篇翻译: 60篇转载: 59266次点击: 10个评论: 0个Trackbacks
Csdn Blog User的个人信息
我的博客 | 我的空间
数据读取中,请稍候...公告
最近访客
ATWHERE
文章
.NET(RSS)
C/C++ Visual C++6 Visual c++2005 Evc4.0 编程(RSS)
DirectX 开发(RSS)
DSP 6000系列开发(RSS)
H264 工程开发(RSS)
Jobs(RSS)
Linux 编程(RSS)
SQL Server 2005(RSS)
SQL Server 2000(RSS)
Visual studio mmx sse sse2 多媒体指令集 (RSS)
VOIP(RSS)
windows 操作系统配置(RSS)
生活随笔(RSS)
图像处理(RSS)
收藏
sea119的专栏
日日新 专业的图像处理blog
相册
北戴河之行
264
一个很好的多媒体BLOG
arm 指令优化
Arm 指令优化
ASP.NET
ASP.NET 学习
IT .NETand VC blog
Linux 编程学习
SQLserver 国外网
一个不错的ASP.NET 学习blog
一个不错的学习Ajax的学习网站
一个很好的.NET 技术blog
一个很强的美女开发高手
卖火柴的小女孩blog
章立民blog
DIRECT X开发
crybaby的博客
happycock的专栏
MS mvp 蒋晟
vrix的专栏
zdl1016的专栏
值得学习 一无所知很全面
天极DSHOW 学习指南
嵌入开发(WinCE)
智能手机开发网
蒋志强的专栏
陆其明CSDN blog
隔断里的生活
风生水起
DSP 6000系列
DSP 技术专家
一个很不错的开发硬件的高手
工控博客耿磊
Linux 编程
vckbase MSDN杂志
MSDN杂志
Visual c++ 编程
vc++ 多线程学习
vc++ 良师
VC+ADO 操作数据blog
windowsmobile cnblog
一个.Net 高手
一个不错的c++程序员
一个全面的底层程序员
一个大牛级程序员
一个很好的c++程序员
一个很强的vc++开发工程师
一个比较强MFC编程高手
一个深入编程高手
北邮一个不错的校友
天才出于勤奋-欢迎访问BenBen的BLOG
小明思考
我的cppblog
Windows Mobile
一个Mobile 开发高手
Windows 编程
ASP.NET 学习blog
crybaby2005的博客 (精讲如何制作dll)
一个不错的c++blog
Windows 驱动程序开发
一个很好的底层驱动开发的博客
Windows 网络编程
深之JohnChen的专栏 很全面的技术人才
电子书
CSDN - 读书频道 - .NET compact FrameWork移动开发指南
考勤系统
考勤系统介绍
流媒体相关链接
quanming1119的专栏
tellmenow的专栏
太极语言
孙涛的专栏
小刘blog
左哥的blog
李世平 csdn blog
李世平视频天空
嵌入式开发
ARM嵌入式开发
一个嵌入式Linux大师
嵌入式开发很棒的一个网址
生活知识
生活百态
生活百态2
数据恢复
一个很好的数据恢复的网址
移动开发
hxh(贺星河)的专栏
lonemaverick (windows mobile 大牛)
一个windowsmobile的mvp(RSS)
子弹头专栏(RSS)
风生水起
音乐
天籁村音乐网
存档
2007年08月(5)
2007年07月(3)
2007年06月(21)
2007年05月(31)
2007年04月(12)
2007年03月(8)
2007年02月(13)
2007年01月(29)
2006年12月(22)
2006年11月(14)
2006年10月(7)
2006年09月(38)
2006年08月(21)
2006年07月(26)
2006年06月(7)
最近评论
guanchanghui:呵呵,上班了吧,过两天你哥要上学去了,我们准备送一下:)
bruce_kang:关哥 我是kangxp阿 无意中看到你了 呵呵
guanchanghui:应该不会吧,我在DSP6上做的话都极快,在现在pc的平台上面更是可以忽略不计
afeicome:使用g711 等之类的编解码算法cpu占用率极高,( cpu 为266 ,占用率大概在10% ,g729的话,几乎100% ) 不晓得lz有何见解?
tiancaiak:没有了? 下面的呢?
作者tag:dsp 6000系列开发
上一篇: DSP 从外部加载文件到内存 | 下一篇: COFF 文件的格式
DSP 优化心得
C6XX优化经验总结
一、c6x的编译的常用选项
(一)c6x的编译程序为“cl6x.exe”使用的方法
Cl6x [options] [filenames]
Cl6x: 编译程序
Options: 编译选项
Filenames: C或汇编源文件
说明:
编译选项是一个字母或者两个字母,对大小写不敏感。
编译选项的前面需要有一个“-”符号。
一个字母的选项可以合并在一起。比如“-sgq”与“-s -g -q”相同。
两个字母的选项如果第一个字母相同也可以合并在一起。比如“-mgt”与“-mg -mt”相同。
(二)有关优化的选项
-mt:表示在程序中没有使用alaising技术,这使得编译器可以进行比较好的优化。
-o3:对文件级别进行最强的优化,一般在编译时应该使用这个选项。但是在个别情况下使用这个选项优化程序可能会出现
错误(-o2有相同现象,-o0和-o1不会出现错误)。可能是在优化循环,组织流水线的时候发生错误。如果有这种现象出现可以同时
使用-g选项,程序优化就不会出现错误,但是优化效果会下降。另外可以调整程序的表达方式,可能会避免编译器发生错误。
-pm:在程序级别进行优化。可以将所以文件联合在一起进行优化,主要有去掉没有被调用的函数、总是常数的变量以及没有使用的
函数返回值。建议由程序员自己进行这种优化工作。使用这个选项在win98下编译可能会出现找不到编译程序的情况。
-ms0:不使用冗余循环进行优化,减小程序的大小。一般情况下这个选项对程序大小的优化作用不明显。
-mh[n]:去掉流水线的epilog,减小程序的大小。这个选项的作用比较明显。但是有可能出现读取地址超出有效范围的问题,
所以要在数据段的开始和结尾处增加一些pading,或者在分配内存时保证数组的前面和后面一段范围内都是有效的地址。
可选的参数n给出这种pading的长度字节数。
(三)保留编译和优化信息的选项
-k:保留优化后生成汇编语言文件。
-s:汇编语言文件中加入优化信息,如果没有则加入C语言源程序作为注释。
-mw:在汇编语言文件加入软件流水线信息。
(四)有关调试和剖析的选项
-g:允许符号调试,在“out”文件中包含符号信息和行号信息,可以在c语言级别进行调试和剖析。使用联合使用-g、-mt和-o3可以保
证能够进行符号调试的情况下最大限度的优化。
-mg:允许profile优化后的程序。 在“out”文件中包含符号信息和很少的行号信息。允许在c语言的函数基本进行剖析。
如果联合使用这两个选项,-g选项可能被忽略,结果与只用-mg相同。
(五)其它类型
-mln:生成大内存模式的程序。
-ml0:缺省情况下将集合变量(数组和结构)作为far型。
-ml1:缺省情况下将全部函数作为far型
-ml2: 等于-ml0加-ml1
-ml3: 缺省情况下将全部数据和函数作为far型
(六)建议使用的编译方式
Cl6x -gk -mt -o3 -mw -ss “filename”
方式1用于程序的调试,这种方式具有比较强的优化能力,并且支持符号调试。在编译的过程中不会发生错误。
由于生成的“out”文件中包含了符号信息和行号信息,所以比较大。
Cl6x -k -mgt -o3 -mw -ss “filename”
方式2用于程序的剖析(profile),这种方式的优化能力几乎最强(绝大多数情况下与方式3相同),
并且支持对程序进行profile。文件中只包含了符号信息和很少的行号信息,所以“out”文件比较小。
Cl6x -k -mt -o3 -mw -ss “filename”
方式3用于最终的发行版本程序,可以对程序进行最强的优化,并且去掉了全部的符号和行号信息,所以“out”文件比较小。
由多个文件组成的程序应该编写makefile,将编译参数放在该文件中,并在其中说明使用的编译器的版本号。
(七)连接参数
-heap:指定堆的大小
-stack: 指定栈的大小
连接的各种选项应该统一放在“cmd”文件中
二、双重循环和多重循环的优化总结
双重循环多重循环看起来比较复杂,但实际上多重循环优化方法比较简单,就在于一个字:“拆”,一旦完成这一步之后,
多重循环就成为单层循环,优化就可以按照普通的单层循环来做了。
多重循环的特点是在优化器优化时只在最内层循环中形成一个pipeline,这样循环语句就不能充分利用C6的软件流水线,
而且对于内部循环的次数较少的情况,消耗在prolog和eplog上的cycle数也是不可忽视的。
针对这种状况可以考虑将多重循环拆开形成一个单层循环,可以拆外层循环也可以拆内层循环,
一般视具体情况而定。这样就可以充分利用优化器构成的Pipeline。如下例:
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);
}
内层循环循环次数较少,运算量也不大,资源方面只占用了一个乘法器,一个cycle只使用一次乘法器,
而事实上我们可以在一个cycle内使用两个乘法器,所以还可以充分利用另外的一个乘法器。因此考虑将内层循环拆开来执行,如下:
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);
}
这样虽然代码长度增加了,可变成了单循环,所有的运算都参加到pipeline中来,在Piped loop kernal
中产生每一个cycle内都使用了两个乘法器,充分利用了DSP内部的资源,提高了运行效率。又如下例:
tot = 4;
for (k = 0; k < 4; k++)
{
max = 0;
for (i = k; i < 44; i += STEP)
{
s = 0;
for (j = i; j < 44; j++)
s = L_mac(s, x[j], h[j - i]);
y32[i] = s;
s = L_abs(s);
if (L_sub(s, max) > (Word32) 0)
max = s;
}
tot = L_add(tot, L_shr(max, 1));
}
在这个多层循环中一共有三层循环,而最内层的循环的运算量很小,只有一次乘累加操作,
而我们知道C6中一个packet中可以做两个乘累加运算,所以为了增加内部循环的运算,减少外部循环的层数,
我们可以将第一层循环的操作拆开,其负责的运算加入到内部循环中,也就是在内层循环中一次做四次的乘累加运算,
这样将多次操作形成pipeline,提高了运行效率,优化后的C代码如下:
tot = 4;
max0=0;
max1=0;
max2=0;
max3=0;
for (i = 0; i <44; i += STEP) //STEP=4, 11 times cirs
{
//code
for (j=0;j<=40-i;j++)
{s0=(Word32)(_sadd(s0,_smpy(hh[j],xx[j+i])));
s1=(Word32)(_sadd(s1,_smpy(hh[j],xx[j+i+1])));
s2=(Word32)(_sadd(s2,_smpy(hh[j],xx[j+i+2])));
s3=(Word32)(_sadd(s3,_smpy(hh[j],xx[j+i+3])));
}
}
//code
CCS的优化:
三、16位变为32位操作,使用intrinsic函数,用const等。
1、源代码:
Word32 L_mpy_ll(Word32 L_var1, Word32 L_var2)
{
double aReg;
Word32 lvar;
/* (unsigned)low1 * (unsigned)low1 */
aReg = (double)(0xffff & L_var1) * (double)(0xffff & L_var2) * 2.0;
/* >> 16 */
aReg = (aReg / 65536);
aReg = floor(aReg);
/* (unsigned)low1 * (signed)high2 */
aReg += (double)(0xffff & L_var1) * ((double)L_shr(L_var2,16)) * 2.0;
/* (unsigned)low2 * (signed)high1 */
aReg += (double)(0xffff & L_var2) * ((double)L_shr(L_var1,16)) * 2.0;
/* >> 16 */
aReg = (aReg / 65536);
aReg = floor(aReg);
/* (signed)high1 * (signed)high2 */
aReg += (double)(L_shr(L_var1,16)) * (double)(L_shr(L_var2,16)) * 2.0;
/* saturate result.. */
lvar = L_saturate(aReg);
return(lvar);
}
2、改编后的代码:
static inline Word32 L_mpy_ll(Word32 L_var1, Word32 L_var2)
{
Word32 aReg_hh;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -