Wäre es bei der Softwareprogrammierung möglich, sowohl die CPU als auch die GPU zu 100% auszulasten?


43

Dies ist eine allgemeine Frage zu einem Thema, das ich als Spieler interessant fand: CPU / GPU-Engpässe und Programmierung. Wenn ich mich nicht irre, verstehe ich, dass sowohl die CPU als auch die GPU Berechnungen durchführen, aber aufgrund der unterschiedlichen Architektur bei einigen Berechnungen die eine besser ist als die andere. Das Knacken von Hashes oder Cryptocurrency Mining scheint auf GPUs effizienter zu sein als auf CPUs.

Ich habe mich also gefragt: Ist es unvermeidlich, dass eine GPU zu 100% ausgelastet ist, während die CPU zu 50% ausgelastet ist (zum Beispiel)?

Genauer gesagt: Können einige Berechnungen, die normalerweise von der GPU ausgeführt werden, von der CPU ausgeführt werden, wenn die erste zu 100% ausgelastet ist, sodass beide eine Auslastung von 100% erreichen?

Ich habe ein bisschen nach dem Thema gesucht, bin aber mit leeren Händen zurückgekommen. Ich denke und hoffe, dass dies seinen Platz in diesem Unterabschnitt hat und bin offen für jede Dokumentation oder Vorlesung, die Sie mir geben könnten!


53
Es ist trivialerweise möglich, dass sowohl CPU als auch GPU gleichzeitig eine Endlosschleife von NO-OPs ausführen , was zu einer Auslastung von 100% führt.
Jörg W Mittag

17
Gemessen an @Jörgs Punkt ist das einzige, was an CPU% gemessen wird, welcher Teil der Zeit nicht für das Warten auf andere Prozessoren aufgewendet wird. 100% können eine gute Sache sein, wenn das Programm effizient ist, oder eine schlechte Sache, wenn das Programm ineffizient ist. Zu oft konzentrieren sich die Leute auf den Prozentsatz der CPU, als wäre dies ein Maß für die Leistung - das ist es nicht.
Mike Dunlavey

22
Die ursprüngliche Crysis hat das in Ordnung gebracht.
CubicleSoft

5
@ MikeDunlavey Sie bringen einen guten Punkt. Bei Autos messen wir ihre Leistung nicht an der Drehzahl, sondern an der Geschwindigkeit.
Captain Man

1
@ JörgWMittag: Die CPU vielleicht. Aber Betriebssysteme und GPUs haben halt Problemlöser, um mit Endlosschleifen umzugehen. Wenn ein Shader nicht in angemessener Zeit fertiggestellt wird, stirbt er und die GPU wird zurückgesetzt.
Nicol Bolas

Antworten:


62

Theoretisch ja, aber praktisch lohnt es sich selten.

Sowohl die CPUs als auch die GPUs sind vollständig , sodass jeder Algorithmus, der von einem berechnet werden kann, auch von dem anderen berechnet werden kann. Die Frage ist, wie schnell und wie bequem.

Während die GPU die gleichen einfachen Berechnungen an vielen Datenpunkten eines großen Datensatzes durchführt, ist die CPU bei komplexeren Algorithmen mit vielen Verzweigungen besser. Bei den meisten Problemen ist der Leistungsunterschied zwischen CPU- und GPU-Implementierungen sehr groß. Das bedeutet, dass die Arbeit des einen beim Stillstand nicht wirklich zu einer merklichen Leistungssteigerung führen würde.

Der Preis, den Sie dafür zahlen müssen, ist, dass Sie alles zweimal programmieren müssen, einmal für die CPU und einmal für die GPU. Das ist mehr als doppelt so viel Arbeit, da Sie auch die Schalt- und Synchronisationslogik implementieren müssen. Diese Logik ist äußerst schwierig zu testen, da ihr Verhalten von der aktuellen Last abhängt. Erwarten Sie sehr dunkle und unmöglich zu reproduzierende Bugs von diesem Stunt.


1
Sie haben erwähnt, dass bei den meisten Problemen der Leistungsunterschied zwischen CPU- und GPU-Implementierungen sehr groß ist. Eigentlich interessiert mich sehr, inwieweit sich die Leistungslücke verringert. Hätten Sie Zahlen oder Artikel dazu (zum Beispiel zum Beispiel Textur-3D-Rendering)? Vielen Dank für Ihre Antwort und für Ihre Zeit!
MadWard

2
Möglicherweise möchten Sie hinzufügen, dass für die Synchronisierung zwischen der CPU und der GPU Leistungskosten anfallen. Daher möchten Sie im Allgemeinen die Anzahl der Übertragungen zwischen den beiden minimieren. Auch das naive Hinzufügen von Zweigen für "Nicht auf den Elementen ausführen, an denen die CPU bereits gearbeitet hat" würde Ihnen nichts bringen, da die GPU-Threads im Gleichschritt arbeiten.
Ethan

3
@gardenhead Nichts im Universum unterstützt eine unbegrenzte Rekursion, da das Universum eine endliche Größe und eine endliche Informationsdichte hat. "Turing-Vollständigkeit" eines Systems ist im Allgemeinen eine Diskussion darüber, was möglich wäre, wenn solche Einschränkungen beseitigt würden.
Random832

3
Ich habe kaum Zweifel, dass eine moderne GPU technisch mindestens so vollständig ist wie ein 80er-PC. Wenn Sie jedoch versuchen, allgemeine Algorithmen auf einer GPU auszuführen, wird sie in der Regel zu einem sequentiellen Prozessor, der es auch nicht sein wird Schneller als ein 80er-PC, daher ist die Turing-Vollständigkeit einer GPU in der Praxis kaum nützlicher als die Turing-Vollständigkeit von Brainfuck .
Leftaroundabout

7
@leftaroundabout Moderne GPUs sind wie jede CPU trivial vollständig . Die Vollständigkeit der Prüfung hat nichts zu tun mit: 1) Leistung 2) Lesbarkeit der Quelle. 80er CPU waren so nah an TC hat alles andere: entweder waren sie TC oder waren sie nicht (die letztere Option ist Unsinn).
Margaret Bloom

36

Es hat nichts mit Spielprogrammierung zu tun. Einige wissenschaftliche Codes können auch sowohl die GPU als auch die CPU verwenden.

Mit sorgfältiger und mühsamer Programmierung, z. B. mit OpenCL oder CUDA , könnten Sie sowohl Ihre GPU als auch Ihre CPU nahezu zu 100% auslasten. Sehr wahrscheinlich müssen Sie verschiedene Codeteile für die GPU (sogenannter "Kernel" -Code) und für die CPU sowie etwas langweiligen Klebstoffcode (insbesondere, um den kompilierten Kernel-Code in die GPU zu senden) schreiben.

Der Code wäre jedoch komplex, und Sie müssen ihn wahrscheinlich auf die bestimmte Hardware abstimmen, auf der Sie ausgeführt werden, insbesondere weil die Datenübertragung zwischen GPU und CPU kostspielig ist.

Lesen Sie mehr über heterogenes Computing .

Siehe auch OpenACC , unterstützt von neueren Versionen von GCC (zB GCC 6 im Juni 2016)


1
Du hast Recht, meine Tags und Titel waren irreführend, entfernte Spiele und fügten Leistung / Optimierung hinzu. Ich meinte nicht, dass es exklusiv für Spiele ist, aber das ist mir aufgefallen. Ich dachte, es müsste auch sehr hardwarespezifisch sein. Vielen Dank für Ihre Antwort und Links!
MadWard

3
Dies würde so ziemlich zu zwei Algorithmen führen. Ich habe es einmal versucht: ein ganzes Bild auf einmal für die GPU und mehrere Bilder auf einmal für die CPU (um einen großen Cache zu missbrauchen). Es ist in der Tat schmerzhaft, besonders zu pflegen.
PTwr

11

Aus Sicht des Supercomputers ist es besser, nicht an die prozentuale CPU- / GPU-Auslastung zu denken, sondern zu bestimmen, wie viele Vorgänge Ihr Problem benötigt, und diese dann mit der Spitzenleistung des Systems zu vergleichen.

Wenn Sie eine 100% ige CPU-Auslastung erzielen, bedeutet dies nicht unbedingt, dass Sie die gesamte Leistung aus dem System herausholen. CPUs können oft mehrere verschiedene Dinge gleichzeitig erledigen, z. B. eine Unterteilung und eine Hinzufügung. Wenn Sie die Aufteilung frühzeitig beginnen können, kann sie sich möglicherweise mit dem Zusatz überschneiden. Ihre Desktop-CPU hat höchstwahrscheinlich eine Einheit für nicht ordnungsgemäße Ausführung , die die Anweisungen neu anordnet, um von solchen Überschneidungen zu profitieren. Oder wenn Sie folgendes Programm haben:

if (expr1)
    expr2;
else
    expr3;

Eine umordnende CPU wird versuchen, die drei Ausdrücke gleichzeitig zu berechnen und dann das Ergebnis eines von ihnen wegzuwerfen. Dies macht es insgesamt schneller. Wenn Sie einen Blocker in Ihrem Programm haben und die Reihenfolge nicht ändern können, verwenden Sie weniger Spuren in der CPU, aber es werden wahrscheinlich immer noch 100% angezeigt.

Dann haben Sie SIMD-Funktionen in den CPUs, die Vektoroperationen sind. Es ist wie GPGPU-light in dem Sinne, dass Sie normalerweise nur vier oder acht Operationen gleichzeitig haben, GPUs wie 32 oder 64. Dennoch müssen Sie das verwenden, um die FLOPS auszulösen.

Sachen wie falsches Teilen können so zu hohen Synchronisationskosten führen, die sich normalerweise als Kernellast unter Linux zeigen. Die CPU ist voll ausgelastet, aber Sie haben nicht viel nützlichen Durchsatz.

Ich habe auf einer IBM Blue Gene / Q-Maschine etwas programmiert. Es hat viele Hierarchieebenen ( Schema von veraltetem Blue Gene / L ) und ist daher schwer effizient zu programmieren. Sie müssen die gesamte Hierarchie bis hinunter zu SIMD und SMT (Intel nennt dies HyperThreading) verwenden, um die Leistung zu optimieren.

Und dann schränkt Sie das Netzwerk oft ein. Daher stellt sich heraus, dass es in der (Wanduhr-) Zeit schneller ist, Dinge auf mehreren CPUs gleichzeitig zu berechnen, anstatt sie über das Netzwerk zu kommunizieren. Dadurch werden die CPUs stärker belastet und das Programm schneller ausgeführt. Der tatsächliche Programmdurchsatz ist jedoch nicht so gut, wie es aus den Rohdaten hervorgeht.

Wenn Sie dem Mix GPUs hinzufügen, wird es noch schwieriger, das Ganze zu orchestrieren, um Leistung zu erzielen. Das wird eines der Dinge sein, die ich in ein paar Monaten in meiner Lattice QCD Master Thesis anfangen werde.


1

Vielleicht möchten Sie sich die Servo- Browser-Engine ansehen , die von Mozilla Research entwickelt wird, und insbesondere das Web-Rendering (Video) .

Während das dynamische Verschieben einer Aufgabe von der CPU zur GPU unpraktisch sein kann, wie in anderen Antworten (insbesondere bei Philip's) erwähnt, kann es sinnvoll sein, die CPU- / GPU-Last bei typischen Arbeitslasten im Voraus zu untersuchen und einige Aufgaben auf die im Allgemeinen weniger belasteten zu verschieben einer.

Im Fall von Web Render besteht die Neuheit darin, dass Browser traditionell den größten Teil ihrer Renderarbeit auf der CPU erledigen (dh die CPU wird verwendet, um zu berechnen, welche Objekte angezeigt werden sollen, wo sie geschnitten werden sollen usw.). Die GPU ist normalerweise besser darin ... mit der Ausnahme, dass nicht alle Verwendungszwecke einfach zu implementieren sind (partielles Ausmerzen, Schatten, ... und Text).

Eine erste Version von Web Render erwies sich bei der Leistungssteigerung als äußerst erfolgreich, versuchte jedoch nicht, das Problem der Textwiedergabe zu lösen (und hatte einige andere Einschränkungen). Mozilla Research arbeitet derzeit an einer zweiten Version, die weniger Einschränkungen aufweisen und insbesondere das Rendern von Text unterstützen soll.

Das Ziel ist natürlich, den Rendering-Prozess so weit wie möglich auf die GPU zu verlagern, damit die CPU Javascript ausführen, das DOM aktualisieren und alle anderen Aufgaben ausführen kann.

Obwohl es nicht so extrem ist wie Ihr Vorschlag, geht es darum, eine Berechnungsstrategie zu entwerfen, die sowohl die CPU als auch die GPU berücksichtigt.


0

Wenn Sie sich auf Spiele konzentrieren (da Sie dies in Ihrem Beitrag ausdrücklich erwähnt haben), haben Sie einige Möglichkeiten, die Last auszugleichen. Ein Beispiel ist "skinning", dh ein Modell animieren. Für jedes Bild, das gerendert werden soll, müssen Sie die Transformationsmatrizen für jedes Bild der Animation generieren und auf die Scheitelpunkte des Modells anwenden, um es in die Pose zu transformieren, in der es sich befinden muss. Sie müssen auch Bilder interpolieren, um eine reibungslose Bewegung zu erzielen , es sei denn, Sie möchten, dass Ihre Animation wie das ursprüngliche Beben aussieht (dh ruckelt).

In dieser Situation können Sie dies entweder auf der CPU tun und die Ergebnisse zum Rendern auf die GPU hochladen oder die Berechnung und das Rendern auf der GPU ausführen. Ich glaube, dass es heutzutage auf der GPU gemacht wird (bekannt als "Hardware-Skinning"): Es ist sinnvoll, dies zu tun, da Sie relativ einfache Berechnungen haben, die tausende Male durchgeführt werden müssen und jeder Eckpunkt seit dem Ergebnis gleichzeitig berechnet werden kann von Vertex A hat keinen Einfluss auf das Ergebnis von Vertex B.

Theoretisch könnte man jedoch dynamisch zwischen CPU und GPU wechseln, je nachdem, wie überlastet die GPU und die CPU sind.

Das Hauptproblem bei allen Berechnungen ist jedoch, dass CPU und GPU unterschiedliche Stärken und Schwächen aufweisen. Massiv parallele Jobs werden auf der GPU besser erledigt, während intensive lineare Tasks mit Verzweigung besser auf der CPU erledigt werden. Nur ein paar Jobs konnten realistisch auf beiden ausgeführt werden, ohne dass die Leistung ernsthaft beeinträchtigt wurde.

Insgesamt besteht das Hauptproblem bei der GPU-Programmierung (zumindest bei OpenGL und DirectX 11 und darunter) darin, dass Sie nur wenig Kontrolle darüber haben, wie die GPU Ihren Shader-Code interpretiert. Das Verzweigen in einem Shader ist riskant, da die GPU möglicherweise aus Versehen eine Abhängigkeit zwischen den Berechnungen herstellt und die Pixel einzeln rendert. Dabei werden 60 fps bis 10 fps im Nu gedreht, obwohl die tatsächlich zu rendernden Daten identisch sind.


0

Ein Beispiel aus der Praxis ist die Open Source LuxRender- Rendering-Engine, mit der eine CPU und eine GPU gleichzeitig vollständig geladen werden können. Darüber hinaus können mehrere GPUs gleichzeitig geladen und auf mehrere Computer verteilt werden.

LuxRender verwendet OpenCL , um dies zu vereinfachen, obwohl auch Builds ohne OpenCL existieren.

Dies ist praktisch, da die von LuxRender verwendeten Algorithmen in hohem Maße parallelisierbar sind. Der gebräuchlichste Algorithmus, den LuxRender verwendet, ist die Pfadverfolgung , bei der viele einzelne Lichtpfade unabhängig voneinander berechnet werden können - eine ideale Situation für GPU-Computing, die keine komplexe Synchronisation zwischen Rechenknoten erfordert. Einschränkungen der GPUs (geringere Speicherkapazität, mangelnde Unterstützung für einige komplexe Rendering-Funktionen und allgemeiner Mangel an Verfügbarkeit für einige Interpreten) stellen jedoch sicher, dass die CPU-Unterstützung weiterhin von wesentlicher Bedeutung ist.


Wozu dient dieses Bild, wie ist es für die gestellte Frage relevant?
gnat

1
Ehh gut. Ich werde es löschen. Ich dachte, es würde leicht zeigen, was für eine Software es ist. Aber vielleicht ist es nur sehr ablenkend. (Es gibt viele verschiedene Arten von Rendering-Engines; dieses ist auf fotorealistische Standbilder ausgerichtet.)
PythonNut

0

Ja, das ist durchaus möglich.

Jede Berechnung, die eine CPU, eine GPU und umgekehrt ausführen kann.

Aber es ist ungewöhnlich, weil:

  • Technische Komplexität Während es möglich ist, denselben Code auf einer CPU und einer GPU (z. B. CUDA) auszuführen, weisen die Prozessoren unterschiedliche Fähigkeiten und Leistungsmerkmale auf. Einer ist MIMD; die andere, SIMD. Was auf einem schnell ist, ist auf dem anderen langsam (z. B. Verzweigung), sodass Sie separaten Code schreiben müssen, um die Leistung zu maximieren.

  • Kosteneffizienz GPUs sind in Summe viel mächtiger als CPUs. Die ganze Idee von GPUs besteht darin, billigere, langsamere, aber zahlreichere Prozessoren zu verwenden, um Berechnungen viel schneller durchzuführen, als dies bei CPUs zu den gleichen Kosten möglich wäre. GPUs sind in Bezug auf die Kosten um ein oder zwei Größenordnungen effizienter.

Wenn Ihr Algorithmus auf GPUs ausgeführt werden soll, ist es nur sinnvoller, diese zu optimieren und so viele hinzuzufügen, wie Sie benötigen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.