[资料分享] DSP代码优化方法(4)

fish001   2018-2-23 22:36 楼主
方法一 把浮点运算改成定点运算
        因为C6x DSP板并不支持浮点运算,但我们的原始程序代码是浮点运算的格式,所以必须改成定点运算,而其修改后的执行速度也会加快很多。我们采用 Q-format 规格来表示浮点运算。以下将介绍其相关原理。
        定点DSP使用固定的小数点来表示小数部份的数字,这也造成了使用上的限制,而为了要分类不同范围的小数点,我们必须使用Q-format的格式。不同的Q-format表示不同的小数点位置,也就是整数的范围。表2呈现Q15数字的格式,要注意在小数点后的每一位,表示下一位为前一位的二分之一,而MSB (most-significant-bit ) 则被指定成有号数 ( Sign bit )。由表2可以知道,当有号数被设成0而其余位设成1时,可得到最大的正数 (7FFFH ) ;而当有号数被设成1而其余位设成0时,可得到最大的负数 ( 8000H ) 。所以Q15格式的范围从-1到0.9999694 (@1) ,因此我们可以藉由把小数点向右移位,来增加整数部份的范围,如表3所示,Q14格式的范围增为-2.0到1.9999694 (@2) ,然而范围的增加却牺牲了精确度。

        方法二 建立表格 ( table )
        原来程序的设计是除了要读AAC的档案外,在译码时,还要再另外读取一些C语言程序代码的内容再做计算,如读取一些数值做sin、cos、exp的运算,但是为了加快程序的执行速度,故将这这些运算的结果建成表格,内建在程序中,可以不必再做额外的计算动做,以加速程序。

        方法三 减短程序的长度
        1.去除Debug的功能
        原本程序在Debug的阶段时,就加了许多用来侦测错误的部份,程序 Debug完后,已经没有错误发生,所以就可以把这些部份给去除,以减少程序的长度,也可以减少程序执行时的时脉数,加快程序的速度。
        2.去除计算时脉( clock ) 功能
        原本程序可以计算执行程序所需的时脉数,我们也可以把这些部份给去除,如果有需要计算时脉时,我们可以用C6x的工具软件来作,功能更强大。

        方法四 减少I/O 过程
        原本在做译码的动作时,是先读取AAC档案的一部份做译码,译码完成后再读取下一部份,再做译码。但是由于C6x的板子跟PC做档案读取时相当的缓慢,读取的动作占了大部份的时间,所以就将程序改成先将AAC档案全部读到C6x的内存中,再做译码。或是将AAC建成表格(约1 MB),以避免DSP板上的内存不足。

        方法五 减少子程序的呼叫
        在呼叫子程序时,必须先将缓存器的内容放到堆栈(stack) 中,而从子程序返回时,也要将这些缓存器原本的内容从堆栈中取出来。但是有些子程序的长度很短,而且被呼叫的次数又很多,往往几个时脉就可以完成却浪费时间在存取堆栈的内容上,所以干脆将这些很短的子程序直接写在主程序当中,以减少时脉数。

        方法六 写汇编语言
        虽然由C语言所编译出来的汇编语言可以正确无误的执行,但是这个汇编语言却不是最有效率的写法,所以为了增加程序的效率,于是在某些地方,例如一些被呼叫很多次且程序代码不长的函式(function),必须改以自己动手写汇编语言来取代。

        方法七 利用平行处理的观念
        C6x是一颗功能强大的处理器,它CPU的内部提供了八个可以执行不同指令的单元,也就是说最多可以同时处理八个指令。所以如果我们可以用它来作平行处理,我们就可以大大的缩短程序执行的时间,最有效率的来利用它来作解码的动作。

        最后还要知道:
        第三级优化(-O3),效率不高(经验),还有一些诸如用一条读32位的指令读两个相邻的16位数据等,具体情况可以看看C优化手册。但这些效率都不高(虽然ti的宣传说能达到80%,我自己做的时候发现绝对没有这个效率!65%还差不多),如果要提高效率只能用汇编来做了。还有要看看你的c程序是怎么编的,如果里面有很多中断的话,6000可以说没什么优势。还有,profiler的数据也是不准确的,比实际的要大,大多少不好说。还有dsp在初始化的时候特别慢,这些时间就不要和pc机相比了,如果要比就比核心的部分。

        关于profile:
        C6x的Debug工具提供了一个profile界面。在图9中,包括了几个重要的窗口,左上角的窗口是显示出我们写的C语言,可以让我们知道现在做到了哪一步。右上角的窗口显示的是C6x所编译出来的汇编语言,同样的我们也可以知道现在做到了哪一步。左下角的窗口是命令列,是让我们下指令以及显示讯息的窗口。而中间的profile窗口就是在profile模式下最重要的窗口,它显示出的项目如下表:
        表5:profile的各项参数[8]
        字段 意义
Count被呼叫的次数
Inclusive 包含子程序的总执行clock数
Incl-Max 包含子程序的执行一次最大clock数
Exclusive 不包含子程序的总执行clock数
Excl-Max 不包含子程序的执行一次最大clock数
复制代码
       利用这个profile模式我们可以用来分析程序中每个函数被呼叫的次数、执行的时脉数等等。用这个分析的结果,我们就可以知道哪个函数所花费的时脉最多,是可以再改进的,而针对它来作最佳化。

        汇编代码级的优化
        在经过C代码的优化之后,还不能满足性能上的要求,则可以通过profile
        clock工具找出效率很低的部分,使用线性汇编重新改写。再通过汇编优化器编译,汇编优化器从输入的线性汇编代码中,完成以下功能:
● 寻找可以平行执行的CPU指令。
● 在软件流水线期间,处理流水线标号。
● 分配寄存器的用法。
● 分配功能单元。
复制代码
       TI提供的汇编优化器可以得到很高的效率,一般可以满足性能上的要求。
        优化中的问题
        在优化过程中,总是要对程序进行一定的改动,这样经常会出现一些问题。
        1) 优化结果的验证
        优化过的程序往往不知道是否运行正确,这就需要加以验证。一般采用的办法就是通过测试序列来验证。测试序列指的是对于不同的算法所取的一组特殊的数据,这些数据可以准确的反映算法的特性。测试序列中每组数据包括输入数据和输出数据,通过对输入数据的运算,把结果与输出数据进行比较,判断程序的正确性。一些常见的算法,一般都提供了测试序列。还有一些,没有测试序列。这时就需要根据算法的特点,自己构造测试序列,进行验证。构造的时候,注意序列最好有几组,数据最好有一定的长度,这样验证的更准确。
        2) 内存泄漏的问题
        C64X系列DSP的内部存储空间有1MB,其中程序和数据还有CPU的二级缓存将共享这片空间,因此当程序的运行不正常时,很有可能就是内存泄漏造成的。因此,在程序设计中,应尽量不用指针,同时注意进行边界检测。
        程序设计的一些方法
        程序设计时,一切以满足实际的要求为目标。在实际的设计中,除了优化能够提高性能以外,还可以采取其他的办法,利用DSP的特性,提高程序的运行性能,满足实际的设计要求。
        1) 把程序和经常要用的数据放入片内RAM
        片内RAM与CPU
        工作在同一时钟频率,比片外RAM性能高得多。因此把程序放在片内可以大大提高运行的速度。同时对于一些经常要用到的数据,放入片内,也会节省处理时间。
        2) 通过DMA技术搬移数据
        对于C64X芯片,其片内RAM有1MB,但是对于一些大型的图像处理算法而言,仍可能是不够的,因此经常通过DMA技术,把需要用到的数据搬入片内,把不需要的搬到片外,可以大大的提高程序的运行速度。
        3) CACHE的使用
        增大CACHE,可以明显的提高性能。但是C64X系列DSP中程序和数据还有CACHE共享片内RAM,因此增大CACHE,就减小了实际的片内可用空间,设计中需要注意。

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复