DSP 图像处理算法的实现-III

更新时间:2023-12-21 03:15:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

本科毕业论文

(科研训练、毕业设计)

题 目:DSP 图像处理算法的实现-III姓

名:翁彬彬

院:信息技术与科学学院 系:电子工程系

专 业:电子信息工程专业 年 级:2004 学

号:04140059

指导教师(校内):杨涛 职称:教授 指导教师(校外):

职称:

2008 年

5 月

20

1

摘要 本文研究的是基于 TI 公司DSP 硬件平台的数字图像处理技术。考

虑到可移植性,采用 C 语言编写代码。采用空域法设计图像处理的算法,所涉 及运算包括卷积,相关,中值滤波等。由于图像处理要处理大量的数据,需用 DSP 处理器来提高效率。TMS320C6000 系列 DSP 是 TI 公司最新推出的一种 并行处理的数字信号处理器,其特有的代码优化器也使得 C 优化更加方便。我 们根据 TMS320C6000 系列的结构特点,对 C 代码进行一系列优化,例如:选 用适当的编译器选项,内联函数的使用,字处理技术,打开循环,流水线技术, 线性汇编等一系列方法对 C 代码进行优化,从而极大地提高了数字图像处理的 工作效率。

关键字 数字图像处理 TMS320C6000 系列 DSP C 语言优化

Abstract: In this thesis, based on the DSP hardware platform of TI Co., the algorithms of digital image processing were studied. C language was used to program these algorithms for the purpose of maximizing the portability of program modules. These algorithms, which include convolutions, correlations and medium filters, were designed based on spatial patterns. To make real-time image processing possible, DSP processors are used to process the massive data in images. The TMS320C6000 DSPs from TI Co. are parallel digital

image processors, of which the C-complier makes the compilation and optimization of C-codes seamless and highly efficient. The C-code optimization was highly improved based on the unique designing features of TMS320C6000 series, such as proper choices of compiling options, the utility of intrinsics, the word processing technology, loop opening, pipeline technologies, linear assembly and etc.

Keywords: Digital image processing technology TMS320C6000 C code optimization

2

目录:

引言…………………………………………………………………….4 第一章 数字图像处理的基本知识............................4

1.1 数字图像处理简述…………………………………………………4 1.2 几种处理算法………………………………………………………4

第二章 TMS320C6000DSP芯片的特点..........................6

2.1 数字信号处理器的特点 ………………………………………… ..6 2.2 TMS320C6000 的硬件结构简介……………………………...…..7 2.3 TMS320C6000 指令系统………………………………………...10.

第三章 基于TMS320C6000DSP系列的代码优化…………………..…….11

3.1 第一个阶段代码优化…………………………………………….….11 3.2 第二个阶段代码优化…………………………………………….….13 3.3 第三个阶段代码优化…………………………………………….….17

第四章 对所编C代码进行优化处理......................................................20

4.1 小循环的打开………………………………………………….......20 4.2 较大循环的打开 ………………………………………………21

结论................................................................................................................22 致谢语……………………………………………………..……………………….24 参考文献………………………………………………….……………………….24

3

随着计算机技术的发展,数字图像处理技术以其广阔的应用领域,受到人们 越来越多的关注,本次实验是以 DSP 为平台,对数字图像处理系统进行仿真。 由于图像处理需要处理大量的数据,并且对运算速度提出了很高的要求,因此我 们选用 DSP 平台,并根据它的结构特点,对所编的 C 代码进行了优化,极大地 提高了运算速度

第一章 数字图像处理的基本知识

第一节 数字图像处理的概述

数字图像处理(Digital Image Processing)又称为计算机图像处理,它是指 利用计算机和其它高速、大规模集成数字硬件,对从图像信息转换来的数字电信 号进行某些数字运算或处理,以期提高图像的质量或达到人们所预想的结果。

数字图像处理方法大致可分为两大类,即空域法和变换域法。

1、空域法 这种方法是把图像看作是平面中各个像素组成的集合,然后直接对这一二维

函数进行相应的处理。空域处理法主要有下面两大类。

(1)领域处理法 包括梯度运算、拉普拉斯算子运算、平滑算子运算和卷积运 算。

(2)点处理法 包括灰度处理及面积、周长、体积、重心运算等。

2、变换域法 数字图像处理的变换域处理方法是首先对图像进行正交变换,得到变换域系

数阵列,然后施行各种处理,处理后再反变换到空间域,得到处理结果。

在我们的设计中采用的是空域法中的域处理法.

第二节 几种图像处理算法的介绍

对于一张数字图像,我们采用 RGB 模式真彩色位图来表示它,一张图像由

4

像素矩阵构成,每个像素包含它对应的位置信息,以及 RGB 三个通道各自亮度 值的大小,R 对应红色,G 对应绿色,B 对应蓝色,它们统称为三基色,这三 中色彩的不同搭配,就可以搭配成各种现实中的色彩。如果是单色图像,只要让 三个通道的值相等就可以了 。

在实现数字图象处理的过程中,主要是通过对图像中的每一个像素点运用各 种图像处理算法来达到预期的效果,在本实验里主要涉及了卷积运算,相关运算, 中值滤波。

1 卷积运算:

使用一个 m*n 的掩模,依次覆盖在要处理图像的各个像素上,掩模中心与 该像素重合。掩模上的各个元素均有其自身的权值。将掩模各元素权值与覆盖在 其下的像素值分别相乘后求和,在除以掩模权值之和,所得结果称为响应,赋给 当前处理的像素。通过选取不同的矩阵,我们可以对图像得出很多不同的结果, 这个结果取决于所选取的卷积矩阵不同,可以是高通滤波,低通滤波等等,通过 滤波我们可以得到所需要处理图像的一些特性,比如可以采用高通滤波突出某些 边缘轮廓,用低通滤波来平滑图像,去掉图像中的高频成分。

2 相关运算:

图像的相关性运算与卷积运算基本上类似,不同点是卷积矩阵 mask 取自图 像本身的某一块值,这里不对相关性的图像处理做图像处理,主要说明一下相关 性的意义。利用相关性可以检测出图像的矩阵模板,用于模板的匹配,检测等等。

3 中值滤波:

同样使用一个 m*n 的掩模依次处理各个像素,但是掩模没有权值,而是将 掩模覆盖下的像素值排序后取中间值,将这个中值赋值给当前处理的像素。

中值滤波可以将图像中的高频成分去掉,使图像变得平滑,这个特性和低通 滤波有点类似。

掩模在图像边缘时,会遇到覆盖了非图像部分的情况,这里可以有多种方式 处理,比较常见的有部分滤波和补零法(zero-padding)。部分滤波为在遇到图像 边界时,忽略超出图像边界的部分,采用部分掩模处理边界像素。补零法是将图 像边缘部分补上相应于掩模大小的零值(也可以为其它常值),处理完成后再将这 部分切除,恢复至原图像大小,但是这样图像边缘往往会出现灰度值偏小的情况。

5

一般来说图像边缘往往是不重要的部分,所以这些处理带来的缺点是可以容忍 的。

第二章、TMS320C6000 DSP 芯片的硬件系统

第一节 数字信号处理器的特点

1 算术单元 硬件乘法器

由于 DSPS 的功能特点,乘法操作是 DSPS 的一个主要任务。在通用微处 理器内是通过程序实现乘法操作的,这往往需要耗费很大的时钟周期,因此在 DSPS 内部设有硬件乘法器来完成乘法乘法操作,以提高乘法速度。所以硬件乘 法器是 DSP 区别于通用微处理器的一个重要标志。

多功能单元

为进一步提高速度,可以在 CPU 内设置多个并行操作的功能单元(ALU, 乘法器,地址产生器等)。如 C6000 的 CPU 内部有八个功能单元,即两个乘法 器和六个 ALU,八个功能单元最多可以在一个周期内同时执行八条 32 位指令。由 于多功能单元的并行操作,使 DPS 在相同时间内能够完成更多的操作,因而提 高了程序的执行速度。

2 总线结构 通用微处理器是为计算机设计的,通常采用冯诺依曼总线结构,统一的程序

和数据空间,共享的程序和数据总线,由于总线的限制,微处理器执行指令时, 取指和存取操作数必须共享总线,因而程序指令只能串行执行。对于 DSP 而言, 采用冯诺依曼总线结构将使系统的性能受到很大的限制,因此 DSP 采用了独立 程序总线的哈弗总线结构,而且很多 DSP 甚至有两套以上内部数据总线,这种 总线结构称为修正的哈佛结构,对于乘法或加法等运算,一条指令要从存储器中 取两个操作数,多套数据总线就使得两个操作数可以同时取得,提高了程序效率

3 专用寻址单元

6

DSP 面向的是数据密集型应用,因为需要频繁地访问数据,数据地址的计 算时间也线性增长,如果不做特殊处理,计算地址的时间有时会比实际的算术操 作时间还长。因此,DSP 通常都有支持地址计算的算术单元——地址产生器与 ALU 并行工作,因此地址的计算不再额外占用 CPU 时间

4 流水处理

除了多功能单元外,流水技术是提高 DSP 程序执行效率的另一个主要手段。 流水技术使两个或更多不同的操作可以重叠执行,流水线操作是 DSP 实现高速 度、高效率的关键技术之一。TMS320C6000 只有在流水线充分发挥作用的情况 下,才能达到 1600MIPS 的速度。C6000 的流水线分为三个阶段:取指、解码、 执行、总共 11 级。和以前的 C3x、C54x 相比,有非常大的优势,主要表现在: 简化了流水线的控制以消除流水线互锁;增加流水线的深度以消除传统流水线结 构在取指、数据访问和乘法操作上的瓶颈。其中取指、数据访问分为多个阶段, 使得 C6000 可以高速地访问存储空是。

5 大容量片内存储器

大容量片内存储器外部存储器一般不能适应高性能 DSP 核的处理速度, 因 此在片内设置较大容量的程序/数据存储器以减少对外部存储器的访间速度, 充 分发挥 DSP 核的高性能,数据 RAM 的容量高达 7MB。采用大的片内存储器可以 减少外部存储器接口的引脚, 甚至省略外部存储器接口, 而且还可以减小芯片的 封装体积。

6 零消耗循环控制 数字信号处理的一大特点是很多运算时间都用在执行较小循环的少量核心

代码上大部分 DSP 芯片具有零消耗循环控制的专门硬件, 可以省去循环计数器 的测试指令, 提高了代码效率, 减少了执行时间。

第二节 TMS320C6000 的硬件结构简介

TMS320C6000 系列 DSP(数字信号处理器)是 TI 公司最新推出的一种并 行处理的数字信号处理器。它是基于 TI 的 VLIW 技术的,它包含两个子系列: 用于定点计算的 TMS320C62X 系列和用于浮点计算的 TMS320c 67x 系列其中, TMS320C62xx 是定点处理器,TMS320C67xx 是浮点处理器。以 TMS320C6201

7

为例,该处理器的工作频率最高可以采用 50MHz,经内部 4 倍频后升至 200MHz, 每个时钟周期最多可以并行执行 8 条指令,从而可以实现 1600MIPS 的定点运 算能力,而且完成 1024 定点 FFT 的时间只需 70μs。

TMS320C6000 的 CPU 有两个数据通道 A 和 B,每个通道有 16 个 32 位字 长的寄存器(A0~A15,B0~B15),四个功能单元(L,S,M,D),每个功能 单元负责完成一定的算术或者逻辑运行。A、B 两通道的寄存器并不是完全共享, 只能通过 TM320C6000 提供的两个交换通道 1X、2X,才能实现处理单元从不 同通道的寄存器堆那里获取 32 位字长的操作数。TMS320C6000 的地址线为 32 位,存储器寻址空间是 4G。

各个部分简要介绍:

C62X 和 C67X 的数据通路包括:

2 个通用寄存器组(A 和 B)8 个功能单元(.L1,.L2,.S1,.S2,.M1,.M2,.D1,D2) 2 个存储器读取通路(LD1 和 LD2)2 个存储器存储通路(ST1 和 ST2) 2 个寄存器组交叉通路(1X 和 2X)2 个数据寻址通路(DA1 和 DA2) 1 通用寄存器组

C62X/C67X 数据通路中有 2 个通用寄存器组(A 和 B): 寄存器组 A:A0-A15,寄存器组 B:B0-B15。

8

条件寄存器: A1、A2、B0、B1 和 B2 可用于循环寻址的寄存器:A4-A7 和 B4-B7。

通用寄存器组支持 32 位和 40 位定点数据,C67X 也支持 32 位单精度和 64 位双精度浮点数据。对于 40 位和 64 位数据,需跨放在两个寄存器内。

2 功能单元

8 个功能单元分成 A、B 两组:A 组:L1、S1、M1、D1 B 组:L2、S2、 M2、D2

每个功能单元都有:2 个 32bit 读口和 1 个 32 位写口

.L1、.L2、.S1 和.S2 另有:8bit 写口和 8bit 读口,支持 40 位操作数的读写 同一周期 8 个功能单元可并行使用

各个功能单元的执行操作 功 能

浮 点 操 作 .L 单元(.L1,.L2) 32/40 位算术和比较操作 算术操作 32 位中最左边 1 或 0 的位数计数 转换操作 32 位和 40 位计数 DP→SD INT→32 位逻辑操作 DP INT→SP .S 单元(.S1,.S2) 32 位算术操作 32/40 位移位和 32 位位操作 32 位逻辑操作 转移 常数产生 寄存器与控制寄存器传递(仅.S2) .M 单元(.M1,.M2) 16×16 乘法操作 比较倒数和倒数平方根 操作 绝对值操作 SP→DP 转换 单 元 结构示意图

定 点 操 作 32×32 乘法操作 浮点乘法操作 .D 单元(.D1,.D2) 32 位加、减、线性循环寻址计算 5 位常数偏移量双字读 5 位常数偏移量取存 取 15 位常数偏移量取存(仅.D2) 3 寄存器组交叉通路 9

CPU 中有两个交叉通路 1X 和 2X

1X:允许 A 侧功能单元读取 B 组寄存器数据

2X:允许 B 侧功能单元读取 A 组寄存器数据 每侧仅有一个交叉通路,在同一周期内从另一侧寄存器组读操作数只能一 次,或者同时进行使用 2 个交叉通路(1X 和 2X)的操作。

.D 不能使用交叉通路仅 src2 可以使用另一侧寄存器数据

第三节 TMS320C6000 指令系统

C62xx 和 C67xx 共享同一个指令集。所以 C67xx 可以使用所有的 C62xx 指令,但因为 C67xx 是浮点芯片,怕以 C67xx 的指令集中有一些指令只能用于 浮点运算。TMS320C6201CPU 的设计采用了类似于 RISC 的结构,指令集简单、 运算速度快。8 个功能单元负责不同功能的运算,指令和功能单元之间存在一个 映射关系。其中,L 单元有 23 条指令,M 单元有 20 条指令,S 单元 29 有条指 令,D 单元有 26 条指令。

TMS320C6201 的大部分指令都可在单周期内完成,都可以直接对 8/16/32bit 数据进行操作。同时,TMS320C6201 指令集针对数字信号处理算法 提供了一引起特殊指令:为复杂计算提供的 40bit 的特殊操作的加法运算;有效 的溢出处理和归一化处理;简洁的位操作功能等。TMS320C6201 中最多可以有 8 条指令同时并行执行;所有指令均可条件执行。以上所有特点提高了指令的执 行效率、减小了代码长度、大大减少了因跳转引起的开销、提高了编码效率。

10

第三章 基于 TMS320C6000 系列的 C 代码优化

在 DSP 软件开发中推荐的开发流程如图 1 所示

于是我们可以份三个阶段来优化所写的 C 语言代码 第一个阶段:对第一个阶段,我们根据需要实现的功能来编写 C 语言程序,

这时的代码和硬件平台是独立的,可以进行一些基本的 C 优化,然后使用 C6000 代码剖析工具,确定 C 代码中可能存在的低效率段,为进一步改进代码性能, 进入第二阶段。

第二个阶段:在这一阶段,我们根据 TI,C6000 平台一些基本的结构特点,

11

使用特定的优化方法,改进 C 代码。这些方法包括使用编译器选项、和代码转 换字访问、软件流水和循环展开等。如果代码仍不能达到所期望的效率,则进入 第三个阶段。

第三个阶段:从 C 代码中抽出对运行时间影响最大的代码段,用线性汇编 改写这段代码。用户能使用汇编优化器优化该代码。

第一节 第一个阶段代码优化

第一阶段的优化是基于通用微处理器的 PC 机环境中的优化,主要是针对 C 程序的通用特性来考虑的。这方面的优化工作主要包括数据类型选择、数值操作 优化、快速算法、变量定义和使用优化、函数调用优化以及计算表格化等.这个 阶段的 C 代码优化,可以通过选定 CCS(Code Composer Studio)提供的 C 编 译器的选项来实现优化,所以不详细展开,但有几点与 C6000 的硬件结构有关, 需详细说明下

1 数据类型 数据类型的选择在分析和编写代码时很重要,充分考虑数据类型大小才能从

C6000 体系结构中取得最优的性能。C6x 编译器对每种数据类型都定义了数据 大小。char :8 bit ; short : 16 bit ; int :32 bit ; long :40 bit ;float :32 bit ;double :64 bit 基于每一种数据类型的大小,在书写 C 代码时,应注意以下原则。(1) 要避免 把 int 和 long 数据类型当成相同大小来处理,因为 C6x 编译器对 long 数据使 用 40 bit 操作数;(2) 定点乘法,尽量采用 short 型作为输入,因为 C6x 上是一

16 的乘法器;个 16?(3) 用于循环的计数器,数据类型采用 int 或者 unsigned int

以避免汇编器产生不必要的符号扩展指令;(4) 当在浮点 DSP 装置中使用浮点 指令时,例如 C67x 应使用-mv6700 编译器开关,使得代码产生器符合浮点的 硬件装置代码。

2 数值操作优化

C 程序中主要有以下数值操作优化:(1)用比特的移位操作来代替 2 次幂整 数的乘除法运算更为有效;(2 )当使用浮点设备时, 尽量使用浮点数据类型,这 能够减小定点处理单元的负担;(3) 尽量避免数值的上下溢出,除非是算法本身 的需要。

3 快速算法

12

本优化方法是用快速算法实现各种变换。例如离散傅立叶变换(DFT)是数字 图像处理中应用十分广泛的一种变换,具有很好的实用性,其快速算法——快速 傅立叶变换(FFT)对其计算速度又有非常大的改进,从而使得该算法得到了更 加广泛的应用。

4 变量定义和使用优化

C 程序中对于需要多次重复使用的变量,如 for 循环中的变量值,一般可以 设置成 register 变量,从而提高效率。另外在 C 语言中指针和数组是可以相互 替代的,而对于数组的寻址非常耗时,特别是多维数组,因此可以通过降低数组 的维数,再指针化,从而提高效率。

5 函数调用优化

函数调用会产生大量的代码,开销也很大。当 C 调用一个函数时,它首先 把参数传递给寄存器或者堆栈,如果函数参数很多,则调用开销将很大。因此要 尽量避免传递结构,一般用结构指针代替。另外,限制局部变量的数目也有利于 提高效率。对于 C++用户,可以用 inline 技术消除函数调用的开销,但这样往 往以增加目标代码的大小为代价,在实际开发中要根据需要综合考虑。

6 计算表格化 在数值运算中,除基本的加减乘除运算外,还有其它许多非线性运算,如对

数运算、开方运算、指数运算、三角函数运算等,实现这些非线性运算一般采用 查表法。查表法是快速实现非线性运算最常用的方法。在实时 DSP 应用中,一 般采用这种方法必须根据自变量的范围和精度要求制作一张表格。查表法求值所 需的计算就是根据输入值确定表的地址,根据地址就可得到相应的值,因而运算 量较小。

第二节 第二个阶段代码优化

第二个阶段可以利用如下技术来提高性能:

1 使用 C6x 编译器选项

C6X 编译器具有很高的效率,它可将 C 代码转换成更高效率的汇编语言源 代码,进而进行汇编和连接,产生可执行的目标代码,在编译选项中有许多与 C 优化器直接相关的选项,我们可以通过对她们的设置,来实现优化代码的目的。

C6000 的优化器是 TI 公司的一个创新, 它对程序循环的流水处理使得代码

13

的效

率得到很大提高。其使用也很简单, 只要在编译时加人优化选项即可。采用 优化选项进行优化后, 点积函数可的执行时间有大幅减少,性能提高了很多

表 1 给出了与优化器有关的编译选项

选项 说明 文件级优化选项,与-pm 合用,可进行程序级优化,x 是数字 0,1,2,3 使语法分析器在启动优化器和代码产生器之间,把所有的 C 文 -pm 件合成一个文件来处理,这样做,可以对整个程序进行优化, 使优化效率更高 向编译器说明在程序中没有出现 aliasing。有了这个信息, -mt 优化器在进行优化时效率就可能更高,选项-ma 与-mt 相反, 它通知编译器在程序中使用了 aliasing,因而在优化时会更 谨慎 内联选项。使用-x2 之后,编译器会对于小于指定长度的函数, -x2 以及使用了 inline 关键字的函数进行内联处理,在进行三级 优化时,内联选项自动启用。 -ml 大模式选项,大模式选项用于说明程序中使用超过了 32k 字节 的 static 和 global 变量:如果不特别指明是 near,编译器会 把每个变量都作为 far 变量处理 -g 符号调试选项,符号调试选项-g 会使许多与符号调试不兼容 的优化手段无法使用。二级优化是与符号调试兼容的最高优化 级别 -s,-ss,-os 交叉列表功能选项。在最初功能调试阶段,把 C 语句,汇编语 句以及编译器注释放在一起,对调试会有帮助,但可能会影响 代码的优化 -ox 当优化器被激活时,将完成图 2 所示的过程。C 语言源代码首先通过一个完 成预处理的解析器(Parser),生成一个中间文件(.if)作为优化器(Optimizer)的输 入。优化器生成一个优化文件(.opt),这个文件作为完成进一步优化的代码生成 器(Code generator)的输入,最终生成汇编文件(.asm)。当选择编译选项时,-o2 和-o3 将尽可能地优化软件。如下图所示:

14

编译器优化 C/C++程序流程

C/C++语言 源程序

解析器 优化器 代码生 成器 .if 文件 .opt 文件 .asm 文件

编译器工具也包括一个外壳程序,利用它,程序可一步完成代码的编译,汇 编优化,汇编和连接。 调用外壳函

数需键入下列命令:

cl6x[options]{filenames}{-z[linker options]{object files}}如: 不带优化选项进行编译,即功能验证时,cl6x-g-s file.c-z; 用最高级别优化选项进行编译 cl6x-03-pm film.c-z 用优化级别 o2 进行编译 cl6x-g-o file.c-z 注意每个步骤都要进行功能验证

2 用 C6x 编译器内部函数来代替复杂的 C 代码;

内联函数 intrinsics:直接与 C62xx 汇编指令相对应的特殊内联函数,没有函 数调用开支。TMS320C6X 提供了很多内联函数,它们直接映射为内嵌 C6X 汇 编指令的特殊函数,这样可迅速优化 C 语言代码。C 编译器以内联函数的形式 支持所有 C 语言代码不易表达的指令。内联函数用下划线“_”开头,使用时同调用 函数一样调用它,尤其在需要大量 C 代码才能表示的复杂功能时,应尽量用 C6x 的内部函数表示。例如执行饱和加法的 C 代码需要多个周期,若引用 intrinsics, 则这些复杂的代码可以通过一条单独指令_sadd()取代。C6000intrinsics 中有些 指令如_ass2(),_mpyhl()和_mpylh()是对存储在 32 位寄存器的高 16 位和低 16 位字段进行操作。当对一连串短型数据进行操作时,可使用字(整型)一次访问 2 个短型数据,然后使用 C6000 intrinsics 对这些数据进行操作,从而减少对内 存的访问。

3.对短字长的数据使用宽长度的存储器访问,即字处理技术

15

要提高 C6000 数据处理率,应使一条 Load/Store 指令能访问多个数据。 如使用字访问存放在 32 位寄存器的高 16 位和低 16 位字段的数据,使用双字 访问存放在 64 位寄存器的 32 位数据。这样一条指令就能同时处理两个数据, 再配上前面所说的内联函数,如_mpyh,(数据的高十六位相乘)_mpy(数据的低 十六位相乘),可以极大地提高运算速度。要实现上面的优化还碰到一个问题是: 如何对十六位数据进行三十二位的访问。

这里列举三个方法:

1) 联合 Union

,把要访问的 16 位 short 类型定为 union 位类型定义为类型, 方法如下

Typedef union {

Short a[4]; Int w[2]; } data_union; Data_union x={1,2,3,4}; Short y;

Int z; Y=x.s[2];//访问十六位数

据 Z=x.w[1];//访问三十二位数据

2) 强制类型转换

Short x[4]={1,2,3,4}; Short y,*xp=x; Int z; Y=*xp; Z=*(int*)xp;

//访问 16 位数据 //访问 32 位数据

3)把数据直接定义为 32 位字

Int x[2]={0x0002000};

Int z*xp=x;

下面具体举例说明字处理与内联函数结合在一起的应用

short DP(short *m, short *n, short count)

{

short i ; int pro_h, pro_l ; int sum_h = 0 ; int sum_l = 0 ; int sum = 0 ;

int *data_a = ( int *) m ;/这里用来实现强制类型转换,现在的指针一次

16

取就可以取出十六位,即原来数组中两个元素,一个放在高八位,一个放在低八位

int *data_x = ( int *) n ;

count = count >> 1 ;/COUNT 变为原来的一半 for(i=0;i

pro_l = _mpy( data_a[i], data_x[i]) ;/_mpy 是内联函数,它的功能

是把寄存器低八位的两个数相乘,结果给 pro_l

pro_h = _mpyh( data_a[i], data_x[i]) ;/_mpyh 也是内联函数,它是

把高八位的两个数相乘,结果给 pro_h

sum_l += pro_l ; sum_h += pro_h ; }

sum = sum_l + sum_h ; return( sum) ;

}

4 软件流水线技术的使用

软件流水线技术用来对一个循环结构的指令进行调度安排,使之成为多重迭 代循环并行执行。必须指出的是,只有当循环计数器大于一定值的时候才能进行 以上优化,在编译时使用-o2 和-o3 选项,编译器可对循环代码实现软件流水。 软件流水线的循环结构图如下图 所示。在图中用 A、B、C、D、E 表示循环的 各次迭代,其实的数字表示各次迭代的第几条指令,同一行的指令是同一周期内 并行执行的指令。同一周期内最多可执行 5 次迭代的不同指令(阴影部分)又称 为循环核,核前部分叫做循环填充,核后部分叫做循环排空。

A1 B1 C1 D1 E1

A2 B2 C2 D2 E2 A3 B3 C3 D3 E3 A4 B4 C4 D4 E4 A5 B5 C5 D5 E5 流水线填充 循环内核 流水线排空

5 循环结构中的代码展开

改进性能的另一种方法就是展开循环,这种优化方法可增加并行执行的指令 数,当单次迭代操作没有充分利用 C6x 结构的所有资源时,可使用循环展开提

17

高性能,展开循环结构的代码对于编译器利用软件流水线技术也有很大的好处, 因为汇编优化器只针对最内层的循环进行优化,因此,为了提高性能可创造一个 比较大的内循环。创造大的内循环的一个方法就是完全展开执行周期很少的内循 环。同时,因为展开循环会增加代码尺寸,所以我们必须在代码大小与运算时间 之间做出取舍。

第三节 第三个阶段代码优化

如果经过前两步的优化,代码还不能达到要求的话,我们可以进入第三阶段 的优化。由于汇编语言具有高效性,所以可以利用代码剖析工具从 C 代码中抽 出效率低的部分,然后用汇编语言改写它。,这里有两种方法可以进行汇编优化。 一种是使用线性汇编重新改写,然后用 CCS 提供的汇编优化器对改写的线性汇 编进行优化得到最终优化的汇编代码;另一种方法是直接对这部分代码进行手工 改写,得到优化的汇编代码[]。第二种方法需要程序员对 C6000 系列芯片的内 部结构非常了解,所以我们一般用第一种办法,采用线性汇编改写 C 代码。

线性汇编与普通的 C6x 汇编很相似,都使用汇编指令书写代码。不同的是, 线性汇编不需要书写普通汇编时必须提供的所有信息(如指令是否并行执行、指 令的标号、流水线的延迟、寄存器的使用和功能单元的使用等) 。汇编优化器从 输入的线性汇编代码中,完成以下功能:(1) 寻找哪些 CPU 指令可以并行执行; (2) 在软件流水线期间,处理流水线标号;(3) 分配寄存器的用法;(4) 定义使用 哪个功能单元。

1 线性汇编优化技术

下面用定点点积来具体举例说明用线性汇编优化代码的过程。

例 2 定点点积的 C 代码

short dotp(short a[], short b[])

{ int sum, i; sum = 0;

for(i=0; i<40; i++) sum += a[i] * b[i]; return(sum); }

把 C 代码改编成线性汇编指令

loop:

ADD .L1 A4,A5,A5;

18

|| MPY .M1X B4,A3,A4; || [B0] B .S2 loop;

|| [B0] SUB .L2 B0,0x1,B0; || LDH .D2T2 *B5++,B4; || LDH .D1T1 *A0++,A3;

上述定点点积的 C 代码没有经过优化的时候需要 1787 个指令周期,经过 线性汇编的优化以后只需要 120 个周期,效率得到提高。在实际的开发过程中 常常用这种方法对 C 代码进行汇编优化

2 手工汇编优化技术

所谓手工汇编优化,就是对 C 代码编译产生的汇编代码进行手工优化改写。 在某些性能要求比较苛刻的开发中,有时需要程序员对程序进行手工的汇编优 化,以发挥 DSP 性能的极致。手工汇编优化方法是首先写出要优化的 C 程序 代码段的一般汇编形式,然后对应一般汇编形式画相关图并分配资源,然后写出 与相关图对应的汇编代码。通常的优化策略包括:1 写并行代码 2 有对短数据(16 bit) 使用字(32 bit) 访问、3 软件流水线技术、4 多周期循环的模编排、5 循环展 开等[4],这里不再具体介绍。

19

第四章 对所编的 C 代码进行优化处理

第一节 小循环的打开

(1)for(l=0;lheight-2;l++) {///中间滤波

for (i = 0; i width-2; i++) {

sum = 0;

for (j = 0; j < 3; j++) {

for (k = 0; k < 3; k++) {

sum += p[(l+j)*in_data->width + i + k] *mask[j*3 + k]; } }

sum = (sum >> shift);

sum = (sum > 32767)? 32767 : (sum < -32768 ? -32768 : sum); OUT[(l+1)*in_data->width+i+1]=(short)sum; } }

在这里,由于 j k i 都不是很大,于是我们可以把里面的几层循环都打开,程序可 以改为,

for(l=0;lheight-2;l++)

{///中间滤波

for (i = 0; i width-2; i++)

20

本文来源:https://www.bwwdw.com/article/7sa5.html

Top