Hexagon

Hexagon,第1张

Hexagon_DSP_User_Guide (1)
    • 3.5 VerifyanapplicationrunningontheDSP
    • 3.6 OverheadforaFastRPCcall
    • 3.7 OverheadforlaunchingDSPthreadsfromtheDSP
  • 4 OptimizetasksfortheDSP
    • 4.1 Programminglanguagesandextensions
      • 4.1.1 C/C++ support
      • 4.1.2 Halidelanguage
      • 4.1.3 Compilerintrinsics
      • 4.1.4 Assembly language

(1))

3.5 VerifyanapplicationrunningontheDSP

在使用模拟器时,可以直接为DSP编译代码并模拟该代码。这样就可以在不使用FastRPC调用的情况下测试一个功能。
然而,为了在硬件设备上运行,你通常必须实现一个CPU应用程序,对DSP进行FastRPC调用以调用一个工作负载。因此,典型的做法是实现一个简单的测试驱动程序,该驱动程序作为Android命令行应用程序用于设备测试,或作为Hexagon可执行程序用于模拟器测试。当作为Hexagon可执行文件构建时,测试驱动程序中的FastRPC调用直接链接到DSP应用程序中的骨架实现。
在安装Hexagon SDK和设置新设备后,熟悉用模拟器或设备构建和测试示例应用程序的过程。
本节的其余部分强调了该过程中涉及的主要步骤。关于更多的细节,请看在线SDK中包含和记录的一些项目实例,如计算器、downscaleBy2或基准。
在模拟器上使用FastRPC调用验证一个实现是很简单的:这可以通过下面的例子命令行来完成。

make tree V=hexagon_ReleaseG_toolv81_v62

这导致了用Hexagon DSP编译器和模拟器编译然后运行测试驱动和DSP代码。
在上面的例子中,v81意味着代码是用Hexagon工具的8.1版本编译的,V62意味着代码被编译为目标DSP变体V62。
在目标上验证同一实现涉及多个步骤。
1.为CPU编译主可执行文件,它负责进行FastRPC调用。例如,这是用以下方法完成的。

make tree V=android_ReleaseG

2.为DSP编译实现FastRPC功能的代码。比如说:

make tree V=hexagon_ReleaseG_dynamic_toolv81_v60

注意:动态关键字表示我们正在建立一个扩展名为.so的动态库。

3.6 OverheadforaFastRPCcall

一个特定的FastRPC调用的延迟取决于几个因素。
1. CPU构建配置
为了获得最佳效果,Android构建必须是性能构建。
2. CPU和内存的时钟速率
在正常运行期间,两者都受制于DCVS。
3. CPU调度延迟
这些延迟对DSP响应调用时的中断服务延迟有影响。它们可以根据各种CPU线程上可能运行的内容而变化。
4. 完成DSP调用的时间
DSP调用消耗的时间越多,CPU就越有可能进入较低的时钟或低功耗状态,在DSP响应时需要额外的唤醒步骤。
5. 正确使用共享缓冲区的ION内存 对于零拷贝的FastRPC来说是需要的。
6. CPU和DSP之间共享的缓冲区的可缓存性。 […]
如果缓冲区被配置为来自CPU端的非缓存(例如,它们来自摄像机硬件而不被CPU改变),则可避免CPU端缓存维护,并减少开销。
IO连贯性
对于与DSP共享的CPU缓存缓冲区,IO Coherence是默认启用的,但在每个缓冲区上是禁用的。
它在每个缓冲区的基础上被禁用。
IO-coherent缓冲区不需要CPU端缓存维护,这有利于减少FastRPC的开销,对共享缓冲区的总大小没有什么依赖性。然而,当DSP访问IO-coherent缓冲区时,由于在硬件中执行CPU缓存窥探 *** 作以确保一致性行为,可能会遭受一些性能损失。
非IO-coherent缓冲区的FastRPC往返开销较大,与共享的非IO-coherent缓冲区的总大小成比例。
在理想化条件下,FastRPC的往返开销在200到300微秒之间。当CPU和内存时钟被设置为最大值,并且禁用低功耗状态时,这种性能是可以实现的。不幸的是,在生产环境中,从功耗的角度来看,这些设置通常是不能容忍的。
在更现实的条件下,CPU和内存时钟由DCVS驱动,必要时由散热条件限制。在基于DSP的工作负载期间,CPU倾向于降低其时钟速度或进入低功耗(睡眠)状态,以节省能源,同时等待DSP对FastRPC调用的响应。在这些条件下,未减轻的FastRPC往返开销根据瞬时条件而变化,但它可能达到几毫秒。 使用www.DeepL.com/Translator翻译(免费版)
FastRPC提供API,通过在有足够的FastRPC流量时禁用某些睡眠状态,或通过投票决定底层时钟速率,帮助管理典型条件下的性能。这些API可能会大大减少FastRPC的延迟,但代价是功耗略有增加。
我们建议你尝试各种配置,以确定哪些设置最适合你的需要。欲了解更多信息,请参见 Hexagon SDK 在线文档中的 FastRPC 和 FastRPC QoS。

3.7 OverheadforlaunchingDSPthreadsfromtheDSP

如第3.3节所述,使用dspCV_worker_pool_submit可以将一个作业提交给一个池子,并在有线程可用时由一个硬件线程接走。提交一个作业的开销大约是5000个处理器周期。换句话说,父线程比它启动的其他线程完成任务的速度略快。因此,在踢掉N-1个工作线程后,让父线程执行相同的调用作业以获得最佳性能,是一个很好的做法。
具体来说,通过切换这段代码,可以提高性能:

for(i=0;i<numJobs;i++) { (void) dspCV_worker_pool_submit(job); }

对这个代码:

for (i = 0; i < numJobs-1; i++) { (void) dspCV_worker_pool_submit(job);
j}ob.fptr(job.dptr); // executed on parent thread, likely to start first
4 OptimizetasksfortheDSP

本章概述了如何在DSP上有效地移植和运行计算任务。它讨论了编程环境、DSP指令和架构细节的各个方面,这些都是编写优化DSP代码时需要考虑的关键。

4.1 Programminglanguagesandextensions 4.1.1 C/C++ support

要移植到DSP的参考代码通常是用C或C++编写的。这样的代码不需要做任何改变就可以在DSP上运行。高通公司的编译器依赖于LLVM,目前支持以下版本的C和C++标准。
1. C语言。K&R C、ANSI C89、ISO C90、ISO C94(C89+AMD1)、ISO C99(+TC1、TC2、TC3)
2. C++语言。C++98, C++11, C++14
注意 :C++11和14仅在SDM835、SDM660和较新的设备上支持。
Hexagon LLVM编译器支持目前发布的Hexagon处理器的所有版本。V4、V5、V55、V56、V60、V61、V62、V65和V66。
在本文件的其余部分,当涉及DSP标量变体时,只讨论V66。除非另有说明,关于V65的评论也适用于旧的变体。
有关 LLVM 编译器的其他信息,请参见 Hexagon LLVM C/C++ 编译器用户指南,该指南是 Hexagon 文件包的一部分。
一旦你验证了参考C/C++代码在DSP上正常运行,就可以使用其他语言和扩展来进一步优化代码,如以下各节所述。

4.1.2 Halidelanguage

Halide是一种用于视觉处理的编程语言。Halide被设计成C++的一种方言。它允许熟悉C++的程序员开始编写Halide程序。
Halide工具集可作为Hexagon SDK和Hexagon LLVM工具集的一部分。该工具集包含一个针对HVX架构的Halide编译器。Halide for HVX编译器允许你在不了解底层HVX架构的情况下利用HVX处理器的强大功能。这反过来又实现了更高层次的抽象,使你能够专注于图像算法,并从HVX获得高水平的性能。
Halide运行时也使得将内核卸载到HVX的任务变得简单。只需在Halide程序中添加一个.hexagon()指令,Halide运行时就能确保内核被透明地分配到HVX处理器中。
关于Halide编程语言的更多信息,请参见Halide for HVX用户指南(80-PD002-1),并访问http://halide-lang.org/ 上的资源。你也可以把关于Halide HVX的问题直接发到halide@quicinc.com 邮箱。

4.1.3 Compilerintrinsics

编译器本征被编译器视为机器指令。绝大多数汇编指令与编译器内含物有一对一的映射,因此允许你将一个函数表达为汇编指令的序列,让编译器来执行寄存器分配、指令分组和指令调度。
用本征编程提供了留在C/C++中的灵活性,在最需要的地方交错使用编译器本征。这种方法提供了一种环境,使代码易于调试和测试,因为你仍然可以将变量内容打印到日志或文件中,或运行用C语言编写的测试程序。
C/C++编译器不具备HVX识别能力。因此,在数据并行化提供速度改进的代码部分使用内含物。例如,V65标量指令集的许多指令和所有的HVX指令都是SIMD指令,并并行处理多个32位、16位或8位相邻元素。使用内在的SIMD指令可以保证编译器生成的汇编指令能够并行地处理这些元素。
Hexagon V66程序员参考手册(80-N2040-42)和Hexagon V66 HVX程序员参考手册(80-N2040-44)分别详细介绍了标量核心和HVX可用的所有内在汇编指令的语法和功能。
在C/C++程序中,通过包括库头文件hexagon_protos.h,可以访问所有的编译器内在指令。
例如,如果x和y被声明为64位数(声明为long long int),下面的代码将y赋值为x的四个半字中每一个的饱和绝对值:

y = Q6_P_vabsh_P_sat(x)

或者如果x,y,z被定义为128字节的数字(声明为HVX_Vector),下面的
代码将z指定为x和y的字节级相加,然后是饱和度:

z = Q6_Vh_vadd_VhVh_sat(x,y)

除了对变量进行转换外,还经常需要对变量进行访问或将其结合起来。这些 *** 作不一定映射到汇编指令中,因此在《程序员参考手册》中没有涉及。Hexagon LLVM C/C++编译器用户指南(80-VB419-89)的第11.3和11.4节中涉及到了这些内容。
例如,下面的语法创建了一个向量对vp的副本,其中下半部分被替换为向量x。下面的Q6_W_vcombine_VV指令是PRM中的一个内在的指令,可以转化为汇编指令vcombine,而Q6_V_hi_W是编译器指南中描述的一个宏。

HVX_VectorPair vp;
HVX_Vector x;
HVX_Vector v = Q6_V_hi_W(vp); // set v to the high vector of vp HVX_VectorPair new_vp = Q6_W_vcombine_VV(v, x); // create a new pair

注意 :编译器会自动优化这样的语法:如果代码的其他部分允许,new_vp和vp可以重新使用相同的寄存器来表示它们的内部,可能不需要vcombine汇编指令。

4.1.4 Assembly language

这些工具还提供了用汇编语言编写任何部分代码的能力。编写汇编为软件开发人员提供了最大的控制权,他负责选择、调度和分组指令,以及将寄存器分配给变量。
处理器的流水线是完全互锁的:如果一条指令消耗了一个寄存器,而这个寄存器的内容预计将由一个较早的指令计算,但还不能使用,那么硬件会自动停顿,并保证在寄存器被消耗时,其值是正确的。这种方法允许你在编写功能代码时不必关心指令的时间:只要指令是按照预期的执行顺序编写的,输出就会是正确的,与线程可能要停顿多少次无关。
用汇编编写的最常见和推荐的用法是用汇编编写整个函数。例如,如果一大块C语言代码中只有一个部分需要优化,那么这个部分就被表达为一个函数调用,然后用汇编编写。
如果你在写汇编代码,你必须遵守编译器的调用惯例。特别是调用保存的寄存器,标量寄存器R16到R31(R28除外),如果被改变,必须正确保存。
所有的HVX寄存器都是调用者保存的寄存器,因此都可以直接使用,而不需要在编写叶子汇编函数时将其保存在堆栈中。
更多信息请参见Hexagon应用二进制接口规范(80-N2040-23)中的跨调用寄存器使用章节。
也可以使用内联汇编来编写汇编代码。这种方法允许你直接从C/C++源文件中敲入汇编。然而,我们强烈反对这种用法,因为内联汇编的语法使用起来很麻烦,而且容易出错。
一个汇编文件可以包含一个或多个函数的实现,你只需要在C/C++源文件中声明为extern,就可以从你的C/C++代码中直接调用。
例如,如果一个汇编文件包含一个foo的实现,它接受一个32位元素数组指针作为输入,不返回任何值,并且有一个汇编实现开始如下。

.globl foo           // makes function have global scope
      .type  foo, @function
   foo:                    // begin implementation here

然后从C/C++调用这个函数,声明如下:

 extern "C" void foo(int ptr);

注意 如果函数是在C++文件中调用的,"C "应该跟在extern pragma后面,以防止函数名称被篡改。如果函数是在C语言文件中调用的,可以省略它。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/914948.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)

保存