000
02.06.2002, 20:33
Diablo_bth
|
eigentlich is dass ja eine Frechheit wenn man z.B. so etwas is der math.h zu lesen bekommt:
inline float sinf(float _X) {return ((float)sin((double)_X)); }
da benutzt man extra 32-bit-float anstatt double und dann sowas! Ok in einem Source habe ich dann sowas entdekt:
__forceinline static __declspec(naked) float __fastcall fsin(float a) { __asm { fld DWORD PTR [esp+4] fsin ret 4 } }
__forceinline static __declspec(naked) float __fastcall fcos(float a) { __asm { fld DWORD PTR [esp+4] fcos ret 4 } }
Das ist fast genau doppelt so schnell wie das normale sin/cos. Mein Problem ist jetzt dass ich von Assmbler nicht wirklich was verstehe, aber das ganze gerne auch für tan, asin, acos, atan und sqrt ( sqrtf() is auch so eine verarsche! ) hätte. Nicht dass ich das nicht versucht hätte, doch wenn ich nun anstatt fcos z.B. ftan hinschreibe gibts einen Fehler. Kann mir da jemand weiterhelfen?
--
Dieser Beitrag wurde am 02.06.2002 um 20:34 von Diablo_bth bearbeitet.
|
|
Profil || Suche
|
001
02.06.2002, 20:47
Ferdi
|
du hast sin und cos... wie wärs mit tan(x) = sin(x) / cos(x) ?
nur ein vorschlag um dass Problem zu umgehen aber es gibt sicher auch ne bessere Variante
--
|
|
Profil || Suche
|
002
02.06.2002, 20:52
Diablo_bth
|
ähh ich glaube Du hast mich nicht ganz verstanden?! es gibt natürlich auch ein tan( double ), ich will das aber für float optimiert haben! So wie ich das in den beiden Beispielfunktionen gezeigt habe!
--
|
|
Profil || Suche
|
003
02.06.2002, 22:25
Ferdi
|
ich glaube du verstehst mich eher falsch...aber egal...
--
|
|
Profil || Suche
|
004
02.06.2002, 23:55
Kriz
|
Nicht meckern, selber programmieren =)
--
K:R-I)Z++ "CSS ist cascading style sheets. Und nicht so'n Ranzspiel." - dp In memory of Voice ( 2005/03/30)
|
|
Profil || Suche
|
005
03.06.2002, 01:36
Tron
|
es ist nur halbe verarsche der rueckgabewert in form von fliesskommazahlen wird ueber st0 (das erste fpu register) gehandhabt, da ist es voellig egal ob das nun float, double oder gar long double ist. wie es mit der parameteruebergabe aussieht haengt vermutlich von der schlaeue des optimierers ab. ich empfehle: einfach mal profilen, ob es langsamer langsamer ist. das normale sin/cos ist vermutlich deshalb langsamer, da ANSI-C(++) sehr genaue vorgaben bzgl. rundung macht und das vor jedem groesere flieskommabtrechnung eingestellt wird, was die ganze sache natuerlich enorm verlangsamt ich werd nacher mal bissl wuehlen und schauen wie die assemblerbefehle fuer die uebrigen operationen lauten.
btw: im quake sourcecode ist eine sehr gute 1/sqrt(x) funktion drin, das is zwar der uebelst gehackteste kleine bastard, den ich je gesehen habe, aber dafuer sauschnell. such mal im forum von www.flipcode.com , da gab es mal einen thread ueber sowas
--
'KEINE PANIK' - aus der Triologie in fuenf Baenden von Douglas Adams
'FÜR DEINN FERD' - aus 'Gevatter Tod' von Terry Pratchett
|
|
Profil || Suche
|
006
03.06.2002, 22:43
[PE]Spinator
|
@Diablo_bth: Ferdi hat schon recht, wenn du optimierte funktionen für cos und sin hast, dann kannst du dir ne tan aus diesen beiden basteln... allzugross ist der speed verlust sicher nit...
--
This post was written using Opera 7.0 (http://www.opera.com)
|
|
Profil || Suche
|
007
03.06.2002, 23:03
Diablo_bth
|
wow krass geil ich hab voll den Exzess darüber gefunden: http://www.flipcode.com/cgi-bin/msg.cgi?showThread=00002548&forum=3dtheory&id=-1
@Spinator, Ferdi: ihr habt nicht wirklich recht, da ich ein wenig recherchiert habe. Ihr könnt ja mal so eine Funktion basteln und die mit der hier vergleichen: ( ich bin sicher dass ist schneller als alles was ihr je gesehen habt!! )
__forceinline /* inline */ static __declspec( naked ) float __fastcall ftan( float ) { __asm { fld dword ptr [esp+4] fptan fstp dword ptr [esp+4] ret 4 } }
@Tron: da waren nun schon ein paar ganz gute Ansätze für sqrtf, tanf, arcsin/cos. Die haben aber z.B. sowas hier gemacht:
float asm_arccos( float r ) { // return half_pi + arctan( -r / sqr( 1.f - r * r ) ); const float asm_one = 1.f; const float asm_half_pi = half_pi; __asm { fld r fld r fmul r fsubr asm_one fsqrt fstp r fchs fdiv r fld1 fpatan fadd asm_half_pi } }
Wenn man dann den asm-code anschaut ist da noch viel unnötiges Zeug drin wie zB. das pushes un popen von ebx, den Aufruf von __checkesp und anderes Zeug was ich nicht verstanden habe. Da habe mich nun mal selbst mit der Materie beschäftigt und die Performance dieser Funktionen etwas gesteigert. Der code funktioniert, ich bin mir aber seiner Fehlerfreiheit nicht 100%ig sicher. Zumindest wird das esp ( was immer das auch ist ) durch den Funktionaufruf nicht verändert. [ damit hatte ich anfags probleme ] ( ich poste einfach mal alle in meiner fmath.h, vielleicht interessiert das noch jemand )
__forceinline /* inline */ static __declspec( naked ) float __fastcall fsin( float ) { __asm { fld dword ptr [esp+4] fsin ret 4 } }
__forceinline /* inline */ static __declspec( naked ) float __fastcall fcos( float ) { __asm { fld dword ptr [esp+4] fcos ret 4 } }
__forceinline /* inline */ static __declspec( naked ) float __fastcall ftan( float ) { __asm { fld dword ptr [esp+4] fptan fstp dword ptr [esp+4] ret 4 } }
__forceinline /* inline */ static __declspec( naked ) float __fastcall fasin( float ) { // return arctan( r / sqr( 1.0f - r * r ) ); __asm { push ebp mov ebp,esp sub esp,44h
mov dword ptr [ebp-4],3F800000h // 1.0f;
fld dword ptr [ebp+8] // r0 = r fld dword ptr [ebp+8] // r1 = r0, r0 = r fmul dword ptr [ebp+8] // r0 = r0 * r fsubr dword ptr [ebp-4] // r0 = r0 - 1.0f fsqrt // r0 = sqrtf( r0 ) fdiv // r0 = r1 / r0 fld1 // r0 = fpatan // atan( r0 )
mov esp,ebp pop ebp ret 4 } }
__forceinline /* inline */ static __declspec( naked ) float __fastcall facos( float ) { // return half_pi + arctan( r / -sqr( 1.0f - r * r ) ); __asm { push ebp mov ebp,esp sub esp,48h
mov dword ptr [ebp-4],3F800000h // 1.0f; mov dword ptr [ebp-8],3FC90FDBh // M_HALFPI;
fld dword ptr [ebp+8] // r0 = r fld dword ptr [ebp+8] // r1 = r0, r0 = r fmul dword ptr [ebp+8] // r0 = r0 * r fsubr dword ptr [ebp-4] // r0 = r0 - 1.0f fsqrt // r0 = sqrtf( r0 ) fchs // r0 = - r0 fdiv // r0 = r1 / r0 fld1 // r0 = fpatan // atan( r0 ) fadd dword ptr [ebp-8] // r0 = r0 + pi / 2
mov esp,ebp pop ebp ret 4 } }
__forceinline /* inline */ static __declspec( naked ) float __fastcall fatan( float ) { __asm { fld dword ptr [esp+4] fld1 fpatan fstp dword ptr [esp+4] fld dword ptr [esp+4] ret 4 } }
__forceinline /* inline */ static __declspec( naked ) float __fastcall fsqrt( float ) { __asm { fld dword ptr [esp+4] fsqrt ret 4 } }
__forceinline /*inline*/ static __declspec( naked ) float __fastcall fabsf( float ) { __asm { push ebp mov ebp,esp sub esp,44h
mov dword ptr [ebp-4],00000000h // 0.0f;
fld dword ptr [ebp+8] fcomp dword ptr [ebp-4]
fnstsw ax test ah,1 je groesser // größer als 0.0f ?
fld dword ptr [ebp+8] fchs // *= -1.0f
mov esp,ebp pop ebp
ret 4
groesser: fld dword ptr [ebp+8]
mov esp,ebp pop ebp
ret 4 } }
#define M_HALFPI 1.5707963267948966192313216916397f #define M_PI 3.1415926535897932384626433832795f #define M_2PI 6.2831853071795864769252867665590f #define M_PIOVER180 0.0174532925199432957692369076848f // M_PI / 180.0 #define M_NPIOVER180 57.295779513082320876798154817014f // M_PIOVER180 ^ (-1.0)
#define SIN( x ) ( fsin((x) * M_PIOVER180) ) #define COS( x ) ( fcos((x) * M_PIOVER180) ) #define TAN( x ) ( ftan((x) * M_PIOVER180) )
#define ASIN( x ) ( fasin(x) * M_NPIOVER180 ) #define ACOS( x ) ( facos(x) * M_NPIOVER180 ) #define ATAN( x ) ( fatan(x) * M_NPIOVER180 )
P.S.: was ist das esp eigentlich genau? Es fühlt sich zumindest so an die die direkte Speicher-Hauptschlagader
*edit* wenn jemand noch einen Vorschlag für atan2() hätte soll er das doch bitte posten
--
Dieser Beitrag wurde am 03.06.2002 um 23:10 von Diablo_bth bearbeitet.
|
|
Profil || Suche
|
008
04.06.2002, 00:49
Tron
|
esp ist der stackpointer (Extended Stack Pointer, extended, da 32bit breit) ueber den stack werden die parameter uebergeben
--
'KEINE PANIK' - aus der Triologie in fuenf Baenden von Douglas Adams
'FÜR DEINN FERD' - aus 'Gevatter Tod' von Terry Pratchett
|
|
Profil || Suche
|