专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
DSP
ADI Blackfin处理器的C语言编程与优化——内存Memory和Cache优化
2019-07-13 18:50
发布
生成海报
站内文章
/
DSP
16476
0
1260
以上章节讲述了在ADI Blackfin系列上的C语言优化方法,如何利用DSP的特性进行循环和条件控制语句的具体优化策略,该部分则主要讲述如何优化memory的性能,以及如何实现速度speed vs. 代码大小size的折衷。
Programming and Optimizing C Code on Blackfin
ADI Blackfin处理器的编程与优化
Part 5. Memory优化
内存性能
编译器往往把内存视为统一的无限大小的资源,可以在存取是不存在任何额外的开销。这是个理想的
flat memory
模型,但是在现实中
,
存储器的存取开销将直接影响你的应用程序的性能。因此我们需要学习内存对我们程序性能的影响。大多数
DSPs
都能访问内部
(on-chip)
和外部
(off-chip)
的内存空间。但是片内的快速存储器
(
通常静态存储器
)
和片外的慢速内存
(
通常
SDRAM)
有非常巨大的性能差距。编译器很少能自动智能的防止数据的代码,因此需要由程序员把程序内最
most-critical
程序代码和数据放在片内的存储空间,而其他的放在片外。这通常是通过一个连接器控制文件来完成的。你也可以告诉链接器如何将特定的数组和代码放置在存储空间。例如
,
下面的声明告诉链接器将数组放在
L1 data
数据空间。
片内存储器的访问速度取决于数据访问模式,在理想的情况下
,
大多数
DSPs
可以在每个周期内访问两个数据。然而
DSP
的片内存储器通常是分成几个
Bank,
同一个
Bank
如果接收到两个同时的数据访问请求时会产生
stall
。不幸的是
,
编译器不知道是否两个数据是否会分布在同一个
Bank
因为数据的放置位置是由链接器完成的。一个比较好的解决办法是用
pragma
来指导编译器。
Blackfin
提供了指定不同的
bank
的
pragma
来告诉编译器数据来自不同的
bank
,从而可以更为激进的在同一个周期做两次数据访问。
片外存储器访问的速度取决于存储器的性能、速度以及处理器和内存间的总线宽度。在许多
DSPs
中
,
程序员可以选择存储器总线的速度。为了节省功耗,可以选择更为低速的存储设备,然是不弱你的程序对性能要求很高,你可能就需要选择更为高速的存储设备。一个硬件系统中,可以设定处理器频率和内存频率的分频比,即
CPU
的频率需要是内存频率的一个特定倍数,如图
1
是
ADSP-BF533 Blackfin
处理器的内存速度配置和
CPU
频率的比率关系,需要注意的是内存总线最大速率为
133 MHz
。
图
1. ADSP-BF533
的
CPU
频率和内存频率配置
图
2
的分析可以看出外部存储器性能的重要性。第一排
(L1)
显示有
single-cycle
内存访问,第二行
(L3
缓存
)
是
Cache
缓存结果,第三行
(L3)
显示的是在一个
un-cached
系统,在这种情况下,连的
16
位传输需要带
40
个周期。值得注意的是,这里内存的访问的消耗代价将抵消任何优化的编译器带来的好处。外部存储器拥有一个结构行
(
也许在一排占据
4 kB)
和一个更大的结构的
Bank
。当存储访问从一行移动到下一个时,将需要增加一个额外的延迟,该延迟并不是很严重的性能损失,连续内存的访问很容易摊薄这个延时,而随即访问导致的连续变换的行讲导致非常严重的性能损失。
图
2.
不同情况下的内存访问周期数
.
图
2
的一个自然的反应来可能依靠缓存
cache
来提高性能。显然缓存将内存访问的代价大大降低。但需要注意的是,顺序访问外部存储器的代价还是从
L1
缓存的
7.7
倍。如果你
re-use
重用数据,缓存数据的性能将大大提升。因此你应该考虑修改你的数据访问模式,尝试在循环内尽可能重用数据,而不是不断从外部存储器获取新的数据。这种
cache
的优化,编译器可以给你帮助不大。如在第一部分中所述你可以通过
profiler
来发现一个内存访问的代价过大的问题,大量的不明原因的
load/store stall
产生时,你需要重新思考你的内存使用情况。
代码的速度
vs
大小
Code Speed vs. Space
小程序有很多好处,代码
size
小了能放到
L1
片内存储空间,所以小代码可以提高应用程序的速度。较小的代码也许并不需要外部存储器,进而降低成本和能耗。编译工具通常会帮助你优化你的程序的大小。你可以要求优化的最大速度,您可以要求最低代码大小,或者你可以追求速度和空间的一种平衡。通常情况下,你可以给编译器一个低层次的指导来告诉编译器那些文件要求速度优先,哪些文件要求空间优先。图
3
显示的是不同的编译选项情况下选择速度优先和选择空间优先的代码空间变化。
图
3.
不同优化选项下的代码大小变化
两个优化
选项造成代码大小的重大区别。第一个是
inlin
e
功能
,那是有点惊讶,但同时也警告我们弄清楚你的编译器如何积极的追求速度不惜一切代价。
"
其他造成代码大小变化的是代码优化扩展,主要来自于对循环的优化。大量使用这些优化技术,如循环展开和流水线。最大化的利用
16
位数据偏移,而不是用
32
位的地址计算则有
2%
的增益。
一件需要注意的小事实是内存的边缘。程序员往往将数据数组在第一个地址或直到最后地址的数据。然而这导致了不利于软件流水的问题。软件流水是最强大的优化编译器方法,因为它允许
DSP
取下一个数据集的同时处理早先的数据。当一个数据数组被放在一个内存边缘时,最后一次循环的迭代将试图取位于内存空间之外的数据,这将引起一个地址错误。为了避免这个问题,编译器减少循环数,并把循环的最后一次迭代作为一个
epilog
迭代循环。这保证了代码的安全,但它同时也增加了许多指令代码。为了避免这个代码大小的增加,
Blackfin
有
"-extra-loads "
编译选项。这个选项告诉编译器是继续加载一个数组的元素师安全的。
现代的编译器尝试通过提供智能的空间和速度的优化。例如,
Blackfin
编译器提供了一个选择从
0%
提高到
100%
空间优化策略。编译器根据指定的目标来理解每个循环的空间优化。这个编译器也评估根据应用程序仿真的结果,对不经常执行的代码块采取空间优化策略,而对经常执行的代码块则是速度优化。因此编译器非常智能和灵活,下面来看编译器的表现。图
4
是一个测试程序,一个
JPEG
编码器,采取速度最大化优化和代码
space
优先的关系,我们可以在速度和空间二者中选择一个折中。
图
4. speed/size
编译器的折中
如果你对全自动优化不感冒,或你不能用仿真的过程,你也可以手动处理这个问题。图
5
显示的是你对不同文件采取速度和空间优先编译时的影响。
图
5.
单独文件
speed/size
优化结果,
%
列显示的是该文件占整个优化程度的比例。如
fileio.c
占整个可能速度优化的
24.95%
图
5
中,从
"
速度
"
一栏我们看到了不同速度和优化空间。只有黄 {MOD}标示出的文件显示出显著的效果。这告诉我们我们大部分的应用可以被编译器以中立的态度来处理或者以节省空间策略处理。同样的右边栏目显示代码相同条件下大小的变化。只有用蓝 {MOD}高亮的文件显示出显著的效果。唯一需要仔细考虑的文件是那些显示在两个黄 {MOD}和蓝 {MOD}。对许多人来说最好的优化设置是显而易见的。有趣的是,大多数黄 {MOD}标示的文件和蓝 {MOD}高亮的文件并不相符。这也说明一个小小的分析可以极大地减少错综复杂的优化选择。
Reference
http://www.eetimes.com/design/signal-processing-dsp/4017462/Programming-and-optimizing-C-code-part-5?pageNumber=1
http://en.wikipedia.org/wiki/Cache_algorithms
http://www.blog.163.com/houh-1984/
以上章节讲述了在ADI Blackfin系列上的C语言优化方法,如何利用DSP的特性进行循环和条件控制语句的具体优化策略,该部分则主要讲述如何优化memory的性能,以及如何实现速度speed vs代码大小size的折衷
Ta的文章
更多
>>
ADI Blackfin处理器的C语言编程与优化——内存Memory和Cache优化
0 个评论
热门文章
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮