it-swarm.com.de

Wäre es bei der Softwareprogrammierung möglich, die CPU- und GPU-Auslastung zu 100% zu erreichen?

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, habe ich verstanden, dass sowohl die CPU als auch die GPU Daten berechnen, aber dass eine aufgrund der unterschiedlichen Architektur in einigen Berechnungen besser ist als die andere. Zum Beispiel scheint das Knacken von Hashes oder das Cryptocurrency Mining auf GPUs weitaus effizienter zu sein als auf CPUs.

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

Oder genauer: Können einige Berechnungen, die normalerweise von der GPU durchgeführt werden, von der CPU durchgeführt werden, wenn die erste zu 100% ausgelastet ist, sodass beide eine Last 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!

43
MadWard

Theoretisch ja, aber praktisch lohnt es sich selten.

Sowohl CPUs als auch GPUs sind turing-complete , 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 für viele Datenpunkte eines großen Datensatzes ausfü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 Verwendung von einem, um dem anderen die Arbeit abzunehmen, wenn es zum Stillstand kommt, nicht wirklich zu einer nennenswerten Leistungssteigerung führen würde.

Der Preis, den Sie dafür zahlen müssen, ist jedoch, 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 Fehler von diesem Stunt.

62
Philipp

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

Bei sorgfältiger und schmerzhafter Programmierung, z. Mit OpenCL oder CUDA können Sie sowohl Ihre GPU als auch Ihre CPU zu nahezu 100% laden. Sehr wahrscheinlich müssen Sie verschiedene Codeteile für die GPU (sogenannter "Kernel" -Code) und für die CPU sowie etwas langweiligen Klebercode schreiben (insbesondere, um den kompilierten Kernel-Code an die GPU zu senden).

Der Code wäre jedoch komplex, und Sie müssen ihn wahrscheinlich auf die jeweilige 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 (z. B. GCC 6 im Juni 2016)

36

Unter dem Gesichtspunkt des Supercomputers ist es besser, nicht in Prozent an der 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 erhalten, bedeutet dies nicht unbedingt, dass Sie die gesamte Leistung aus dem System herausholen. CPUs können oft mehrere verschiedene Dinge gleichzeitig ausführen, z. B. eine Division und eine Addition. Wenn Sie die Division frühzeitig starten können, kann sie sich möglicherweise mit der Addition überschneiden. Ihre Desktop-CPU verfügt höchstwahrscheinlich über eine nicht in Ordnung befindliche Einheit , die die Anweisungen neu anordnet, um von solchen Überlappungen zu profitieren. Oder wenn Sie folgendes Programm haben:

if (expr1)
    expr2;
else
    expr3;

Eine neu geordnete CPU versucht, die drei Ausdrücke gleichzeitig zu berechnen und wirft dann das Ergebnis eines davon weg. Dies macht es insgesamt schneller. Wenn Sie einen Blocker in Ihrem Programm haben und nicht neu anordnen können, verwenden Sie weniger Lanes in der CPU, aber es wird wahrscheinlich immer noch 100% angezeigt.

Dann haben Sie SIMD-Funktionen in den CPUs, die Vektoroperationen sind. Es ist wie bei GPGPU-light in dem Sinne, dass Sie normalerweise nur vier oder acht Operationen gleichzeitig ausführen, GPUs wie 32 oder 64. Sie müssen dies jedoch verwenden, um die FLOPS herauszukurbeln.

Dinge wie falsches Teilen können zu hohen Synchronisationskosten führen, die normalerweise unter Linux als Kernel-Last angezeigt werden. Die CPU ist vollständig ausgelastet, aber Sie haben nicht viel nützlichen Durchsatz.

Ich habe einige Programmierungen auf einer IBM Blue Gene/Q-Maschine durchgeführt. Es hat viele Hierarchieebenen ( Schema von veraltetem Blue Gene/L ) und ist daher schwer effizient zu programmieren. Sie müssen die vollständige Hierarchie bis auf SIMD und SMT (Intel nennt dies HyperThreading) verwenden, um die Leistung zu verbessern.

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 wird schneller ausgeführt. Der tatsächliche Programmdurchsatz ist jedoch nicht so gut, wie es aus den Rohzahlen hervorgeht.

Wenn Sie dem Mix GPUs hinzufügen, wird es noch schwieriger, diese ganze Sache 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.

11
Martin Ueding

Vielleicht möchten Sie die Servo Browser-Engine ausprobieren, die bei Mozilla Research entwickelt wird, und insbesondere deren () Web Render (Video) .

Während das dynamische Verschieben einer Aufgabe von der CPU zur GPU unpraktisch sein kann, wie in anderen Antworten erwähnt (insbesondere bei @ Philip's), kann es praktisch sein, die Belastung der CPU/GPU bei typischen Workloads im Voraus zu untersuchen und zu wechseln einige Aufgaben an die allgemein weniger belastete.

Im Fall von Web Render besteht die Neuheit darin, dass Browser traditionell den größten Teil ihrer Rendering-Arbeit auf der CPU ausführen (dh die CPU wird verwendet, um zu berechnen, welche Objekte angezeigt werden sollen, wo geschnitten werden soll usw.). Die GPU ist normalerweise besser darin ... außer dass nicht alle Anwendungsfälle trivial zu implementieren sind (partielles Culling, Schatten, ... und Text).

Eine erste Version von Web Render erwies sich als äußerst erfolgreich bei der Leistungssteigerung, 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 Renderprozess 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 in die Richtung, eine Berechnungsstrategie zu entwerfen, die sowohl sowohl CPU als auch GPU berücksichtigt.

1
Matthieu M.

Mit einem Fokus auf Spiele (da Sie es speziell in Ihrem Beitrag erwähnt haben) gibt es einige Möglichkeiten, wie Sie die Last ausgleichen können. Ein Beispiel ist das "Enthäuten", d. H. Das Animieren eines Modells. Für jedes zu rendernde Bild müssen Sie die Transformationsmatrizen für jedes Bild der Animation generieren und auf die Eckpunkte 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 durchführen. Ich glaube, heutzutage wird dies auf der GPU (bekannt als "Hardware-Skinning") durchgeführt: Dies ist sinnvoll, da Sie relativ einfache Berechnungen haben, die tausendfach durchgeführt werden müssen, und jeder Scheitelpunkt kann seit dem Ergebnis gleichzeitig berechnet werden von Scheitelpunkt A hat keinen Einfluss auf das Ergebnis von Scheitelpunkt B.

Theoretisch können Sie jedoch dynamisch zwischen CPU und GPU wechseln, je nachdem, wie überlastet GPU und CPU sind.

Der Hauptblocker bei allen Berechnungen ist jedoch, dass CPU und GPU unterschiedliche Stärken und Schwächen aufweisen. Massiv parallele Jobs werden besser auf der GPU ausgeführt, während intensive lineare Aufgaben mit Verzweigung besser auf der CPU ausgeführt werden. Nur wenige Arbeiten konnten realistisch an beiden ohne ernsthaften Leistungseinbruch ausgeführt werden.

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 innerhalb eines Shaders ist riskant, da die GPU, wenn Sie versehentlich eine Abhängigkeit zwischen Berechnungen erstellen, möglicherweise beschließt, Ihre Pixel einzeln zu rendern und sofort 60 fps bis 10 fps zu drehen, 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 erleichtern, obwohl auch Builds ohne OpenCL existieren.

Dies ist praktisch, da die von LuxRender verwendeten Algorithmen stark parallelisierbar sind. Der gebräuchlichste Algorithmus, den LuxRender verwendet, ist Pfadverfolgung , bei dem viele einzelne Lichtpfade unabhängig voneinander berechnet werden können - eine ideale Situation für GPU-Computing und eine, die keine komplexe Synchronisation zwischen Rechenknoten erfordert. Einschränkungen der GPUs (geringere Speichermengen, mangelnde Unterstützung für einige komplexe Rendering-Funktionen und allgemeine mangelnde Verfügbarkeit für einige Künstler) stellen jedoch sicher, dass die CPU-Unterstützung weiterhin unerlässlich ist.

0
PythonNut

Ja, das ist sicherlich möglich.

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

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; der andere SIMD. Was auf dem einen 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 insgesamt viel leistungsfähiger als CPUs. Die ganze Idee von GPUs besteht darin, billigere, langsamere, aber zahlreichere Prozessoren zu verwenden, um Berechnungen weitaus schneller durchzuführen, als dies CPUs bei gleichen Kosten könnten. GPUs sind in Bezug auf die Kosten um ein oder zwei Größenordnungen effizienter.

Wenn Sie Ihren Algorithmus auf GPUs ausführen lassen, ist es nur sinnvoller, diese zu optimieren und so viele hinzuzufügen, wie Sie benötigen.

0
Paul Draper