Schnellerer ACos() mit Array und Makros

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Schnellerer ACos() mit Array und Makros

Beitrag von NicTheQuick »

Wieder ein Stück aus meiner RayTracing-Engine, die vielleicht jemand
gebrauchen kann, obwohl es jeder wohl auch selbst hinbekommen würde. :wink:
Das Makro ersetzt die rechenintensive Funktion ACos() durch ein Array mit
vorberechneten Werten mit wählbarer Genauigkeit per Konstante.

Laut meinem Speedtest benötigt die Variante bei 20.000.000 Durchläufen
nur runder 38% der Zeit, die die Original-Funktion benötigt. Sicherlich ist
das von Rechner zu Rechner auch wieder unterschiedlich.

Der Speicherverbrauch des Arrays ist auch enorm, solange man Doubles
einsetzt, aber wird bei grafischen Sachen wohl kaum eine Rolle spielen.

Code: Alles auswählen

;Schnellerer ACos() über Array und Macros gelöst
#RT_Cos2ACos = 20000 ;Genauigkeit (Speicherverbrauch: 20001 * SizeOf(Double) = 160.008 Bytes)
#RT_Cos2ACos2 = #RT_Cos2ACos / 2
Global Dim Cos2ACos.d(#RT_Cos2ACos)
For _ = 0 To #RT_Cos2ACos : Cos2ACos(_) = ACos((_ - #RT_Cos2ACos2) * 1.0 / #RT_Cos2ACos2) :Next
Macro RT_ACos(v)
  Cos2ACos(Int(v * #RT_Cos2ACos2) + #RT_Cos2ACos2)
EndMacro
///Edit:
Hier noch die Version für alle, die die Winkel lieber in DEG haben:

Code: Alles auswählen

;Schnellerer ACos() über Array und Macros gelöst
#RT_Cos2ACos = 20000 ;Genauigkeit (Speicherverbrauch: 20001 * SizeOf(Double) = 160.008 Bytes)
#RT_Cos2ACos2 = #RT_Cos2ACos / 2
Global Dim Cos2ACos.d(#RT_Cos2ACos)
For _ = 0 To #RT_Cos2ACos : Cos2ACos(_) = ACos((_ - #RT_Cos2ACos2) * 1.0 / #RT_Cos2ACos2) * 57.295779513082323 : Next
Macro RT_ACos(v)
  Cos2ACos(Int(v * #RT_Cos2ACos2) + #RT_Cos2ACos2)
EndMacro


Debug ACos(0.123456678) * 57.295779513082323
Debug RT_ACos(0.123456678)
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Code: Alles auswählen

For _
:mrgreen:
Tschuldige, dabei kann ich mir ein Grinsen nicht verkneifen
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Ist doch 'ne tolle temporäre Variable, meinst du nicht? :mrgreen:
Benutzeravatar
DrShrek
Beiträge: 1970
Registriert: 08.09.2004 00:59

Beitrag von DrShrek »

NicTheQuick hat geschrieben:Ist doch 'ne tolle temporäre Variable, meinst du nicht? :mrgreen:
Eher makaber ;-)
Siehste! Geht doch....?!
PB*, *4PB, PetriDish, Movie2Image, PictureManager, TrainYourBrain, ...
Benutzeravatar
#NULL
Beiträge: 2238
Registriert: 20.04.2006 09:50

Beitrag von #NULL »

Code: Alles auswählen

_=3:_+_*_-_/2+_-_<<_&$c:Debug _
:o :lol: ["..singatur zu verschenken, greifen sie zu!" :wink: ]
Zuletzt geändert von #NULL am 15.12.2006 14:13, insgesamt 2-mal geändert.
my pb stuff..
Bild..jedenfalls war das mal so.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Hab aus #NULL seinem Code mal eine wiederverwendbar Procedure
gemacht, kann ins CodeArchiv :mrgreen:

Code: Alles auswählen

Procedure _(_)
  ProcedureReturn _+_*_-_/_+_-_<<_&$c
EndProcedure

; example
Debug _(3)
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
#NULL
Beiträge: 2238
Registriert: 20.04.2006 09:50

Beitrag von #NULL »

; description:
; converts unfug into mist
my pb stuff..
Bild..jedenfalls war das mal so.
Friedhelm
Beiträge: 43
Registriert: 29.08.2004 08:50

Beitrag von Friedhelm »

Mein spiiiiiiiiiiit forschlag

Code: Alles auswählen

;Schnellerer ACos() über Array und Macros gelöst
#RT_Cos2ACos = 20000 ;Genauigkeit (Speicherverbrauch: 20001 * SizeOf(Double) = 160.008 Bytes)
#RT_Cos2ACos2 = #RT_Cos2ACos / 2
Global Dim Cos2ACos.d(#RT_Cos2ACos)
For _ = 0 To #RT_Cos2ACos : Cos2ACos(_) = ACos((_ - #RT_Cos2ACos2) * 1.0 / #RT_Cos2ACos2) :Next
Macro RT_ACos(v)
  Cos2ACos(Int(v * #RT_Cos2ACos2) + #RT_Cos2ACos2)
EndMacro



; float fast_acos(float val)
; 00254 {
; 00255     float fRoot = sqrt(1.0f-val);
; 00256     float fResult = -0.0187293f;
; 00257     fResult *= val;
; 00258     fResult += 0.0742610f;
; 00259     fResult *= val;
; 00260     fResult -= 0.2121144f;
; 00261     fResult *= val;
; 00262     fResult += 1.5707288f;
; 00263     fResult *= fRoot;
; 00264 
; 00265     Return fResult;
; 00266 }

Macro RT_Fast_ACos(v)
   ((((((-0.0187293  *  v)  +  0.0742610)  *  v) -  0.2121144) *  v) +  1.5707288) * Sqr(1.0-v) 
EndMacro



XX=1000000000
string.s = "Ich bin ein fieser Teststring"

Delay(10)
TestZeit.l  = ElapsedMilliseconds()
For i=1 To XX
  Debug  ACos(0.1) 
Next
Zeit1 = ElapsedMilliseconds()-TestZeit

Delay(10)
TestZeit.l  = ElapsedMilliseconds()
For i=1 To XX
  Debug RT_ACos(0.1)
Next
Zeit2 = ElapsedMilliseconds()-TestZeit

Delay(10)
TestZeit.l  = ElapsedMilliseconds()
For i=1 To XX
 Debug RT_Fast_ACos(0.1)
Next
Zeit3 = ElapsedMilliseconds()-TestZeit

Out.s  = "Es wurden je "+Str( XX)+" Aufrufe gestartet"+#crlf$
Out.s  + "ACos()        : "+Str(Zeit1)+" ms."+#crlf$
Out.s  + "RT_ACos()     : "+Str(Zeit2)+" ms."+#crlf$
Out.s  + "RT_Fast_ACos(): "+Str(Zeit3)+" ms."+#crlf$
SetClipboardText(Out)
MessageRequester("Ergebnis",Out,#PB_MessageRequester_Ok)
 
Mein Ergebnise
Es wurden je 1000000000 Aufrufe gestartet
ACos() : 2860 ms.
RT_ACos() : 3422 ms.
RT_Fast_ACos(): 1828 ms.
mfg
Friedhelm
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Beitrag von remi_meier »

Ich verwende hier zur Zeit diesen Code:

Code: Alles auswählen

; Sinus & Cosinus Tabelle
#SINCOS = 1 << 12
Dim tSin.f(#SINCOS)
Dim tCos.f(#SINCOS)
Define.l z
For z = 0 To #SINCOS
  tSin(z) = Sin(z * 2 * #PI / #SINCOS)
  tCos(z) = Cos(z * 2 * #PI / #SINCOS)
Next
#SINCOS ist der Winkel, bei dem man wieder am Anfang steht, also bei
Grad-Angaben 360°. Er sollte im 2^x Format vorliegen, denn dann kann
man ganz einfach mit
angle & (#SINCOS - 1)
den Winkel "angle" auf den Bereich von 0 - #SINCOS-1 beschränken.

Läuft ganz ordentlich hier :D
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Antworten