ARMv7+NEON 的快速正弦/余弦:寻找测试人员…
可以使用 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"
);
}
Could somebody with access to an iPhone 3GS or a Pandora please test the following assembly routine I just wrote?
It is supposed to compute sines and cosines really really fast on the NEON vector FPU. I know it compiles fine, but without adequate hardware I can't test it. If you could just compute a few sines and cosines and compare the results with those of sinf() and cosf() it would really help.
Thanks!
#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"
);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
刚刚在我的 beagleboard 上测试了它。正如评论中所说:相同的 CPU。
你的代码大约比 clib 快 15 倍..干得好!
我测量了您的实现的每个调用的 82 个周期,以及四个 c-lib 调用的 1260 个周期。请注意,我已经使用软浮点 ABI 进行了编译,并且我的 OMAP3 是早期芯片,因此对 c-lib 版本的每次调用都会有至少 40 个周期的 NEON 停顿。
我已将结果压缩在一起。
http://torus.untergrund.net/code/sincos。 zip
性能计数器的东西很可能在 iPhone 上不起作用。
希望这就是您一直在寻找的东西。
Just tested it on my beagleboard.. As said in the comments: Same CPU.
Your code is roughly 15 times faster than the clib.. Well done!
I've measured 82 cycles for each call of your implementation and 1260 for the four c-lib calls. Note that I've compiled with soft-float ABI and my OMAP3 is early silicon, so each call to the the c-lib version has a NEON stall of at least 40 cycles.
I've zipped together the results..
http://torus.untergrund.net/code/sincos.zip
The performance-counter stuff will most likely not work on the iphone.
Hope that's what you've been looking for.
哦 - 在我忘记之前:也许你可以安全地做一些工作..
看看这些 NEON 优化的数学函数:
http://code.google.com/p/math-neon/
Oh - before I forget it: Maybe you can safe yourself a bit of work..
Take a look at these NEON optimized math functions:
http://code.google.com/p/math-neon/