3

我可以使用哪些函数来Accelerate.framework按标量缩放向量,并对向量进行归一化?我发现一个我认为可能适用于文档中的缩放,但我对它的操作感到困惑。

vDSP_vsma
Vector scalar multiply and vector add; single precision.

void vDSP_vsma (
   const float *__vDSP_A,
   vDSP_Stride __vDSP_I,
   const float *__vDSP_B,
   const float *__vDSP_C,
   vDSP_Stride __vDSP_K,
   float *__vDSP_D,
   vDSP_Stride __vDSP_L,
   vDSP_Length __vDSP_N
);
4

1 回答 1

9

就地标准化向量的最简单方法是

int n = 3;
float v[3] = {1, 2, 3};
cblas_sscal(n, 1.0 / cblas_snrm2(n, v, 1), v, 1);

你需要

#include <cblas.h>

或者

#include <vblas.h>

(或两者)。请注意,当它们对向量进行操作时,其中一些函数位于“矩阵”部分。

如果您想使用 vDSP 函数,请参阅矢量标量除法部分。您可以做几件事:

  • vDSP_dotpr(), sqrt(), 和vDSP_vsdiv()
  • vDSP_dotpr(), vrsqrte_f32(), and vDSP_vsmul()(vrsqrte_f32()是内置的 NEON GCC,所以你需要检查你正在为 armv7 编译)。
  • vDSP_rmsqv(), 乘以sqrt(n), 和vDSP_vsdiv()

没有向量归一化函数的原因是因为 vDSP 中的“向量”意味着“一次有很多东西”(最多大约4096/ 8192),并且必然是线性代数中的“向量”。标准化一个元素向量是毫无意义的1024,一个快速标准化一个3元素向量的函数不会让你的应用程序明显更快,这就是为什么没有。

vDSP 的预期用途更像是规范化1024 2- 或 -3元素向量。我可以找到几种方法来做到这一点:

  • 用于vDSP_vdist()获取长度向量,后跟vDSP_vdiv(). vDSP_vdist()但是,对于长度大于 2 的向量,您必须多次使用。
  • 用于vDSP_vsq()对所有输入求平方,vDSP_vadd()多次将所有输入相加,相当于vDSP_vsqrt()or vDSP_vrsqrt(), and vDSP_vmul()orvDSP_vdiv()视情况而定。vDSP_vsqrt()写出or的等价物应该不会太难vDSP_vrsqrt()
  • 假装您的输入是复杂向量的各种方法。不可能更快。

当然,如果你没有要归一化的 1024 个向量,请不要使事情过于复杂。

笔记:

  1. 我不使用“2-vector”和“3-vector”来避免与相对论中的“4-vector”混淆。
  2. n的一个不错的选择是几乎填满您的 L1 数据缓存。这并不难;它们已经相对固定在32K大约十年或更长时间(它们可能在超线程 CPU 中的虚拟内核之间共享,而一些较旧/更便宜的处理器可能有 16K),所以你应该做的最多的是8192在原地操作浮动。您可能希望减少一些堆栈空间,如果您正在执行多个顺序操作,您可能希望将其全部保存在缓存中;1024或者2048看起来很明智,再多一点可能会导致收益递减。如果您关心,请测量性能...
于 2010-11-23T02:35:26.027 回答