c/c++语言开发共享如何在ARM Cortex-a8中使用乘法和累加内在函数?

如何使用GCC提供的Multiply-Accumulate内在函数?

float32x4_t vmlaq_f32 (float32x4_t , float32x4_t , float32x4_t); 

任何人都可以解释我必须传递给这个函数的三个参数。 我的意思是源和目标寄存器以及函数返回的内容?

救命!!!

    简单地说vmla指令执行以下操作:

     struct { float val[4]; } float32x4_t float32x4_t vmla (float32x4_t a, float32x4_t b, float32x4_t c) { float32x4 result; for (int i=0; i<4; i++) { result.val[i] = b.val[i]*c.val[i]+a.val[i]; } return result; } 

    所有这些编译成一个单独的汇编指令:-)

    您可以在3D图形的典型4×4矩阵乘法中使用此NEON-assembler内在函数,如下所示:

     float32x4_t transform (float32x4_t * matrix, float32x4_t vector) { /* in a perfect world this code would compile into just four instructions */ float32x4_t result; result = vml (matrix[0], vector); result = vmla (result, matrix[1], vector); result = vmla (result, matrix[2], vector); result = vmla (result, matrix[3], vector); return result; } 

    这样可以节省几个周期,因为您不必在乘法后添加结果。 经常使用加法,这些天乘法积累hsa成为主流(甚至x86在最近的一些SSE指令集中添加了它们)。

    另外值得一提的是:像这样的乘法累加运算在线性代数和DSP(数字信号处理)应用中非常常见。 ARM非常智能,并在Cortex-A8 NEON-Core内部实现了快速路径 。 如果VMLA指令的第一个参数(累加器)是前面的VML或VMLA指令的结果,则该快速路径启动。 我可以详细介绍,但简而言之,这样的指令系列运行速度比VML / VADD / VML / VADD系列快四倍。

    看看我的简单矩阵乘法:我就是这么做的。 由于这种快速路径,它的运行速度比使用VML和ADD而不是VMLA编写的实现快大约四倍。

    谷歌为vmlaq_f32 , 提出了RVCT编译器工具的参考 。 这是它说的:

     Vector multiply accumulate: vmla -> Vr[i] := Va[i] + Vb[i] * Vc[i] ... float32x4_t vmlaq_f32 (float32x4_t a, float32x4_t b, float32x4_t c); 

    定义以下类型以表示向量。 NEON向量数据类型根据以下模式命名: x <通道数> _t例如,int16x4_t是包含四个通道的向量,每个通道包含一个带符号的16位整数。 表E.1列出了矢量数据类型。

    IOW,函数的返回值将是一个包含4个32位浮点数的向量,并且通过将bc的相应元素相乘,并添加a的内容来计算向量的每个元素。

    HTH

     result = vml (matrix[0], vector); result = vmla (result, matrix[1], vector); result = vmla (result, matrix[2], vector); result = vmla (result, matrix[3], vector); 

    但是,这个序列不起作用。 问题是x分量只累积由矩阵行调制的x,可以表示为:

     result.x = vector.x * (matrix[0][0] + matrix[1][0] + matrix[2][0] + matrix[3][0]); 

    正确的顺序是:

     result = vml (matrix[0], vector.xxxx); result = vmla(result, matrix[1], vector.yyyy); 

    NEON和SSE没有字段的内置选择(每个向量寄存器需要8位指令编码)。 例如,GLSL / HLSL确实有这种设施,所以大多数GPU也有。

    实现这一目标的另一种方法是:

     result.x = dp4(vector, matrix[0]); result.y = dp4(vector, matrix[1]); 

    … //当然,矩阵将为此转置以产生相同的结果

    mul,madd,madd,madd序列通常是首选,因为它不需要目标寄存器字段的写掩码。

    否则代码看起来不错。 =)

    需要了解更多c/c++开发分享如何在ARM Cortex-a8中使用乘法和累加内在函数?,也可以关注C/ C++技术分享栏目—计算机技术网(www.ctvol.com)!

      以上就是c/c++开发分享如何在ARM Cortex-a8中使用乘法和累加内在函数?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/980464.html

      (0)
      上一篇 2021年12月13日
      下一篇 2021年12月13日

      精彩推荐