Performance ARMv7和x2B的快速正弦/余弦;霓虹灯:寻找测试员…;

Performance ARMv7和x2B的快速正弦/余弦;霓虹灯:寻找测试员…;,performance,assembly,arm,iphone-3gs,neon,Performance,Assembly,Arm,Iphone 3gs,Neon,如果有人可以使用iPhone3GS或Pandora,请测试一下我刚刚编写的以下组装例程 在NEON矢量FPU上,它应该能够非常快速地计算正弦和余弦。我知道它编译得很好,但没有足够的硬件,我无法测试它。如果你能计算一些正弦和余弦,并将结果与sinf()和cosf()的结果进行比较,那将非常有帮助 谢谢 #include <math.h> /// Computes the sine and cosine of two angles /// in: angles = Two angles

如果有人可以使用iPhone3GS或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"
    );  
}
#包括
///计算两个角度的正弦和余弦
///in:angles=两个角度,以弧度表示,在[-PI,PI]范围内。
///输出:结果=包含[sin(角度[0])、cos(角度[0])、sin(角度[1])、cos(角度[1])]的向量
静态内联void vsincos(常量浮动角度[2],浮动结果[4]){
静态常量浮点常量[]={
/*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
};  
挥发性物质(
//用[angle1,angle1,angle2,angle2]加载q0
vldmia%1,{d3}\n\t
vdup.f32 d0,d3[0]\n\t
vdup.f32 d1,d3[1]\n\t
//用常数加载q1-q6
vldmia%2,{q1-q6}\n\t
//Cos(x)=Sin(x+PI/2),所以
//q0=[angle1,angle1+PI/2,angle2,angle2+PI/2]
vadd.f32 q0、q0、q1\n\t
//如果角度1+PI/2>PI,则减去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”(结果),“r”(角度),“r”(常数)
:“内存”、“cc”、“q0”、“q1”、“q2”、“q3”、“q4”、“q5”、“q6”
);  
}

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

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

我对实现的每个调用测量了82个周期,对四个c-lib调用测量了1260个周期。请注意,我使用软浮点ABI进行编译,我的OMAP3是早期的silicon,因此每次调用c-lib版本都会有至少40个周期的NEON暂停

我已经把结果整理好了

性能计数器很可能在iphone上不起作用


希望这就是你一直在寻找的东西。

哦——在我忘记之前:也许你可以为自己争取一点工作

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


只是好奇——你用什么算法来快速计算sin,cos?如果你添加一个测试程序,我可以在我的beagleboard上运行它。。相同的CPU。@gahooa:我使用Nicolas Capens在上描述的方法,并且cos(x)=sin(x+90°)非常感谢Nils。我有点惊讶它是开箱即用的,实际上:-)为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。是的,我知道这些函数。我希望我有一台iPhone3GS来玩霓虹灯,这肯定比我的iPod的VFP11有趣得多。随着iPhone的出现,FPU热潮开始了,但在此之前的规则是:不做浮动,做定点。我开始认为那些为iPhone编写浮动代码的人是错误的。ARM非常擅长处理整数,设置浮点寄存器的开销很大。事实上,我知道另一个相关的项目,而不是这个项目。我想到的那个只有矩阵/向量函数。刚刚检查了你的链接。看起来它有所有的math.h函数!我正在主演,谢谢!:-)