Schnelle Sinus / Cosinus für ARMv7 + NEON: Suche nach Testern ...
-
13-09-2019 - |
Frage
Könnte jemand mit Zugriff auf ein iPhone 3GS oder ein Pandora Bitte testen Sie die folgende Assembly-Routine ich gerade geschrieben?
Es wird angenommen, Sinus und Kosinus wirklich sehr schnell auf dem NEON Vektor FPU zu berechnen. Ich weiß, dass es kompiliert gut, aber ohne ausreichende Hardware ich es nicht testen kann. Wenn Sie nur ein paar Sinus und Cosinus berechnen können und die Ergebnisse mit denen von sinf vergleichen () und cosf () würde es wirklich helfen.
Danke!
#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"
);
}
Lösung
getestet es einfach auf meine Beagle .. Wie gesagt in den Kommentaren. Gleiche CPU
Der Code ist etwa 15-mal schneller als die clib .. Gut gemacht!
Ich habe 82 Zyklen gemessen für jeden Aufruf der Implementierung und 1260 für die vier c-lib Anrufe. Beachten Sie, dass ich zusammengestellt habe mit Soft-Float-ABI und mein OMAP3 ist früh Silizium, so dass jeder Aufruf an die c-lib-Version hat eine NEON Stall von mindestens 40 Zyklen.
Ich habe zusammen die Ergebnisse Reißverschluss ..
http://torus.untergrund.net/code/sincos.zip
Die Performance-Counter Sachen werden höchstwahrscheinlich nicht auf dem iPhone funktionieren.
Ich hoffe, das ist, was Sie gesucht haben.
Andere Tipps
Oh - bevor ich es vergesse: Vielleicht können Sie sicher selbst ein bisschen Arbeit ..
Werfen Sie einen Blick auf diese NEON mathematischen Funktionen optimiert: