【问题标题】:Fast sine/cosine for ARMv7+NEON: looking for testers…ARMv7+NEON 的快速正弦/余弦:寻找测试人员……
【发布时间】:2010-12-23 16:18:23
【问题描述】:

可以使用 iPhone 3GS 或 Pandora 的人测试一下我刚刚编写的以下汇编程序吗?

它应该在 NEON 矢量 FPU 上非常快速地计算正弦和余弦。我知道它编译得很好,但是没有足够的硬件我无法测试它。如果您可以只计算一些正弦和余弦并将结果与​​ sinf() 和 cosf() 的结果进行比较,那将非常有帮助。

谢谢!

#include <math.h>

/// Computes the sine and cosine of two angles
/// in: angles = Two angles, expressed in radians, in the [-PI,PI] range.
/// out: results = vector containing [sin(angles[0]),cos(angles[0]),sin(angles[1]),cos(angles[1])]
static inline void vsincos(const float angles[2], float results[4]) {
    static const float constants[]  = { 
    /* q1 */  0,                M_PI_2,           0,                M_PI_2,
    /* q2 */  M_PI,             M_PI,             M_PI,             M_PI,
    /* q3 */  4.f/M_PI,         4.f/M_PI,         4.f/M_PI,         4.f/M_PI,
    /* q4 */ -4.f/(M_PI*M_PI), -4.f/(M_PI*M_PI), -4.f/(M_PI*M_PI), -4.f/(M_PI*M_PI),
    /* q5 */  2.f,              2.f,              2.f,              2.f,
    /* q6 */  .225f,            .225f,            .225f,            .225f
    };  
    asm volatile(
        // Load q0 with [angle1,angle1,angle2,angle2]
        "vldmia %1, { d3 }\n\t"
        "vdup.f32 d0, d3[0]\n\t"
        "vdup.f32 d1, d3[1]\n\t"
        // Load q1-q6 with constants
        "vldmia %2, { q1-q6 }\n\t"
        // Cos(x) = Sin(x+PI/2), so
        // q0 = [angle1, angle1+PI/2, angle2, angle2+PI/2]
        "vadd.f32 q0,q0,q1\n\t"
        // if angle1+PI/2>PI, substract 2*PI
        // q0-=(q0>PI)?2*PI:0
        "vcge.f32 q1,q0,q2\n\t"
        "vand.f32 q1,q1,q2\n\t"
        "vmls.f32 q0,q1,q5\n\t"
        // q0=(4/PI)*q0 - q0*abs(q0)*4/(PI*PI)
        "vabs.f32 q1,q0\n\t"
        "vmul.f32 q1,q0,q1\n\t"
        "vmul.f32 q0,q0,q3\n\t"
        "vmul.f32 q1,q1,q4\n\t"
        "vadd.f32 q0,q0,q1\n\t"
        // q0+=.225*(q0*abs(q0) - q0)
        "vabs.f32 q1,q0\n\t"
        "vmul.f32 q1,q0,q1\n\t"
        "vsub.f32 q1,q0\n\t"
        "vmla.f32 q0,q1,q6\n\t"
        "vstmia %0, { q0 }\n\t"
        :: "r"(results), "r"(angles), "r"(constants)
        : "memory","cc","q0","q1","q2","q3","q4","q5","q6"
    );  
}

【问题讨论】:

  • 只是好奇——你用什么算法来快速计算 sin,cos?
  • 如果你添加一个测试程序,我可以在我的 beagleboard 上运行它。相同的 CPU。
  • @gahooa:我使用 Nicolas Capens 在devmaster.net/forums/showthread.php?t=5784 上描述的方法以及 cos(x)=sin(x+90°)

标签: performance assembly arm iphone-3gs neon


【解决方案1】:

刚刚在我的 beagleboard 上测试过。正如 cmets 中所说:相同的 CPU。

您的代码比 clib 快大约 15 倍。做得好!

我为您的实现的每次调用测量了 82 个周期,为四个 c-lib 调用测量了 1260 个周期。请注意,我使用 soft-float ABI 进行编译,并且我的 OMAP3 是早期芯片,因此对 c-lib 版本的每次调用都有至少 40 个周期的 NEON 停顿。

我已经把结果压缩在一起了..

http://torus.untergrund.net/code/sincos.zip

性能计数器很可能无法在 iphone 上运行。

希望这就是您一直在寻找的。​​p>

【讨论】:

  • 非常感谢尼尔斯。我有点惊讶它开箱即用,实际上 :-) 为 VFP11 实现的相同方法只比在我的 iPod Touch 上调用 sinf()+cosf() 快两倍,所以我使用了一个查找表而是。
  • 啊,我从您的测试程序中看到您使用了 libc 函数的双精度变体(sin()/cos(),而不是 sinf()/cosf())。这解释了为什么我认为 libc 函数的表现如此糟糕:-)
  • 刚刚用sinf/cosf编译运行,并没有太大区别。
  • 你的意思是,与使用 sin()/cos() 测试时相比,与 sinf()/cosf() 测试相比,结果几乎没有差异,或者两者之间的速度几乎没有差异我的函数和 libc 的?
  • sin和sinf没有太大区别(cos也是一样)。我测量了双版本的 1260 个周期/迭代和浮动版本的 1245 个周期/迭代。我敢打赌这是相同的代码,我们只是将演员表从 double 保存到 float。
【解决方案2】:

哦 - 在我忘记之前:也许你可以保护自己一些工作..

看看这些 NEON 优化的数学函数:

http://code.google.com/p/math-neon/

【讨论】:

  • 是的,我知道这些功能。我希望我有一部 iPhone 3GS 来玩 NEON,这肯定比在我的 iPod 的 VFP11 上工作有趣得多。 iPhone 开始出现 FPU 热潮,但在此之前,规则是:不要做浮点数,要做定点数。我开始认为那些为 iPhone 编写浮点数的人是错误的。 ARM 非常擅长处理整数,而设置浮点寄存器的开销很大。
  • 其实我知道另一个相关的项目,不是这个。我想到的只有矩阵/向量函数。刚刚检查了您放置链接的那个。看起来它具有所有 math.h 函数!我是主演,谢谢! :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-16
  • 1970-01-01
  • 2017-10-06
相关资源
最近更新 更多