Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   grundsätzliche Frage zu Multithreading (https://www.delphipraxis.net/173956-grundsaetzliche-frage-zu-multithreading.html)

Gargamel 26. Mär 2013 07:38

grundsätzliche Frage zu Multithreading
 
Hi

Die Tage habe ich die Geschwindigkeit von C#, Delphi und C++ getestet. Dazu habe ich in einer 10-Mio.-For-Schleife einen Vektor normalisiert. Dabei kam heraus, dass C# dafür 1,5 Sekunden benötigt. Delphi 0,5 Sekunden und C++ irgendwas um 0,003 Sekunden. Dass C# am langsamsten ist, dachte ich mir fast. Aber der Unterschied zwischen Delphi und C++ ist arg groß. Da ich nun für meine KI jeden Leistungsvorteil nutzen möchte, will ich sämtliche Berechnungen über C++ erledigen, wobei die Verwaltung der KI selbst in Delphi erfolgt.
(Ich mag halt Delphi und will C++ nur dann nutzen, wenn es unbedingt nötig ist)

Der Aufbau sieht so aus: Hauptprogramm(3D-Engine) --> KI(Delphi-DLL) --> reine Berechnungen(C++-DLL)

Was mich nun interessieren würde ist, inwieweit sich das mit Multithreading vereinbaren lässt. In der Delphi-DLL werden, z.B. bei einem Quad-Core, 4 Threads erstellt, die ständig auf exportierte Funktionen der C++-DLL zugreifen (Pathfinding, Fuzzy-Logic, usw.).

Geht das so überhaupt?

Danke

Der schöne Günther 26. Mär 2013 08:14

AW: grundsätzliche Frage zu Multithreading
 
Ich sehe jetzt nicht ganz, eine weitere "Zwischen-DLL" überhaupt nötig ist, aber noch eher glaube ich, dass man den generellen Performance-Unterschied jetzt nicht an einer Vektor-Operation festmachen sollte. Ich glaube nicht, dass es so einen argen Unterschied gibt... :oops:

Neutral General 26. Mär 2013 08:15

AW: grundsätzliche Frage zu Multithreading
 
Eine weitere Idee um es ggf. in Delphi noch schneller zu kriegen:

1. inline funktion
2. inline assembler (ggf. sogar mit MMX, SSE ?)

Dann sparst du dir den ganzen C++ Kram.

Medium 26. Mär 2013 08:32

AW: grundsätzliche Frage zu Multithreading
 
Und wenn man wirklich das letzte Bischen herausquetschen will, wäre Bei Google suchenCUDA bzw. Bei Google suchenOpenCL eine prima Sache. Gerade für Aufgaben wie "führe N Mal die gleiche Operation auf Member in einem langen Datenstrom aus". In welcher Sprache man das dann einbettet dürfte auch ziemlich egal werden. Ansonsten stimme ich zu: Es kommt auch stark darauf an, wie man konkret gecoded hat. Delphi ist sicherlich nicht per se langsamer als C++, beide erzeugen ähnlich performanten Maschinencode. Die Frage ist, ob du die Aufgabe in Delphi für Delphi sinnvoll optimiert umgesetzt hast. (Nutzung von SSE via inline asm wäre ein ähnliches Schmankerl wie GPGPU, aber da würde ich eher zu letzterem greifen, wenn man schon was neues lernen muss. Zudem krallt man sich damit dann auch nicht so arg an eine Architektur.)

Gargamel 26. Mär 2013 08:34

AW: grundsätzliche Frage zu Multithreading
 
@Günther

Wie gesagt, die reine Verwaltung mache ich lieber in Delphi. Nur den Mathe-Kram würde ich gerne wegen der Geschwindigkeit auslagern.

@General

Inline Assembler kann ich nicht nutzen, da der 64bit-Delphi-Compiler sowas nicht kann. (Delphi XE3)

Gargamel 26. Mär 2013 08:39

AW: grundsätzliche Frage zu Multithreading
 
@Medium:

Mit CUDA binde ich mich leider an nVidia. Für ein Spiel ist das nicht sinnvoll. OpenCL hingegen klingt ganz gut.

Neutral General 26. Mär 2013 08:45

AW: grundsätzliche Frage zu Multithreading
 
@Gargamel: Soweit ich weiß kannst du zwar keine kompletten inline-Funktionen mit asm - end machen aber du kannst glaube ich sowas machen:

Delphi-Quellcode:
begin
  asm

  end;
end;
? Kann mich aber auch täuschen.

Ansonsten probier mal deine Funktion zum normalisieren von Vektoren mit inline; zu markieren.
Ich denke das sollte wie gesagt auch noch mal etwas bringen.

Aphton 26. Mär 2013 09:08

AW: grundsätzliche Frage zu Multithreading
 
Es wäre sowieso kein gültiger Vergleich, wenn beide Algorithmen nicht zu 100% identisch ablaufen. Dh. wenn in C++ geinlinet wird, dann muss in Delphi das auch geschehen und vice versa. Von daher ist es eig. relativ egal.

Ich würde übrigens gerne Code sehen...

Der schöne Günther 26. Mär 2013 09:09

AW: grundsätzliche Frage zu Multithreading
 
Das gehört hier wahrscheinlich nicht mehr hin.

Aber gibt es überhaupt Nvidia-Karten mit OpenCL? Ich dachte die bleiben weiterhin bei CUDA. Auch haben Sie das Format geöffnet, vielleicht springt ja sogar ATI auf diesen Zug auf...

Blup 26. Mär 2013 09:15

AW: grundsätzliche Frage zu Multithreading
 
Ein Unterschied von 2-5% zwischen den einzelnen Compilern ist durchaus denkbar, deine Ergebnisse mit hundertfacher Laufzeit deuten aber eher auf Fehler in der Implementierung hin.
Assembler ist wirklich nur das letzte Mittel, wenn alle anderen Optimierungen schon durch sind. OpenCL scheint hier der bessere Weg zu sein.

Multithreading und DLL-Aufrufe geht natürlich, sofern die Funktionen in der DLL auch threadsicher implementiert sind oder nur von einem Thread verwendet werden.

Gargamel 26. Mär 2013 10:20

AW: grundsätzliche Frage zu Multithreading
 
Zitat:

Multithreading und DLL-Aufrufe geht natürlich, sofern die Funktionen in der DLL auch threadsicher implementiert sind oder nur von einem Thread verwendet werden.
Wobei mich ja genau das interessiert. Die Funktion in C/C++ sieht so aus:

Delphi-Quellcode:
__declspec(dllexport) int calcCPP(void)
{
   int sum = 0;
   for (int i = 0; i < (100000000 - 1); i++)
        {
            float vecX = 5.7458F;
            float vecY = 3.758F;
            float vecZ = 7.12544F;

            float len = sqrt(vecX*vecX+vecY*vecY+vecZ*vecZ);

            float normX = vecX / len;
            float normY = vecY / len;
            float normZ = vecZ / len;

         sum+=1;
        }
   return sum;
}

Neutral General 26. Mär 2013 10:24

AW: grundsätzliche Frage zu Multithreading
 
Und in Delphi?

Gargamel 26. Mär 2013 10:27

AW: grundsätzliche Frage zu Multithreading
 
Delphi-Quellcode:
procedure calcDelphi();
var vecX, vecY, vecZ, len, normX, normY, normZ:single;
    i:integer;
Begin
  for i:=0 to 100000000 - 1 do
  Begin
    vecX:= 5.7458;
    vecY:= 3.758;
    vecZ:= 7.12544;

    len:=Sqrt(vecX*vecX+vecY*vecY+vecZ*vecZ);

    normX:= vecX / len;
    normY:= vecY / len;
    normZ:= vecZ / len;
  End;
End;

procedure calcDelphi_withCPP();
Begin
  calcCPP(); // importierte Funktion
End;

Sir Rufo 26. Mär 2013 10:33

AW: grundsätzliche Frage zu Multithreading
 
Wobei ich bei solchen Implementierungen immer vorsichtig wäre, denn hier könnte der Compiler auch einfach die Berechnungen wegoptimieren, denn die Ergebnisse sind rein lokal ;)

Und gleich implementiert sind die auch nicht

Neutral General 26. Mär 2013 10:35

AW: grundsätzliche Frage zu Multithreading
 
Mach doch am besten mal eine Funktion mit der du allgemein einen Vektor normalisierst.
Und die rufst du dann 1000000x auf oder so.
Macht das einen Unterschied?

Kann mir kaum vorstellen dass C++ da so viel schneller sein kann.

Gargamel 26. Mär 2013 10:37

AW: grundsätzliche Frage zu Multithreading
 
@General:
Habe ich schon gemacht. In CPP wurde nur die reine Funktion implementiert und in Delphi x-mal aufgerufen. Das Ergebnis war, dass die benötigte Zeit in Delphi von 0,5 Sekunden auf 0,2 Sekunden sank.

Gargamel 26. Mär 2013 10:40

AW: grundsätzliche Frage zu Multithreading
 
@Sir Rufo: Ich hatte einen ähnlichen Gedanken. Möglicherweise erkennt der CPP-Compiler, dass in der Funktion eh immer die gleichen Werte berechnet werden und ruft die Funktion halt nur 1x auf, statt die ganze Schleife komplett durchzulaufen.

Neutral General 26. Mär 2013 10:44

AW: grundsätzliche Frage zu Multithreading
 
Ich meinte eher dass du sowohl in C++ als auch in Delphi den Code so umänderst dass du jeweils eine
normalisiereVektor-Funktion hast. Quasi unter realen Bedingungen^^

Delphi-Quellcode:
type
  TVector = record
    x,y,z: Single;
  end;

function normalisieren(AVector: TVector): TVector; // inline;
var len: Integer;
begin
  len := sqrt(AVector.x*AVector.x+AVector.y*AVector.y+AVector.z*AVector.z);
  Result.x := AVector.x / len;
  Result.y := AVector.y / len;
  Result.z := AVector.z / len;
end;

procedure Testen;
var i: Integer;
    vec: TVector;
begin
  for i:=0 to 100000000 - 1 do
  begin
    vec.x := 5.7458;
    vec.y := 3.758;
    vec.z := 7.12544;
    vec := normalisieren(vec);
  end;
end;
Das gleiche dann nochmal in C++ und dann nochmal die Geschwindigkeit messen.

jfheins 26. Mär 2013 10:52

AW: grundsätzliche Frage zu Multithreading
 
Also bei 10 Mio habe ich ja schon gestutzt. Aber 100 Mio. Berechnungen in 0,003 Sekunden ... no way!

Bei einem 3GHz Rechner sind das 11 Berechnungen (Schleifendurchläufe) pro Takt. Da das ganze nicht irgendwie parallelisiert ist, kann das nicht sein!
Du hast da irgendwo einen Fehler im Vergleich drin, die genannte Optimierung wird sicherlich durchgeführt.

Der Vollständigkeit halber wäre ich auch noch an deinem C# Quellcode interessiert :stupid:

Gargamel 26. Mär 2013 10:54

AW: grundsätzliche Frage zu Multithreading
 
@General: Gerade probiert. Jetzt braucht Delphi 1,9 Sekunden.

Neutral General 26. Mär 2013 10:55

AW: grundsätzliche Frage zu Multithreading
 
Und in C++ ? (darum gings ja in erster Linie :D)
Und dann noch den C# Code! :mrgreen:

Gargamel 26. Mär 2013 10:56

AW: grundsätzliche Frage zu Multithreading
 
@jfheins: Gerne doch.

Delphi-Quellcode:
void calcCSharp()
    {
        for (int i = 0; i < (100000000 - 1); i++)
        {
            float vecX = 5.7458F;
            float vecY = 3.758F;
            float vecZ = 7.12544F;

            float len = Mathf.Sqrt(vecX*vecX+vecY*vecY+vecZ*vecZ);

            float normX = vecX / len;
            float normY = vecY / len;
            float normZ = vecZ / len;
        }
    }

Sir Rufo 26. Mär 2013 10:56

AW: grundsätzliche Frage zu Multithreading
 
@Gargamel

Implementiere doch mal in allen 3 Sprachen die Funktion
Delphi-Quellcode:
type
  TVector = record
    x,y,z: Single;
  end;

function normalisieren(AVector: TVector): TVector; // inline;
var len: Integer;
begin
  len := sqrt(AVector.x*AVector.x+AVector.y*AVector.y+AVector.z*AVector.z);
  Result.x := AVector.x / len;
  Result.y := AVector.y / len;
  Result.z := AVector.z / len;
end;
exact gleich und führe dann deine Messung erneut durch. Diese Werte wären interessant im Vergleich zu sehen

Gargamel 26. Mär 2013 11:05

AW: grundsätzliche Frage zu Multithreading
 
Mit dem nachfolgenden C++-Code sind es 0,8 Sekunden.

Delphi-Quellcode:
TVector normalisieren(TVector AVector)
{
  float len = sqrt(AVector.x*AVector.x+AVector.y*AVector.y+AVector.z*AVector.z);
  AVector.x = AVector.x / len;
  AVector.y = AVector.y / len;
  AVector.z = AVector.z / len;
  return AVector;
}

__declspec(dllexport) void cppTesten()
{
  TVector vec;
  for (int i=0; i< 100000000 - 1; i++)
  {
    vec.x = 5.7458F;
    vec.y = 3.758F;
    vec.z = 7.12544F;
    vec = normalisieren(vec);
  }
}

Gargamel 26. Mär 2013 11:14

AW: grundsätzliche Frage zu Multithreading
 
@alle: Damit jetzt alle drei Sprachen abgedeckt wurden, hier noch der C#-Code. Die benötigte Zeit hierfür beträgt 2,9 Sekunden.

Delphi-Quellcode:
public struct TVector
    {
        public float x;
        public float y;
        public float z;
    }

////////////////////////////

public TVector normalisieren(TVector AVector)
    {
        float len = Mathf.Sqrt(AVector.x * AVector.x + AVector.y * AVector.y + AVector.z * AVector.z);
        AVector.x = AVector.x / len;
        AVector.y = AVector.y / len;
        AVector.z = AVector.z / len;
        return AVector;
    }

void calcCSharp_V2()
    {
        TVector vec;
        for (int i = 0; i < 100000000 - 1; i++)
        {
            vec.x = 5.7458F;
            vec.y = 3.758F;
            vec.z = 7.12544F;
            vec = normalisieren(vec);
        }
    }

Neutral General 26. Mär 2013 11:18

AW: grundsätzliche Frage zu Multithreading
 
Also ernsthaft.. Jetzt würde ich noch gerne den Maschinencode der normalisieren Funktion in Delphi und C++ sehen :mrgreen:

Wo spart C++ denn da über die Hälfte der Zeit?

Robotiker 26. Mär 2013 11:38

AW: grundsätzliche Frage zu Multithreading
 
Zitat:

Zitat von Blup (Beitrag 1208844)
Ein Unterschied von 2-5% zwischen den einzelnen Compilern ist durchaus denkbar,

Der Unterschied zwischen den (32 Bit-) Compilern vom C++ Builder und Visual C++ ist durchaus größer als 2-5%, eher manchmal 20-50% bei gleichem Code.

Zitat:

Zitat von Neutral General (Beitrag 1208907)
Wo spart C++ denn da über die Hälfte der Zeit?

Von welchem Compiler reden wir eigentlich ?
Schlägt da ein Vektorisierer zu, wie bei Microsoft oder Intel ?
http://msdn.microsoft.com/de-de/library/hh872235.aspx

Gargamel 26. Mär 2013 11:59

AW: grundsätzliche Frage zu Multithreading
 
1. Für C++ habe ich Visual C++ 2010 Express verwendet. Ahnung habe ich aber nicht, welche Optimierungen da vorgenommen werden.

2. Thema Multithreading: Nehmen wir an, es ist ein QuadCore, ich erstelle 4 Threads und es gibt 4 KI-Objekte. Jedes Objekt läuft auf einem separaten Kern. Jetzt wird, auch angenommen, ständig in jedem Objekt ein Vektor normalisiert. Die vier Threads laufen über Delphi, jedoch wird die "normalisieren"-Funktion aus einer C++-DLL aufgerufen. Würde das funktionieren oder gibt es da Probleme?

Sir Rufo 26. Mär 2013 12:02

AW: grundsätzliche Frage zu Multithreading
 
Letztens las ich erst, dass man für intensive Berechnungen 2*CPUKerne an Threads benutzen kann.

Die aufgerufenen Funktionen laufen immer in diesem Kontext (wenn man das nicht aktiv ändert und in einen weiteren Thread übergibt)

Der schöne Günther 26. Mär 2013 12:05

AW: grundsätzliche Frage zu Multithreading
 
Jeder Thread hat doch seinen eigenen Stack, das Beispiel mit der Vektor-Normalisierung dürfte doch problemlos klappen?

Robotiker 26. Mär 2013 12:17

AW: grundsätzliche Frage zu Multithreading
 
Zitat:

Zitat von Gargamel (Beitrag 1208917)
1. Für C++ habe ich Visual C++ 2010 Express verwendet. Ahnung habe ich aber nicht, welche Optimierungen da vorgenommen werden.

Den automatischen Vektorisierer gibt es erst ab 2012.

Aber wie schon gesagt, dass VC++ bei gleichen Code deutlich schneller ist als der Builder, ist völlig normal. Das ein gewisser Unterschied auch zu Delphi besteht, ist nicht ausgeschlossen.

Gargamel 26. Mär 2013 12:30

AW: grundsätzliche Frage zu Multithreading
 
Ich danke erstmal allen hier.

Vermutlich werde ich es so machen, dass ich alle Verwaltungsaufgaben der KI über Delphi erledige und komplexere Berechnungen C/C++ überlasse.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:10 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz