Programme, die behaupten, sie seien nicht "Multi-Core" -freundlich

17

Sie sehen diesen oder einen ähnlichen Satz, der sich von Zeit zu Zeit herumwirbelt und sich im Allgemeinen auf ein Programm bezieht, das behauptet, es sei nicht dafür ausgelegt, die Vorteile von Multi-Core-Prozessoren voll auszuschöpfen. Dies ist insbesondere bei der Programmierung von Videospielen üblich. (Natürlich haben viele Programme keine Nebenläufigkeit und benötigen diese nicht, wie z. B. einfache Skripte usw.).

Wie kann das sein? Viele Programme (insbesondere Spiele) verwenden inhärent Parallelität, und da das Betriebssystem für die Aufgabenplanung auf der CPU verantwortlich ist, nutzen diese Programme dann nicht inhärent die verfügbaren mehreren Kerne aus? Was würde es in diesem Zusammenhang bedeuten, "mehrere Kerne auszunutzen"? Verbieten diese Entwickler tatsächlich das Planen von Betriebssystemaufgaben und das Erzwingen von Affinität oder ihre eigene Planung? (Klingt nach einem großen Stabilitätsproblem).

Ich bin ein Java-Programmierer, also musste ich mich vielleicht nicht wegen Abstraktionen oder so weiter damit auseinandersetzen.

SnakeDoc
quelle
11
Eine große Möglichkeit besteht darin, dass bei der Synchronisierung Verknüpfungen verwendet wurden, die für ein Einzelprozessor- / Kernsystem funktionieren, jedoch mit der tatsächlichen Gleichzeitigkeit mehrerer Prozessoren / Kerne brechen.
Bart van Ingen Schenau
@BartvanIngenSchenau: Das ist richtig. Sie sollten dies erweitern und als Antwort posten. Ich denke, alle anderen haben den Punkt verfehlt.
Kevin Cline
1
Ich denke, dass @Bart wirklich nah ist. Allerdings scheint s / work / zu funktionieren / und es wird näher an der Marke sein.
Ben Voigt
Nebenbei bemerkt - ich habe Erfahrung als Benutzer und nicht als Programmierer - Ground Control 2 unter Windows XP. Ich musste die Kernaffinität auf nur einen Kern auf einem Multicore-System festlegen, damit es ordnungsgemäß ausgeführt werden konnte. Andernfalls liefen alle Animationen (die das gesamte Spiel betrafen) mit 10-facher Geschwindigkeit, was, obwohl es sich eher um eine Herausforderung handelte, nach einer Weile etwas ärgerlich wurde . Ich habe keine Arbeit an Spielen gemacht, aber meiner Meinung nach schien ein Teil des Spiels darauf zu beruhen, dass der Prozessor nur eine bestimmte Menge an Arbeit gleichzeitig erledigt.
Jamypeach

Antworten:

28

Für eine gute Parallelität ist viel mehr erforderlich, als ein paar Threads in eine Anwendung zu werfen und auf das Beste zu hoffen. Es gibt eine Reihe von Möglichkeiten, wie gleichzeitig ein Programm von peinlich parallel zu rein sequentiell ablaufen kann. Jedes Programm kann das Amdahlsche Gesetz verwenden, um auszudrücken, wie skalierbar ein Problem oder ein Algorithmus ist. Ein paar Voraussetzungen für eine peinlich parallele Bewerbung wären:

  • Kein gemeinsamer Status, jede Funktion hängt nur von den übergebenen Parametern ab
  • Kein Zugriff auf physische Geräte (Grafikkarten, Festplatten usw.)

Es gibt noch andere Qualifikationen, aber nur mit diesen beiden können wir verstehen, warum gerade Spiele nicht so einfach sind, wie Sie vielleicht denken, um die Vorteile mehrerer Kerne zu nutzen. Zum einen muss das Modell der Welt, das gerendert werden soll, geteilt werden, da verschiedene Funktionen Physik, Bewegung, künstliche Intelligenz usw. berechnen. Zum anderen muss jedes Bild dieses Spielmodells mit einer Grafikkarte auf dem Bildschirm gerendert werden.

Um fair zu sein, verwenden viele Spielehersteller Spiele-Engines, die von Dritten hergestellt werden. Es hat eine Weile gedauert, aber diese Spiele-Engines von Drittanbietern sind jetzt viel paralleler als früher.

Der Umgang mit effektiver Parallelität stellt größere architektonische Herausforderungen

Parallelität kann viele Formen annehmen, von der Ausführung von Aufgaben im Hintergrund bis zur vollständigen Unterstützung der Parallelität durch die Architektur. Einige Sprachen bieten Ihnen sehr leistungsstarke Funktionen für den gemeinsamen Zugriff , z. B. ERLANG . Sie müssen jedoch ganz anders darüber nachdenken, wie Sie Ihre Anwendung erstellen.

Nicht jedes Programm benötigt die Komplexität einer vollständigen Multicore-Unterstützung. Ein Beispiel hierfür ist Steuersoftware oder eine beliebige formulargesteuerte Anwendung. Wenn Sie den größten Teil Ihrer Zeit damit verbringen, auf den Benutzer zu warten, um etwas zu tun, ist die Komplexität von Multithread-Anwendungen einfach nicht so nützlich.

Einige Anwendungen eignen sich für eine peinlichere parallele Lösung, z. B. Webanwendungen. In diesem Fall beginnt die Plattform peinlich parallel und es liegt an Ihnen, keine Thread-Konflikte zu erzwingen.

Die Quintessenz:

Nicht alle Anwendungen sind wirklich betroffen, wenn nicht mehrere Threads (und damit Kerne) ausgenutzt werden. Für diejenigen, die dadurch verletzt werden, sind die Berechnungen manchmal nicht für eine parallele Verarbeitung geeignet, oder der Aufwand für die Koordinierung würde die Anwendung anfälliger machen. Leider ist die parallele Verarbeitung immer noch nicht so einfach, wie es gut sein sollte.

Berin Loritsch
quelle
Dies ist eine großartige Analyse. Eine Sache, die mich jedoch stört, ist Ihre Ansicht, dass reale Programme oft nicht peinlich parallel sind und sich daher nur schwer parallelisieren lassen: Es ist zwar unmöglich, dasselbe parallel zu tun , aber es ist sehr einfach, verschiedene Dinge parallel zu tun ( zB in einer Pipeline-Architektur oder mit einem separaten UI-Thread).
amon
8
Der eigentliche Punkt ist, dass Sie für die parallele Ausführung entwerfen müssen, und wenn Sie dies nicht tun, sind Sie durch den Mangel an Design eingeschränkt. Ich bin damit einverstanden , dass es kann sehr einfach sein , verschiedene Dinge gleichzeitig zu tun, aber nicht , wenn es sich um eine bestehende Anwendung mit hohen Erwartungen der Nutzer ist. In diesem Fall ist möglicherweise ein erneutes Schreiben erforderlich, um dies zu ermöglichen. Rewrites sind von Natur aus riskant, aber gelegentlich können Sie ein gutes Argument dafür vorbringen. Ich habe einige solcher Umschreibungen durchgeführt, die die parallele Verarbeitung maximierten und dabei so viel Code wie möglich behielten. Es gibt viele versteckte Faktoren.
Berin Loritsch
Gute Antwort. Es sollte betont werden, dass die Parallelisierung einiger Systeme nicht nur zu geringeren Erträgen führen kann, sondern dass einige Systeme aufgrund des für die Parallelisierung erforderlichen Overheads sogar langsamer werden. Insbesondere viele Semaphoren / Sperren und Kontextwechsel können sich nachteilig auf die Laufzeit auswirken. Insbesondere das Wechseln des Kontexts kann die Effektivität des Caches beeinträchtigen. Dies ist kein triviales Problem, wenn Sie im Begriff sind, Ihr System zu optimieren. Insbesondere das Beispiel von OP für Game-Engines lässt mich daran erinnern, dass viel mehr über die Optimierung des Cachings als über den parallelen Zugriff gesprochen wurde.
Gankro
35

Viele Programme (insbesondere Spiele) verwenden von Natur aus Parallelität.

Nein, eigentlich ist es umgekehrt. Die meisten Apps sind in einer einzigen Thread-Denkweise geschrieben, und die Entwickler haben nie die notwendigen Änderungen vorgenommen, um Parallelität zu unterstützen.

In C, C ++ und C # müssen Sie die Anwendung explizit anweisen, neue Threads und / oder Prozesse zu starten.

Ich denke, Sie konzentrieren sich zu sehr auf die Planung der Threads und nicht genug auf die Datenverarbeitung innerhalb der potenziellen Threads. Das Teilen von Daten über Threads und / oder Prozesse hinweg erfordert eine gewisse Form der Synchronisation. Wenn Sie eine Anwendung so ändern, dass mehrere Threads verwendet werden, diese Synchronisierung jedoch nicht vorhanden ist, werden Sie wahrscheinlich viele schwer auffindbare Fehler im Code feststellen.

Bei den Multithread-Anwendungen, an denen ich gearbeitet habe, habe ich mich im Allgemeinen nie um den Versand und nur um die Datensynchronisierung gekümmert. Die einzige Zeit, in der ich mir Sorgen um den Versand machen musste, war, als ich wegen falscher Datensynchronisation den Rennbedingungen nachjagte.

Wenn eine Anwendung angibt, dass sie nicht mehrere Kerne verwenden kann, bedeutet dies im Allgemeinen, dass keine Synchronisierung vorhanden ist, um die Datenmanipulation zu schützen.


quelle
Dies gilt auch für neue moderne Programme von großen Entwicklern / Verlegern? Wenn ich mich hinsetze und ein Programm schreibe, ist eines der ersten Dinge in der Entwurfsphase, über die ich nachdenke, dass ich Parallelität benötige. Weil es zu einem drastisch anderen Design kommen kann. Insbesondere Spiele müssen eine gewisse Nebenläufigkeit aufweisen, sonst würde das Spiel einfrieren, wenn eines der tausend On-Screen-Modelle versucht, etwas zu tun ...?
SnakeDoc
5
@ SnakeDoc - Ich denke, Sie verwirren Ihre Domains dort. Big Game-Unternehmen schreiben mit Sicherheit im Hinblick auf Parallelität, aber ich habe noch kein Spiel von einem Big Game gefunden, das Parallelität nicht unterstützt. Die Apps und Spiele, die ich gesehen habe und die Parallelität nicht unterstützen können, stammen im Allgemeinen aus kleineren Läden / einzelnen Entwicklern, in denen sie mit dieser Einstellung nicht begonnen hätten. Und irgendwann in der Entwicklung der Anwendung wird es unmöglich, die Parallelität nachträglich zu überprüfen. Und einige Apps sollten nie genug tun, um die gleichzeitige Verwendung zu rechtfertigen.
Und auch einige Spiele leben von neuen Inhalten (Grafik und Gameplay), ohne dass die Game-Engine aktualisiert werden muss (Code-Implementierung). Somit könnte die Game-Engine in der Technologie Jahre hinterherhinken.
rwong
6
@SnakeDoc: Sie benötigen keine Parallelität, um mit Tausenden von Bildschirmmodellen umzugehen. Es ist nicht so, dass jedes Objekt in Ihrem Spiel einen eigenen Thread benötigt, um es zu simulieren. Ein Thread kann die Aktualisierungen aller Bildschirminhalte in jedem Zeitschritt verarbeiten.
user2357112 unterstützt Monica
13

Hier geht es nicht so sehr um mehrere Kerne, sondern um mehrere Threads. Das Betriebssystem plant möglicherweise, dass ein Thread auf einem beliebigen Kern ausgeführt wird, und diese Planung ist für das geplante Programm transparent. Viele Programme werden jedoch nicht mit mehreren Threads geschrieben, sodass sie nur auf einem Kern gleichzeitig ausgeführt werden können.

Warum sollte ich ein Single-Thread-Programm schreiben? Sie sind einfacher zu schreiben und leichter zu debuggen: Eine Sache passiert nach der anderen (anstatt dass mehrere Dinge gleichzeitig passieren und sich gegenseitig in die Quere kommen). Oder Ihr Programm ist möglicherweise nicht auf Multi-Core-Computer ausgerichtet (wie dies bei alten Spielen der Fall war). In einigen Fällen kann ein Multithread-Programm sogar langsamer als eine Singlethread-Version ausgeführt werden, wenn der Overhead durch Kontextwechsel und Kommunikation zwischen Threads die Geschwindigkeit überwiegt, die durch die parallele Ausführung erzielt wird (einige Teile des Programms sind möglicherweise nicht parallelisierbar).

amon
quelle
8

Dies ist keine vollständige Antwort. Es ist eine warnende Geschichte.

Eines Tages dachte ich, ich würde den Studenten in meinem parallelen Programmierkurs eine parallele Kurzübersicht zeigen. Quicksort sollte gut passen, dachte ich. Ich habe zwei Fäden benutzt. Lief es auf meinem Single-Core-Computer. Die Ergebnisse waren:

  • 14 Sekunden für eine Singlethread-Version.
  • 15 Sekunden für die 2-Thread-Version.

Das war ungefähr das, was ich erwartet hatte.

Dann habe ich es auf einem neueren Dual-Core-Rechner ausprobiert.

  • 11 Sekunden für die Singlethread-Version.
  • 20 Sekunden für die 2-Thread-Version.

Die beiden Threads teilten sich eine Warteschlange verbleibender Aufgaben. Es scheint, dass die Felder des Warteschlangenobjekts zwischen dem Cache eines Kerns und dem des anderen hin und her verschoben wurden.

Theodore Norvell
quelle
2
Mit wie vielen Array-Elementen haben Sie getestet? Vielleicht wäre Mergesort besser geeignet, da die Mehrkernprogrammierung das Kopieren von Daten erforderlich gemacht hätte, um Cache-Line-Konflikte zu vermeiden?
rwong
2
@rwong Es gab 10.000.000 Array-Elemente. Sicherlich würde Mergesort gut parallelisieren. Hätte ich Merge-Sort verwendet, hätte ich wahrscheinlich keine nützliche Lektion gelernt.
Theodore Norvell
1
@ArlaudPierre Ich werde erwägen, einen Algorithmus zu parallelisieren. Quicksort ist interessant, da Sie dafür den Bag-of-Task-Ansatz verwenden können. Da die Aufgaben unabhängig sind, war meine Intuition, dass dies ein Beispiel für peinliche Parallelität sein sollte. Ich sollte erwähnen, dass es nach einigem Abstimmen tatsächlich eine Geschwindigkeit von fast 2 erreichte.
Theodore Norvell
1
@Jules Die Antwort lautet Load Balancing. Außerdem wollte ich es so schreiben, dass die Anzahl der Threads leicht geändert werden kann. Ihr Ansatz lässt sich gut auf Potenzen von 2 verallgemeinern, aber nicht so gut auf andere Anzahlen von Threads.
Theodore Norvell
2
@MaciejPiechotka Die Moral ist so ziemlich alles, was Sie vorschlagen. Zurück zum OP: Ich denke, die wichtigste Moral ist, dass ein Multithread-Programm auf einer Multi-Core-Architektur (viel) langsamer ausgeführt werden kann als auf einem Single-Core-Prozessor, es sei denn, es wurden Anstrengungen unternommen, um etwas anderes sicherzustellen.
Theodore Norvell