首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在ARM Cortex-a8中使用乘法和累加内部函数?

如何在ARM Cortex-a8中使用乘法和累加内部函数?
EN

Stack Overflow用户
提问于 2010-07-14 02:57:00
回答 3查看 14.8K关注 0票数 15

如何使用GCC提供的乘法累加内联函数?

代码语言:javascript
复制
float32x4_t vmlaq_f32 (float32x4_t , float32x4_t , float32x4_t);

谁能解释一下我必须传递给这个函数的三个参数。我指的是源寄存器和目标寄存器以及函数返回的内容?

救命!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-07-14 04:11:55

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

代码语言:javascript
复制
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图形的典型4x4矩阵乘法中使用这种霓虹灯汇编器的固有特性,比如:

代码语言:javascript
复制
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指令集中也添加了它们)。

还值得一提的是:像这样的乘法-累加操作在线性代数和数字信号处理()应用程序中非常常见。ARM非常聪明,在Cortex-A8霓虹灯核心中实现了快速路径。如果VMLA指令的第一个参数(累加器)是前面的VML或VMLA指令的结果,则此快速路径开始生效。我可以详细介绍,但简而言之,这样的指令系列运行速度比VML / VADD / VML / VADD系列快四倍。

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

票数 21
EN

Stack Overflow用户

发布于 2010-07-14 03:16:09

谷歌搜索vmlaq_f32,出现了the reference for the RVCT compiler tools。它是这样写的:

代码语言:javascript
复制
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);

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

函数的返回值将是一个包含4个32位浮点数的向量,该向量的每个元素都是通过将bc的相应元素相乘,然后将a的内容相加来计算得出的。

HTH

票数 9
EN

Stack Overflow用户

发布于 2012-02-29 20:33:08

代码语言:javascript
复制
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,并且可以表示为:

代码语言:javascript
复制
result.x = vector.x * (matrix[0][0] + matrix[1][0] + matrix[2][0] + matrix[3][0]);

..。

正确的顺序应该是:

代码语言:javascript
复制
result = vml (matrix[0], vector.xxxx);
result = vmla(result, matrix[1], vector.yyyy);

..。

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

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

代码语言:javascript
复制
result.x = dp4(vector, matrix[0]);
result.y = dp4(vector, matrix[1]);

... //当然,矩阵将被转置以产生相同的结果

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

除此之外,代码看起来还不错。=)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3240440

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档