Programme für die GPU in C/C++

PC-Kurbel

Cadet 1st Year
Registriert
Okt. 2010
Beiträge
10
Hallo erstmal von mir aus hier an die Geräte zu Hause,

Bisher hatte ich nicht allzuviel mit Programieren zu tun. Nun soll ich aber ein Programm in C oder C++ schreiben, dass monatelang rechnet und am Ende hoffentlich was tolles herauskommt. Da sich das Problem sehr gut parallelisieren lässt, habe ich vor die GPU mit dem Problem zu beauftragen. Nun habe ich aber leider keine Einsteigerfreundliche Anleitung gefunden. Daher habe ich noch ein paar Fragen:

1. Was brauche ich dafür an Programmen? Ich habe eine Ati/Amd Karte, daher habe ich Ati Stream runtergeladen und MS Visual Studio 2010 gabs von der Uni. Habe ich alles?

2. Wie erreiche ich, dass das Programm auf der Grafikkarte läuft und nicht doch in der CPU?

3. Gibt es gravierende Unterschiede zum Code für Programme für die CPU?

4. Kennt jemand eine gute Anleitung in das Thema?

Ich hoffe es kann mir jemand etwas helfen.

Eure PC-Kurbel
 
Hi,

schau dir als erstes mal den User Guide von Stream an. Da sollte vieles beantwortet werden.
 
PC-Kurbel schrieb:
2. Wie erreiche ich, dass das Programm auf der Grafikkarte läuft und nicht doch in der CPU?
Gar nicht - Grafikkarten sind immer noch Grafikkarten und keine CPUs. Die GPU kann nur benutzt werden, um kleine Teile des Programms parallel auf mehrere Daten auszuführen. Da du auch nicht schreibst, wofür genau du die GPU verwenden willst, so würde ich dir zunächst einmal Assembler-Code mit SSE empfehlen. Ist wohl trotz Assembler noch einfacher zu Programmieren als die ganzen GPU-Sachen und kann ebenfalls sehr viele Sachen beschleunigen. Außerdem solltest du keine Performance-Steigerung auf der GPU erwarten - dazu ist gewaltiges Wissen über die Architektur der Grafikkarte erforderlich, ansonsten wird das ganze eher langsamer als auf der CPU.
 
Also das ganze ist für eine Promotion im Bereich Physik. Ich denke die Details erspare ich euch lieber, aber ich erkläre mal kurz das Prinzip. Ich habe eine Liste von Eingangsdaten. Jeder Punkt auf dieser Liste wird dann einzeln und unabhängig von den anderen bearbeitet und man erhält eine neue Liste. Diese neue Liste wird durch paarweise Vergleiche vereinfacht und dann geht es wieder von vorne los. Das Bearbeiten der Liste(n) kann prima parallel ablaufen. Daher die Idee mit der GPU.

Falls dort wirklich enormes Wissen erforderlich ist, rechtfertigt der Aufwand die Mittel nicht. Klang auf Seiten im Internet eigentlich machbar, aber dort stand dann auch nie wie es geht.

Aber vielen Dank schonmal für die schnellen Antworten.

Eure PC-Kurbel
 
Falls du kompletter Programmieranfänger bist, hast du dir schon einiges vorgenommen. In dem Fall würd ich den Algorithmus zuerst mal in C++ implementieren zur Übung. Ganz nach dem Motto: "First make it run, then make it fast". Soo gewaltig ist das "Wissen" nun auch nicht, es gibt genügend Tutorials dafür. ;)
 
Der Anwendungsbereich wäre zumindest nach deiner Erklärung schon gut für GPU Computing geeignet. Prinzipiell würde es so funktionieren, dass du für die Eingangsdaten und Ausgangsdaten von der CUDA/OpenCL/Stream/"wie auch immer" API einen Puffer anlegen lässt. Die Puffer werden dann zusammen mit dem GPU Binärcode an die GPU übergeben und diese führt den Binärcode parallel für die Daten aus. Was man beim GPU Computing gern übersieht ist, dass die GPUs kaum für Sprünge (z.B. if-Anweisung) geeignet sind. So lange man wirklich Hardcore Mathematik ohne große Sprünge ausführen will, läuft das ganze recht gut.

Falls du es wirklich probieren willst, so wäre hier ein kleines Tutorial.

Green Mamba schrieb:
Soo gewaltig ist das "Wissen" nun auch nicht, es gibt genügend Tutorials dafür. ;)
Das schwierige daran ist weniger, das ganze zum Laufen zum bekommen. Viel aufwändiger ist es vernünftige Performance herauszubekommen. Ich hab zwar schon länger nichts mehr mit den Shadern der Grafikkarten zu tun gehabt, aber meine letzten versuche mit Pixel-Shader 2.0 haben doch ein bisschen was hinterlassen.
 
Zuletzt bearbeitet:
Beim ATI Stream SDK liegen auch diverse Beispiele und ein "Getting started Guide" bei. Diese sollten nach der SDK-Installation über das Startmenü erreichbar sein.
 
Ich habe schon ein bischen Programiererfahrung gesammelt und eher einfache Programme geschrieben. Allerdings nicht sehr viel und es ist schon Jahre her. So rein Programmiertechnisch ist das Programm wirklich nicht anspruchsvoll, sondern einfach nur rechenintensiv. Eine lauffähige Version habe ich schon in C, allerdings kommt nicht das raus was rauskommen soll, daher steckt irgendwo der Wurm drin. Vielen Dank für die weiteren Antworten.
 
Zuletzt bearbeitet:
Was für eine ATI-Karte hast du denn?
Dir sollte klar sein, dass die Performance-Steigerung nicht übermäßig gewaltig ausfallen wird.
Zu CUDA gabs mal so eine Seite die eine Sammlung wissenschaftlicher Projekte aufgezählt hat mit dem jeweiligen Hinweis, um welchen Faktor die Beschleunigung stattgefunden hat. Ich find die Seite gerade leider nicht, aber Werte über 20 waren selten - und das waren halt Programmierprofis die sowas hinbekommen.
Stell dir vor du erreichst Faktor 5. Wars dann den Aufwand wert? Also wenn die Berechnung nicht mehr 5 Monate dauert sondern nur noch einen?
Um 5 zu erreichen ist schon viel Wissen und sehr viel mühsame Programmierung nötig - und man kann meistens auch normale C-Programme mit weniger Aufwand extrem beschleunigen.

Die grundsätzliche Frage die du dir stellen solltest ist aber auch: Hängt es überhaupt an mangelnder CPU-Leistung? Hierfür wäre Code-Profiling einer nicht einfach nur hinprogrammierten sondern optimierten C(++) Version vorweg nötig. Weil wenn es zB am IO liegt oder an ineffizienter Programmierung ist es den Aufwand garantiert nicht Wert.

Eine viel einfachere Alternative wäre ein parallelisiertes C(++) Programm zu schreiben und zB beim Rechenzentrum auszuführen. Zumindest bei größeren Informatik-Fachbereichen kann man als Student umsonst Rechenzeit "mieten" und die schlägt jede privat gekaufte GPU um längen.
An meiner Uni hab ich gehört, dass man bis zu 48 Stunden nahezu alle Kerne bekommen kann, sofern die frei sind - und immer mal wieder 20-30 sind sowieso kein Problem. Außerdem werden manche PC-Räume nach Absprache über Nacht angelassen und schon hätte man sehr leicht >50 herkömliche Core2Duos zur Verfügung.

Bring also am besten mal ne C(++) Version zum laufen - frag uns oder wen der sich auskennt, ob da größeres Optimierungspotential drinsteckt und schätz danach erstmal, ob die Laufzeit tatsächlich "monate" beträgt auf einem normalen PC
Gerade da du von Listen etc erzählst wäre die naheliegende Frage, ob du auch hinreichend mit Zeigerarithmetik arbeitest oder evtl. die Daten in den Listen immer überflüssig duplizierst und löscht.
 
Zuletzt bearbeitet:
Aus eigener Erfahrung kann ich sagen, dass man oftmals durch Kenntnisse der Sprache und deren Optimierungsmöglichkeit die Laufzeit extrem drücken kann. Daher würde ich wirklich erst hier ansetzen, wie kuddlmuddl es schon gesagt hat ;)

Gruß,

badday
 
PC-Kurbel schrieb:
Bisher hatte ich nicht allzuviel mit Programieren zu tun. Nun soll ich aber ein Programm in C oder C++ schreiben, dass monatelang rechnet und am Ende hoffentlich was tolles herauskommt. Da sich das Problem sehr gut parallelisieren lässt, habe ich vor die GPU mit dem Problem zu beauftragen. Nun habe ich aber leider keine Einsteigerfreundliche Anleitung gefunden.

Als Programmieranfänger mit GPUs loszulegen ist nicht ohne...

PC-Kurbel schrieb:
1. Was brauche ich dafür an Programmen? Ich habe eine Ati/Amd Karte, daher habe ich Ati Stream runtergeladen und MS Visual Studio 2010 gabs von der Uni. Habe ich alles?

- CUDA: Nur für NVidia Karten, aber dafür gibts da sehr gute Tools und Dokumentation
- Ati Stream: Nur Ati, aber damit habe ich noch nicht gearbeitet

Ausserdem gibt es OpenCL und DirectX Compute. Beide sitzen quasi eine Schicht darüber und erlauben dir Code zu schreiben, der sowohl auch Ati als auch auf Nvidia läuft. Ich weiß aber nicht, ob es damit auch möglich ist Grafikkarten-spezifische Features zu nutzen. Nvidia GPUs haben beispielsweise einen SharedMemory pro Prozessor, den man je nach Aufgabenstellung gut nutzen kann.

PC-Kurbel schrieb:
2. Wie erreiche ich, dass das Programm auf der Grafikkarte läuft und nicht doch in der CPU?

Du programmierst ganz normal Code der am Host (also der CPU) läuft und ausserdem spezielle Abschnitte, die auf der GPU ausgeführt werden. Die notwendigen Daten musst du zwischen Host und GPU hin und her kopieren.

PC-Kurbel schrieb:
3. Gibt es gravierende Unterschiede zum Code für Programme für die CPU?

Jein. Es ist an und für sich C Code, aber die Art und Weise unterscheidet sich etwas. Bei CUDA nennt man die ausführbaren Teile "Kernel", diese werdem vom Host gestartet.

PC-Kurbel schrieb:
4. Kennt jemand eine gute Anleitung in das Thema?

Für CUDA: Nvidia Homepage.

PC-Kurbel schrieb:
Ich habe schon ein bischen Programiererfahrung gesammelt und eher einfache Programme geschrieben. Allerdings nicht sehr viel und es ist schon Jahre her. So rein Programmiertechnisch ist das Programm wirklich nicht anspruchsvoll, sondern einfach nur rechenintensiv. Eine lauffähige Version habe ich schon in C, allerdings kommt nicht das raus was rauskommen soll, daher steckt irgendwo der Wurm drin. Vielen Dank für die weiteren Antworten.

Versuch erst mal die normale Version richtig zu bekommen, bevor du zum optimieren beginnst.

Ob es auf der GPU dann schneller läuft, hängt von mehreren Faktoren ab. Einerseits brauchst du natürlich eine schnelle Grafikkarte, eine für 50 Euro ist mit Sicherheit langsamer als die CPU. Zumal kann man bei der CPU auch viel machen. Um mal ein paar Stichwörter in den Raum zu werfen: Compiler-Optimierung, Cache-Optimierung, Loop-Unrolling, SSE, etc...

Prinzipiell ist es nicht schwer die GPU rechnen zu lassen. Die meisten einfachen Programme holen dann aber nur 10% der Leistung der GPU raus. Die GPU voll auszulasten ist eine Wissenschaft für sich. (Meine Diplomarbeit ging ein bisschen in die Richtung :D)

Manche Aufgabenstellungen lassen sich sogar besser und schneller auf der CPU bearbeiten als auf der GPU. Für manche Sachen ist aber eine GPU auch 100x schneller als ein Quad-Core.

Wenn du schreibst, dass jede Berechnung nur für sich läuft und es keine Datenabhängigkeit gibt, deutet es aber tatsächlich darauf hin, dass sich das gut parallelisieren lässt.

Du musst zudem noch beachten, dass die GPU Leistung in erster Linie für Fließkommazahlen mit einfacher Genauigkeit stehen. Für doppelte Genauigkeit, solltest du das benötigen, sieht das schon wieder ganz anders aus, da deutlich weniger Recheneinheiten dafür auf der GPU sitzen.
 
Zuletzt bearbeitet:
Aus eigener Erfahrung kann ich sagen, dass man oftmals durch Kenntnisse der Sprache und deren Optimierungsmöglichkeit die Laufzeit extrem drücken kann.
Jo genau - ich hab zu Beginn von Java kommend in C++ alles ausversehen "by value" übergeben anstatt "by reference". Nachdem ich das behoben hab war die Version um mehr als den Faktor 100.000 schneller
 
Joar, das klingt alles so als wenn ich lieber bei der Klassischen Variante bleibe. Ich denke mal, dass mein C(++) Code ganz ok, aber natürlich nicht perfekt ist, da ich nur diese Programmiersprache gelernt habe und nicht durch andere "verdorben" bin. Mit Zeigern kenne ich wohl mich auch genug für meine Zwecke aus. Was evtl. nicht so toll sein wird, ist, dass ich nicht genau weiß welche Rechenoperationen wieviel Taktzyklen brauchen. Ausserdem kann es ja auch noch Optimierungen geben von denen ich gar nichts weiß. Wenn ich ein lauffähiges Programm habe kann ich das ja mal posten und dann schauen wir mal.

Nochmals vielen Dank an alle. Ihr seid ne super Hilfe.

PC-Kurbel
 
Also um dir mal ein paar Zahlen zu nennen. Ich habe mal einen recht komplexen Algorithmus auf die GPU portiert (mittels CUDA). Die CPU Implementierung war hochoptimiert (OpenMP, Intel Performance Primitives, Intel Compiler, viel händischer SSE Code). Die optimierte Version war auch 20x so schnell wie der unoptimierte Prototyp.

Im direkten Vergleich Intel Core2Duo vs NVidia GeForce GTX 280, war der Algorithmus auf der GPU ca 10x so schnell. Allerdings musste man alles von Grund auf neu schreiben, da sich die CPU Algorithmen so nicht oder nicht performant auf der GPU einsetzen lassen. Einige Teilschritte des Algorithmus waren nur rund 3x so schnell, dafür gabs auch Teile die 85x schneller waren. Es kommt immer darauf an, was zu der Algorithmus zu tun hat. Code-Branches (Ifs oder Schleifen mit unterschiedlichen Conditions) sind z.B. immer schlecht auf der GPU.
 
Wenn es wirklich so gut parallelisierbar ist, würde sich auch das Buzzword "Cloud Computing" anbieten. Die Aufgabe auf mehrere Rechner verteilen und dann zusammenführen.
 
Also wenn du eine schnelle Grafikkarte hast, dann hört sich alles so an, als ob das recht performant laufen könnte.

Falls du bei dir an der Uni Zugriff auf mehrere Rechner hast (Cluster), dann kannst du das Rechnen ggf. auch darauf verteilen. Dazu müsstest du dich aber etwas in MPI (Message Passing Interface) einarbeiten. Wenn deine Uni einen Cluster betreibt, steht MPI mit Sicherheit dort zur Verfügung.

Im Grunde werden die Cluster ja genau dafür gebaut um numerische Probleme mit vielen Daten parallel zu berechnen. Falls zu zufällig in Aachen, Stuttgart oder München bist, steht eurer Uni ohnehin einer der "Bundeshöchstleistungsrechner" zur Verfügung.
 
Zurück
Oben