FPGA计算性能优化--数据运行优化1

来源:互联网 发布:php企业产品展示网站 编辑:程序博客网 时间:2024/05/20 01:44

前一节里面简单介绍了数据访问优化的几种方式,接下来详解介绍一下:

1.DATA Motion network:

FPGA的数据传输网络是用来连接程序运行在PS端和PL端。SDSOC环境将会自动的创建一个基于数据类型的数据传输网络,但是我们可以使用指令来优化运行速率和硬件资源。

常规的数据传输类型有:

(1)Scalar:常量经常通过AXI_lite协议传输。

(2)Array:数组包含多个数据值,并且可有效的使用高速DMA传输协议。SDSOC环境提供了许多选项来控制硬件和资源的有效性,甚至允许特定的传输数据格式来应用在硬件上。

(3)Pointers:默认情况下,如果没有任何语法,一个指针参数被当作一个常量处理。如果一个指针多次写入或者读出,语法上应该保证数据传输的高效性。

(4)Strect or class:结构体和类

2.Memory Allocation/数据分配(关键词,使用sds lib分配连续的内存地址)

SDSOC编译器将会分析你的程序,进而选择一个合适的数据类型用于在软件和硬件上使用,数据的类型会根据负载的大小,加速器上的硬件接口和函数参数的属性而决定。当编译器可以保证一个数组参数位于连续的物理地址上时,它就可以使用最有效的数据传输。使用sds_lib函数库来分配数据或者内存映射数组时,可以确保编译器让内存访问使用连续的

地址。eg.

sds_alloc(size_t size);//使用连续的地址

当然有可能由于程序结构的原因,sdscc编译器不能够将数据分配到连续的地址上,这时候编译器会给出一个警告:

Warning:[DMAnalysis 83-4492]unable to determine the memory attributes passed to>.......

这时候你可以在需要连续分配地址的程序上加上一下代码来尽量是的数据分配是连续的(注意:这个函数并不一定确保是的数据分配是连续的,你必须还的sds_alloc来分配内存数据)

#pragma SDS data mem_attribute(A:PHYSICAL_CONTIGUOUS)//默认物理地址是非连续的

3.copy and shared memory semantics/复制和共享内存语义:(关键词:如何减少数据访问时间)

(1)通常情况下,硬件函数调用,涉及到函数参数的输入输出的复制。利用一个共享的内存模型对于硬件函数的参数而言是可行的,但是需要主要注意的是,在吞吐量爆炸式的传输下,从PL端口访问外部DDR的延时会明显高于CPU访问外部DDR(CPU频率高得多原因?)。SDSOC环境通过插入一下函数来声明共享内存:

#pragma SDS data zero_copy(A[0:<array>])//

(2)对于可综合的硬件功能,从共享内存(使用zero_copy函数)读取/写入单个数据通常是低效率的。一个更有效的办法是采用memcpy从内存中爆发式地读/写数据,并且将数据存储在本地内存中。(先从外地访问,然后再存储在片上缓存。)

(3)对于复制和零拷贝(内存共享)内存语义,另一个有效的替代办法是在PL和片外的DDR中传输数据,用于内存效率最大化。每当你需要非时序的硬件功能,可以使用硬件函数在本地内存中存储数据,用于重复访问变量。(应用PL端的资源来访问数据?)例如,在视频应用程序中通常有数据流入,并且存储在FPGA内存中,用于支持多种访问视频流数据的类型。对于数组数据传输,sdscc编译器通过硬件函数来允许数据流访问(也就是说,指定索引顺序后,每个元素将精确地被访问一次。)插入一下函数来立即指定函数的原型。

#pragma SDS data access_pattern(A:SEQUENTIAL)//access pattern =SEQUENTIAL |RANDOM 

对于数组作为指针类型传输给硬件函数,有时候编译器可以推断传输的大小,如果不能够推断的话,编译器会给出一下信息:

WARING:[DMAnalysis 83-4439]cannot determine data size for argument p of function foo

对此,使用以下特殊的数据传输长度:

#pragma SDS data copy(p[0:array_size])//eg.int *p

在每个函数的调用基础上,你可以改变改变数据的传输长度,以避免硬件函数在函数定义中不需要通过设置数组的长度(也就是说,函数参数都应该指明所有的变量大小)

#pragma SDS data copy(A[0:L+2*T/3])//scalar arguments L,T to same function

4.data cache coherency/数据缓存一致(关键词:注意考虑数据是否有PS端口访问)

对于每一个由系统要求的传输数据,sdscc/sds++编译器自动生成生成软件配置代码。系统默认的假设是保持在CPU和硬件函数之间的内存访问是一致的。

为了舍得内存访问一致性,编译器可以在传输数据到硬件函数之前执行缓存刷新,并将数据从硬件函数传输到内存之前执行缓存失效。(执行缓存刷新,将原始的缓存失效,以免新来的数据等待???)(默认操作)

上面的操作的正确性是必要的,但是有时候会影响应用的性能。当你使用Zynq devece HP ports时,当你知道CPU不访问内存(应用程序的正确性不依赖高速缓存一致性),你可以重写以上默认。这样做可以避免不必要的缓存刷新开销。使用一下API来分配内存:

void *sds_alloc_non_cacheable(size_t size)

一个典型的应用就是视频缓存帧是由PL访问,不由CPU访问。

5 data access patters/数据访问模式(关键词:函数之间,函数内的数据访问模式对性能的影响)

由于FPGA的优越性能,FPGA被选中来实现C代码。一个FPGA的大规模并行架构允许它执行的操作比一个CPU处理器的固有的顺序操作的速度更快。用户通常都希望利用这一性能。

这里的重点理解是理解C代码中固有的访问模式对结果可能产生的影响。虽然最受关注的是那些进入和推出硬件功能的访问模式,但在硬件功能中的任何瓶颈都会对函数的访问速率产生负面影响,因此考虑函数内的访问模式也是值得考虑的。

为了突出强调某些数据访问模式如何对性能产生负面影响,并演示如何使用其他模式来完全支持FPGA的并行性和高性能功能,本节将通过一种图像卷积算法来阐述。

原创粉丝点击