lohnt sich Rechnen auf GPU?



  • Hallo,

    ich arbeite an einem Programm, welches Grafiken erstellt und für jeden Punkt große Berechnungen durchführen muss. Obwohl alle konstanten Terme bereits vorausberechnet werden, kann eine Grafik zu 100x100 Punkten schon Stunden in Anspruch nehmen. Das liegt an aufwendigen numerischen Integrationen, wobei dafür hauptsächlich Additionen und Multiplikationen nötig sind.

    Dieses Problem lässt sich hervorragend parallelisieren, allerdings schafft meine CPU "nur" 8 Threads gleichzeitig. Ich dachte daher daran, die Berechnung auf die GPU zu verlagern. Da ich allerdings überhaupt keine Ahnung von dem Gebiet habe, wollte ich euch fragen, ob es in diesem Fall überhaupt Sinn macht und möglich ist (Ich besitze eine nVidia Karte und arbeite unter Linux).

    Vielen Dank für eure Tipps!



  • Hm, da braucht man mehr Infos. was macht das Programm? Wie sind die Abhängigkeiten, bzw. die Kommunikationsstruktur? Und was bedeutet für Dich "lässt sich hervorragend parallelisieren"?



  • Hallo, danke für dein Interesse. Ich berechne Likelihoods für physikalische Modelle, habe also einen Satz von Parametern und berechne die Wahrscheinlichkeit für verschiedene Kombinationen, die umfangreiche Kombinationen von Additionen und Multiplikationen (und auch vereinzelt Wurzeln) beinhaltet. Umfangreich wird es, wenn ich numerisch marginalisiere, also die Likelihood nochmal über einen Parameter integriere. Ich rechne also bei einem 200x200 px Plot 200*200*x (wobei x die Anzahl der Schritte bei der numerischen Integration sind) mal die gleiche Funktion, wobei sich nur die Anfangsparameter ändern.

    Jeder Thread könnte also z.B. einen Funktionswert für gegebene Parameter berechnen (oder eine ganze Reihe von Funktionswerten, je nachdem, was effizienter ist). Er würde also einen Satz von doubles erhalten (nur eine handvoll) und müsste einen doouble liefern. Im Moment berechnen meine Threads (über die CPU) gleich eine ganze Reihe von Funktionswerten und liefern dementsprechend einen Vektor von Funktionswerten.

    Edit: Um es zu präzisieren: Ich habe eine nVidia GT 540M, also Fermi Architektur.



  • ja eine Grafikkarte sollte mit diesem Problem sehr glücklich werden. Andererseits glaube ich erstmal nicht, dass das für eine CPU so schwierig sein sollte. Das klingt erstmal nach einer sehr dankbaren Aufgabe.



  • ich denke die performance wird nicht besser, da die double performance auf GPUs, gerade auf den kleinen, nicht so ueberragend ist. hmm, ich glaube die 520m sollte 32gflops haben bei double, mit avx duerfte dein quad core ca 50GFlops haben.

    1. beides nutzen 🙂
    2. vielleicht mit floats versuchen. (dann bist du bei 100gflops auf cpu + 250 gflops auf gpu).



  • Eine GPU, die praktisch nix anderes drauf hat als unzählige Ausführungseinheiten um auf Flops zu kommen hat gerade mal 2.5x soviel Durchsatz wie eine CPU, die, wovon ich jetzt ausgehe, bloß soviele parallele Berechnungen machen kann, wie der Vektor-Befehlssatz darauf zulässt? Also 16 parallele Operationen auf einem Quadcore oder so? Da könnte man doch 2 CPUs nehmen, noch ein bissl was fest verdrahten und hat ne neue, flexible Grafikkarte! Warum geht durch die GPUs nur "so wenig"?



  • Naja, eine 540M ist ja eher ein Grafikentschleuniger 😉

    Mit ordentlichen Grafikkarten sieht das dann schon anders aus. Wobei man auch da aufpassen muss ob SP oder DP Fließkomma. z.B. die GTX 680 z.B. hat ein vergleichsweise schlechtes DP/SP-Verhältnis (1/12), während die GTX 580 dort deutlich besser aussieht (iirc 1/4 oder 1/3).



  • Kann sich lohnen. Auch musst du dir evtl. deinen Threading code ansehen, und ob du da evtl. bessere Ergebnisse mit ThreadPools/TBB/PPL bekommst.
    C++ AMP könnte evtl. dir die nutzung von CPU und GPU in einem ermöglichen, evtl. ist es aber sinnvoller das zu trennen.

    Letzten Endes wirst du dein Problem vereinfachen müssen, und dann damit ein erstes Testprogramm schreiben, was dir zeigt, wie es mit der Performance auf deiner Hardware läuft. Das kann leider sehr zeitintensiv sein, gerade wenn du mehrere Frameworks wie OpenCL oder Thrust testen willst. Schau dir evtl. auch mal odeint an, das bietet da erste Ansätze, falls du ODEs lösen musst.



  • Danke für eure Antworten.

    Leider kann ich nicht auf double verzichten.
    Mittlerweile ist mein Programm schon gut gewachsen. Wie funktioniert das mit der Integrierbarkeit? Kann ich z.B. CUDA benutzen und einfach eine Device-Funktion schreiben und die von C++ aus aufrufen?



  • Ulf schrieb:

    Kann ich z.B. CUDA benutzen und einfach eine Device-Funktion schreiben und die von C++ aus aufrufen?

    ja, an sich schon, schau dir da mal das kleine beispiel an, ich denke das ist selbsterklaerend:
    http://code.google.com/p/cfdlab/source/browse/trunk/cuda/vecAdd.cu?r=43&spec=svn43

    @Decimad
    eine 300euro GPU bzw graka hat 4TFlops float durchsatz, eine 500euro CPU kommt auf 0.3TFlops.

    es kommt halt drauf an was du machst und wie gut du es optimierst.



  • Das ist doch schon eher das, was ich mir vorgestellt hatte. Ist die genannte Graka so schlecht, dass es zu den Beispielwerten von Dir kam?



  • Nach http://de.wikipedia.org/wiki/Nvidia_Geforce_M schafft die 540M immerhin 21,5 GFlops, meine CPU i7-2630QM (die auch wahrlich nicht die langsamste ist) schafft, wenn man manchen Bechmark glauben darf, um die 10 GFlops (bei Parallelisierung).

    Danke für eure Tipps, ich werde mich nun mal intensiver mit CUDA beschäftigen.



  • Decimad schrieb:

    Das ist doch schon eher das, was ich mir vorgestellt hatte. Ist die genannte Graka so schlecht, dass es zu den Beispielwerten von Dir kam?

    jup, ist
    1. eine mobile graka (die sind eh schon beschnitten wegen verbrauch)
    2. eine casual graka (die brauchen normalerweise garkeine double berechnungen leisten).

    der vorgaenger von der 5x0m, also 4x0m oder 3x0m (kann mich nicht 100% erinnern), konnte garkein double und der treiber hat entweder nichts gemacht oder alles implizit auf float gestellt.

    @ulf, du hast recht sind 21.5 und nicht 32.5, hatte ich falsch im kopf (1/12 statt 1/8 vom single durchsatz), jedoch vergleichst du da aepfel mit birnen. 21.5 ist ein theoretischer wert waehrend die 10GFlops scheinbar ein benchmark wert sind. ich habe kurz gegoogled und vom i7-2630QM benchmarks mit >30GFlops double leistung gefunden.

    ich weiss nicht ob du schon threads nutzt, aber ich empfehle dir, fuer den fall das nicht, dir mal openmp anzuschauen, damit kannst du durch eine zeilen aenderung und ein compile flag, vielleicht 4mal schneller rechnen.


Log in to reply