Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

11

30.05.2011, 19:10

Mh ich dachte einige Fragen die hier gerade aufkamen hätte ich bereits oben beantwortet o.O.

1) Meine CPU auf der Arbeit ist ne Gurke. P4 3GHZ, Hyperthreading Modus, so komme ich mit 1 Thread gerade mal an ca 1.5GHz davon ran
2) Somit wäre auch die Frage Float vs Int geklärt: Die "neue" Methode ist 4 mal schneller als die alte. Ausgeteste mit alt vs neue methode jeweils 100Millionenmal hintereinander ausführen. Alte methode ca 4sec, "neu" ca 1sec. Floatingpoint war auf der CPU halt lahm ;)
3)Multithreading war auch eine Idee, beim Synchronisieren geht mir aber ziemlich viel verloren. Bei der alten methode wars ne 0 runde.

@Dot:

Zitat

nrm := 1 div Wert;
Ergebnis := (A*x + B*Y + C*Z) * nrm;
Ergebnis2 := (A*x2 + B*Y2 + C*Z2) * nrm;
Ergebnis3 := (A*x3 + B*Y3 + C*Z3) * nrm;


VORSICHT:
DIV ist eine reine Integer division( / für floatingpoint). Das bedeutet es kommt immer 0 raus(0,xx, da wert immer größer 1 ist). Multiplizierst du dan einen Integer mit einer float, darf Ergebnis kein integer sein(in meinem fall ist es aber so), sondern muss eine float sein, oder du musst per round/trunc ran womit man performance mässig gegen eine wand fährt.
Deswegen ist obiger code in delphi garnicht umsetzbar. :(
Meine Website mit Updates/News zu Aktuellen Projekten:SpareTime-Development

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

12

30.05.2011, 19:27

Niemand hat angezweifelt, dass die neue Methode schneller ist als die alte. Aber wir haben angezweifelt, dass es dafür unbedingt Ganzzahlarithmetik und Assembler notwendig ist.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

13

30.05.2011, 19:38

Nun, wenn er so nur pro Vertex und nichtmehr pro Pixel nach int runden muss dann ist es natürlich schneller, das stimmt schon. Der Performancegewinn kommt aber wohl nicht wirklich daher dass an den Divisionen gespart wird sondern nur durch den gesparten Cast. Sry, ich hab wohl nicht ganz verstanden was du uns mit deinem Posting hier genau sagen wolltest ;)

14

30.05.2011, 19:55

@Dot: ja...ich rede manchmal unsortiert:D.
Nun aufjedenfall war das ganze bei mir die rettung^^.

Wert wurde bisher sowieso nur einmal pro Triangle berechnet, aber ergebnis-3, halt eben pro pixel, so wie jetzt auch.
Gibt aber sicherlich noch andere sachen die ich optimieren muss, war halt die größte bremse^^


MFG
Memnarch
Meine Website mit Updates/News zu Aktuellen Projekten:SpareTime-Development

GR-PA

Treue Seele

Beiträge: 326

Wohnort: Daheim

Beruf: Faulenzer

  • Private Nachricht senden

15

30.05.2011, 20:03

Ein kleiner Testlauf des C++ Äquivalents dieses Codes: (2.147.483.647 Berechnungen, Release Mode, VC++ 2010, Invertierte Werte vorberechnet)

Zitat

10000
123456789
Asm: 12345 in 4976 ms
Float: 12345.7 in 0 ms
Double: 12345.7 in 0 ms
Normal: 12345 in 0 ms

5 Sekunden sprechen für sich... und gegen diesen Code...

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
int Inverse;
int DoCalcAsm(int test)
{
    int res;
    __asm
    {
    mov eax,[test]
    mul [Inverse]
    mov [res],edx
    };
    return res;
}


und besonders viel leichter zu lesen als dieser

C-/C++-Quelltext

1
2
3
4
5
int DoCalcNormal(int test, int wert)
{
    int res;
    return test / wert;
}


oder dieser Code

C-/C++-Quelltext

1
2
3
4
5
float fpInv;
float DoCalcFloat(float test)
{
    return test*fpInv;
}

ist er auch nicht gerade...

Selbst im Debug-Modus sind Fließkommazahlen mit vorberechnetem Kehrwert etwas schneller, die "Normale" Version ist dann 1000 ms langsamer.
Diesmal nur 90 Millionen Berechnungen jeder Art.

Zitat

Asm: 12345 in 3666
Float: 12345.7 in 3650
Double: 12345.7 in 3432
Normal: 12345 in 4649


Höchstens ein #pragma optimize ("", off) um die Funktionen ohne den asm Code lässt diesen Code effizienter erscheinen ;) (900 Millionen Berechnungen)

Zitat

Asm: 12345 in 1108
Float: 12345.7 in 13541
Double: 12345.7 in 13494
Normal: 12345 in 12573


Nebenbei sind die normale Version und die Version mit Fließkommazahlen sehr viel leichter zu verstehen...

Zeigt sehr schön das man bei solchen Sachen dem Compiler das letzte Wort lassen sollte (den asm Code kann der nämlich nicht optimieren was man an den Messungen sehr schön erkennen kann)
Wenn du mit einer anständigen Programmiersprache und einem anständigen Compiler arbeiten würdest, dann würde ich dir jetzt empfehlen dich nicht mit so einem sch... ähh... solchen Kleinigkeiten aufzuhalten und lieber sinnvollere Optimierungen wie SSE zu implementieren...
In Delphi mag das ganze ja eine Optimierung sein [...] (Hassrede über Delphi im letzten Moment unterdrückt... Hab ich schon mal erwähnt wie sehr ich Delphi hasse?)
Signaturen werden überbewertet

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

16

30.05.2011, 20:14

Sry, aber deine Testergebnisse sind ohne jede Aussage, der Compiler hat eindeutig deinen gazen Testcode wegoptimiert nur bei __asm ist er wie immer gezwungen den Optimizer abzuschalten sodass nur im Falle von asm wirklich ein Test durchgeführt wurde.

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »dot« (30.05.2011, 20:25)


17

31.05.2011, 00:05

@GR-PA: und mal ganz nebenbei: So wirklich schnallen tust du das nicht oder, dass ich auf einem P4 untwerwegs bin. Wenn du schon was testen willst, dann bitte mit selber CPU. FloatingPoint war bisher immer langsamer als Integer, nur ist dieser abstand bei modernen CPUs nicht mehr so groß.(und wie dot schon erwähnt hat, schöner testcode^^)
Auf meinem P4 sind 1millionen kalkulationen zudem die steinwand, die sich aus Function Calls ergibt.
Immer

Quellcode

1
2
3
4
5
6
7
8
9
10
11
int DoCalcAsm(int test)
{
    int res;
    __asm
    {
    mov eax,[test]
    mul [Inverse]
    mov [res],edx
    };
    return res;
}


auszuführen verbraucht einen vergleichbar zur hohen overhead für den call. Hatte eine funktion die mir die Fläche eines Dreeicks berechnet hat(musste damals das ding noch pro pixel machen). Diese funktion nur Inline zu schreiben, ohne optimierung, brachte schon 10% mehr geschwindigkeit(natürlich hatte ich danach noch die möglichkeit das ganze auch gleich zu optimieren^^).
ABer wo ich das gerade lese..mh ich bin noch imemr im Debugmodus unterwegs...am Mittwoch gleichmal testen wies ohne debuggen ist. Dann müssen ja keine "live updates" mehr gesammelt werden....damn :D

EDIT: mh release ist genauso schnell wie debug, liegt wohl daran dass er ohne breakpoint keine debuginfos reinkloppt >.<. AUf meinem home PC brauchen 1Mrd der asm variante 1 Secunde.(dualcore 2.66GHZ). Hab hier zuhause dann doch nochmal schnell was zusammengekloppt...^^
Meine Website mit Updates/News zu Aktuellen Projekten:SpareTime-Development

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Memnarch« (31.05.2011, 00:22)


xardias

Community-Fossil

Beiträge: 2 731

Wohnort: Santa Clara, CA

Beruf: Software Engineer

  • Private Nachricht senden

18

31.05.2011, 00:25

Hehe, Compiler sind manchmal halt einfach zu intelligent ;)

Aber ja, float ginge sicher auch, ist vermutlich aber doch 'nen ganzen Tick langsamer.

Glaub ich eben nicht. Floating-Point sollte auf einer halbwegs aktuellen CPU nicht wirklich langsamer sein als Integer-Arithmetik. Die Instruction Latencies waren jedenfalls noch gleich als ich das letzte Mal nachgeschaut hab, d.h. Unterschiede kommen wenn dann vielleicht von der Möglichkeit zur out of order Execution.


Soweit ich weiß ist der Throughput von den FP Multiplizierern nur eine Multiplikation pro 2 cycles, wärend die Integer Multiplizierer nur 1 cycle für die execute stage brauchen.

Aber ich denke du hast trotzdem recht, man kann deswegen jetzt nicht gleich behaupten, dass die FP Variante deswegen nur halb so schnell ist. Die FP Multiplikation wird auf einer separaten Einheit berechnet, d.h. wärend der Berechnung, kann die CPU weitere Befehle ausführen, so lange keine Resource Hazards vorkommen. Im Endeffekt wird das vermutlich nur in speziell konstruierten Extremfällen einen spürbaren Unterschied machen.

Memnarch: Hyperthreading heißt soweit ich weiß nicht, dass du in einem Thread nur die halbe Performance zur Verfügung hast. Das Scheduling wird dynamisch vom Prozessor gemacht, wenn nur dein Thread auf Last läuft, dann kriegt der auch die volle Performance.

19

31.05.2011, 00:36

Nope. Bei Hyperthreading gibt es 2 varianten: Reihenschaltung, Paralellschaltung(ob die bezeichnung so stimmt weiß ich jetzt nicht^^"). Bei einem von beidem ist die CPU gesplitte und punkt. Bei der anderen wie du es beschrieben hast kann auch ein Thread alles bekommn. Ein Thread bekommt auch bei mir im Taskmanager nie mehr als 50%(+-4) o.O.

SSE werde ich mir mal angucken, noch nicht zu gekommen.

PS: Guten morgen Xardias :D

MFG
Memnarch
Meine Website mit Updates/News zu Aktuellen Projekten:SpareTime-Development

Sylence

Community-Fossil

Beiträge: 1 663

Beruf: Softwareentwickler

  • Private Nachricht senden

20

31.05.2011, 07:28

Ein Thread bekommt auch bei mir im Taskmanager nie mehr als 50%(+-4) o.O.


Ja weil es nur ein Thread. Ein thread kann nicht auf 2 Kernen gleichzeitig laufen.

Quellcode

1
while( true ) ;


Das erzeugt bei mir nur 25% CPU Last laut Taskmanager. Das heißt aber nicht, dass ich nur 625MHz bekomme...

Werbeanzeige