TMS320C6678 Programmar Guider翻译.doc_第1页
TMS320C6678 Programmar Guider翻译.doc_第2页
TMS320C6678 Programmar Guider翻译.doc_第3页
TMS320C6678 Programmar Guider翻译.doc_第4页
TMS320C6678 Programmar Guider翻译.doc_第5页
已阅读5页,还剩6页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

TMS320C6678 Programmar Guider本文是对DSP程序优化的第2到4章的部分翻译,水平有限,不妥之处敬请原谅。2 优化C/C+代码2.1 写C/C+代码本章描述了如何分析和裁剪你的代码,以确认你已经从C6000体系获得最好的性能。2.1.1 数据类型小诀窍当写C代码时遵循以下指导方针:1. 避免编码int 和 long类型一样大小,因为C6000编译器的long型为40bit;2. 尽可能使用short数据类型为fixed-point乘法的输入,因为这种数据类型在C6000里提供了最有效的16-bit乘法器。3. 当有循环计数时,使用int或者unsigned int,而不要使用short和unsigned short,以避免不必要的符号扩展说明。2.1.2 分析C代码的性能2.2 编译C/C+代码编译工具提供了一个shell程序(cl6x),可以用来编译,汇编优化,汇编和单步链接程序。调用编译时输入:cl6x options filenames z linker options object files2.2.1 编译选项表2.1 代码关键性能避免选择的编译器选项选项描述-g/-s/-ss这些选项限制了优化C语句的数量,导致较大的代码大小和较慢的执行速度-mu使软件流水线调试无效。用-ms2/-ms3代替来减少代码大小将在其它代码大小的优化上禁用软件流水-o1/-o0总是使用-o2/-o3来最大化编译分析和优化,在性能和代码大小之间用代码大小标志(-msn)来权衡-mz过时的。在3.00前,这个选项改善代码,但是在3.00后,这个选项会降低性能增加代码大小。表2.2性能编译选项选项描述-mh-mhh允许投机执行。适当的填充量必须在数据内存中可用来确保正确执行,这一般不是问题,但必须坚持如此。-mi-mii描述了编译器的中断阈值。如果你知道在你的代码中没有中断发生,编译器可以在软件流水循环一个代码大小前后避免启用和禁止中断,另外,高寄存器压力循环的充分利用有潜在的性能改进。-mt使编译器能够使用假设,使编译器能与某些优化更先进。o3代表最高水平的优化。各种循环执行优化,比如软件流水,展开,和SIMD,各种文件级别特征也用于提高性能。op2指定模块不包含提供给编译器的外部源码调用或者修改的函数和变量。改善了变量分析和允许假设。pm将源文件联合来执行程序层次的优化。 Although o3 is preferable, at a minimum use the o option. Use the pm option for as much of your program as possible. These options imply assertions about your application.表2-3编译器选项稍微降低性能和改善代码大小选项描述-ms0-ms1主要优化性能,其次代码大小。可以用在所有的例程上,但最多用在性能关键例程里。-oi0禁止所有自动控制大小的内联(-o3允许)。用户指定的内联函数仍然允许。表2.4中的选项都是控制代码选择的,结果是以较小的性能下降导致较小的代码大小。表2.4控制代码的编译器选项选项描述o3代表最高水平的优化。各种循环执行优化,比如软件流水,展开,和SIMD,各种文件级别特征也用于提高性能。pm将源文件联合来执行程序层次的优化。op2指定模块不包含提供给编译器的外部源码调用或者修改的函数和变量。改善了变量分析和允许假设。oi0禁止所有自动控制大小的内联(-o3允许)。用户指定的内敛函数仍然允许。ms2ms3主要优化代码大小,其次性能。表2-5描述的选项为信息,不影响性能和代码大小。表2-5信息的编译器选项选项描述-mw用这个选项来产生额外的编译器回馈,这个选项对性能和代码大小没影响。-k保持汇编文件,这样你就可以检查和分析编译器反馈。-s/-ss在汇编中交叉C源码和优化评论。-s选项显示小性能下降;-ss选项显示更严重的性能下降。2.2.2 内存依赖(Memory Dependencies)为了使你的代码最大有效化,C6000编译器安排了尽可能多的指令并行。为了安排并行指令,编译器在指令间必须决定依赖关系。依赖意味着一个指令必须在另一个指令之前发生;比如,一个变量在被调用前必须从内存中被加载。因此只有独立的指令才能并行执行,所以依赖性抑制并行性。n 如果编译器不能决定两个指令是否存在依赖,那么它假设一个依赖项,安排这两个指令循环计算完成第一个指令所需要的任何延迟。n 如果编译器可以决定这两个指令是独立于另一个的,那么可以安排并行。编译器决定指令访问内存是否有依赖性是很难的,下面的技术帮助编译器决定哪个指令是没有依赖性的:n 用restrict关键词指出一个指针是唯一的可以指向一个特定的对象的指针声明的范围的指针。n 用-pm选项,这个选项赋予编译器对所有的程序和模块全局访问和在排除依赖性上允许它更激进。n 用-mt选项,允许编译器使用假设消失依赖性。2.3 Refining C/C+ Code2.4 Refining C/C+ Code表2-10Memory Access IntrisicsTypeC compiler IntrisicDescriptionDouble load/store_memd8(p)开始于地址p(存在内联)的非对齐访问double型数据_memd8_const(p)开始于地址p的非对齐访问常量double型数据_amemd8(p)开始于地址p的double型数据对齐访问_amemd8_const(p)开始于地址p的常double型数据对齐访问Unsigned int load/store_mem4(p)开始于地址p的unsigned int型数据的非对齐访问_mem4_const(p)开始于地址p的常unsigned int型数据的非对齐访问_amem4(p)开始于地址p的unsigned int型数据的对齐访问_amem4_const(p)开始于地址p的常unsigned int型数据的对齐访问Unsigned short load/store_mem2(p)开始于地址p的unsigned short型数据的非对齐访问_mem2_const(p)开始于地址p的常unsigned short型数据的非对齐访问_amem2(p)开始于地址p的unsigned short型数据的对齐访问_amem2_const(p)开始于地址p的常unsigned short型数据的对齐访问指针p可以是任何类型。可是为了允许编译器正确的辨认指针别名,这些内联函数的指针参数p要正确的辨认指向对象的类型。比如,如果你想一次获得4个short型数据,那么在_memd8()里的p指向的类型必须是short。2.4.2.1 Using Word Access in Dot Product(用字访问点积)点积中用到了_mpy()和_mpyh()内联函数;C编译器内联描述int _mpy(int src1, int src2);Multiplies the 16 LSBs of src1 by the 16 LSBs of src2 and returns the result. Values can be signed or unsigned.(src1的低16位跟src2的低十六位相乘,返回结果。返回值可以是signed或unsiganed)int _mpyus(uint src1, int src2);int _mpysu(int src1, uint src2);uint _mpyu(uint src1, uint src2);int _mpyh(int src1, int src2);Multiplies the 16 MSBs of src1 by the 16 MSBsof src2 and returns the result. Values can besigned or unsigned.(src1的高十六位和src2的高十六位相乘,返回的值可以是signed或者unsigned)int _mpyhus(uint src1, int src2);int _mpyhsu(int src1, uint src2);uint _mpyhu(uint src1, uint src2);int _ (int src1, int src2);Multiplies the 16 MSBs of src1 by the 16 LSBs ofsrc2 and returns the result. Values can be signedor unsigned.(src1的高十六位和src2的低十六位相乘,返回值可以是signed或unsigned)int _mpyhuls(uint src1, int src2);int _mpyhslu(int src1, uint src2);uint _mpyhlu(uint src1, uint src2);int _mpylh(int src1, int src2);Multiplies the 16 LSBs of src1 by the 16 MSBs ofsrc2 and returns the result. Values can be signedor unsigned.(src1的低十六位和src2的高十六位相乘,返回值可以使signed或unsigned)int _mpyluhs(uint src1, int src2);int _mpylshu(int src1, uint src2);uint _mpylhu(uint src1, uint src2);2.4.2.3 Using Doubleword Access for Word Data (C64x/C64x+ and C67x Specific)本节的Float Dot Product函数中用到了_itof(),_hi(),_lo()内联函数;C/C+ Compiler IntrinsicDescriptionfloat _itof(uint src);将src的unsigned的比特数解释成float型。Long long _itoll(uint src2, uint src1)通过重新诠释来创建一个新的long long型的寄存器组,src2是高(奇数)寄存器和src1为低(偶)寄存器。uint _lo(double src);从double寄存器组返回低(偶)寄存器uint _lmbd(uint src1, uint src2);搜索由src1的最低位决定的src2的最左边的1或者0,返回的比特数目由改变的比特决定。double _ltod(long src);重新定义long 寄存器组为double寄存器组uint _hi(double src);返回一个double寄存器组的高(奇)寄存器。uint _lo(double src);返回一个double寄存器组的低(偶)寄存器2.4.2.4 Using _nassert(), Word Accesses, and the MUST_ITERATE pragma_nassert内联可能不能解决所有的short-to-int或者float-to-double的数据类型转换,但是它是在不改动C代码的基础上获得更好性能的有用工具。2.4.3 Software Pipelining软件流水线技术用于从一个循环调度指令,这样多个循环可以并行执行。当你选择-o2和-o3编译器选项时,编译器用从你的程序采集到的信息来尝试软件流水你的代码。因为在你的代码中循环是关键性区域,在改善C代码性能上从一下几个方面考虑:n Trip count(行程计数)n Redunant loop(冗余循环)n Loop unrolling(循环展开)n Speculative execution(预测执行)2.4.3.1 Trip Count Issues一个trip count是循环迭代执行的数目。行程计数器是用来计算每个循环的变量。当行程计数器达到trip count的极限,循环终止。如果编译器可以保证至少n次循环迭代将被执行,那么n是已知的最小trip count。编译器有时可以自主决定这些信息。你可以用MUST_ITERATE 和 PROB_ITERATE progma来提供这些信息。最小安全trip count 是循环的迭代次数,这对于安全执行软件流水是很必要的。所有的软件流水循环有一个最小安全trip count需求。如果已知的trip count小于最小安全trip count,将会产生冗余循环。已知的最小trip count和一个给定软件流水循环的最小安全trip count可以从循环的编译器-产生的评论块中找到。一般的,循环在行程计数器倒计时时可以高效软件流水。在多数情况下,编译器可以用一个访问计数器(行程计数器)进行倒计时传递循环,即使源码没有那样写。2.4.3.2 Eliminating Redundant Loops编译器有时不能确定循环执行次数总是大于最小安全trip count。然后编译器将会产生两种循环版本:n 一种非流水版本,如果执行次数小于最小安全trip count;n 一种软件流水版本,执行次数大于等于最小安全trip count;明显地,冗余循环的需求会影响代码大小和性能。为了给编译器指出你不想有两种循环版本,你可以用-ms0或者-ms1选项。只要它可以证明最小trip count将总是大于等于最小安全trip count,编译器将生成软件流水版本,否则,生成非流水线版本。为了帮助编译器只生成软件流水循环版本,用MUST_ITERATE pragma或者-pm选项,帮助编译器确定最小trip count。使用-mh选项可以消除冗余循环的需求。1.2.2.1.2.2.2.3.2.4.2.4.1.2.4.2.2.4.3.2.4.3.1.2.4.3.2.2.4.3.3. Communicating Trip-Count Information to the Compiler当用到编译器时,用下面的选项来把trip-count信息交流给编译器:l -o3和-pm选项允许优化程序访问全部的程序或者大部分和取得循环trip-count的行为特征。l 用MUST_ITERATE pragma来阻止产生冗余循环或允许编译器软件流水循环来减少代码大小。你可以使用MUST_ITERATE和PROB_ITERATE pragma来传递众多关于trip-count的不同类型的信息给编译器。2.4.3.4. Loop Unrolling提高性能的另外一个技术是展开循环;展开小循环使得每个循环的迭代出现在你的代码中。这种优化执行增加了可以并行的指令数目。当一个迭代的操作不实用C6000架构的所有资源时,你可以展开循环。这里有三种循环展开的方法:l 编译器自动展开循环;l 你用UNROLL pragma建议编译器展开循环;l 你自己展开C/C+代码。软件流水只有在内部循环中由编译器实现。你可以创建更大的内部循环来增加性能。一个方法是完全展开内部循环,这样只需要执行几个小周期。循环展开的要求:l 循环数目是一个确定的数字;l 循环数目是2的倍数。第一个要求可以由MUST_ITERATE pragma得到。第二个要求也可以由MUST_ITERATE pragma.传递给编译器。用第三个参数,你可以制定trip-count是2的倍数。如:#pragma MUST_ITERATE (n,n, 2);2.4.3.5. Speculative Execution (mh option)-mh选项有助于编译器消除prologs和epilogs的能力。间接地,可以减少寄存器压力。在减少epilog代码或者消除冗余循环的可能下,-mh选项的应用可以获得更好的代码大小和性能。这个选项可能会造成一个循环读取超过一个数组的结束。因此,你负责安全性。2.4.3.6. What Disqualifies a Loop from Being Software-Pipelined在一系列嵌套循环中,最内层的循环是唯一的一个可以被软件流水的。以下限制适用于软件流水循环:l 如果一个寄存器值存在太久,该代码不是软件流水线代码。l 如果循环在循环体内有复杂的状态代码,这些状态代码的需求超过了在C62x和C67x上的5个C6000状态寄存器或者在C64X/C64x+上的6个状态寄存器,这个循环不是软件流水的。试图消除或者组合这些条件。l 尽管一个软件流水循环会包含内联,但是它不能包含函数调用,包括调用实时支持例程的代码。l 一般的,你在循环中不应该有状态中断(提前退出)。你可能需要用if语句重写你的代码。在一些情况下,编译器可以自动做到这一点。只在代码中用if语句来更新内存和在循环中计算变量的值,在循环外使用它。3. Compiler Optimization Tutorial(编译器优化教程)本章将引导你完成代码开发流程和给你介绍在第一章中提到的编译器优化技术。它使用一步一步的指示和代码示例向您展示如何使用软件开发工具在每一个阶段的发展。3.1. Introduction: Simple C TuningC6000编译器提供业内最好的“开箱即用”的C性能。除了执行许多常见DSP优化,C6000编译器还在各种MIPS密集循环执行软件流水线。这个功能对任何流水线VLIW机器的执行是很重要的。为了充分利用8个独立的功能单元,分析了每个循环的依赖图,安排软件流水。3.1.1. Project Familiarization3.2. Lesson 1: Loop Carry Path From Memory Pointers4. Feedback_Solutions本章对优化循环提供了快速参考,包括回馈综述和反映制定回馈信息的指导方针。1.2.3.4.4.1. Understanding Feedback编译器默认提供一些回馈。额外的回馈是由-mw选项造成的。这些回馈位于.asm文件中,这些文件是由编译器生成的。为了观察这些回馈,你必须启用-k选项,这个选项会从编译器保存.asm输出。了解了回馈,你可以快速调整你的C代码来获得最高的性能。当编译一个循环的时候编译器会经过3个基本阶段。我们将关注这些途径包含的和产生的回馈。这三个阶段是:l 使循环具有软件流水的资格;l 收集循环资源和依赖图示信息;l 循环进行软件流水。4.1.1. Stage 1: Qualify the Loop for Software Pipelining这个阶段的结果会给我们展示回馈窗口的前三或者四行信息,直到编译器可以软件流水。4.1.2. Stage 2: Collect Loop Resource and Dependency Graph Information软件流水一个循环的第二个阶段是收集循环资源和依赖图信息。这些信息主要为:l Loop Carried Dependency Bound。最大循环路径的距离,如果存在。当一个循环的一次迭代写的数值,在下次迭代必须读取时,一个循环执行路径产生。l Unpartitioned Resource Bound。在所有的资源中。在编译器划分每个指令到A或者B之前,资源绑定的最大迭代间隔。l Unpartitioned Resource Bound。在所有的资源中,在编译器划分每个指令到A或者B之后的最大迭代间隔。l Resource Partition table。概述了指令集如何被分配到各个机器资源上和是怎么在A和B上划分的。该表描述如下:n Indi

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论