Warum würde ein Programm eine bestimmte Mindestanzahl von CPU-Kernen erfordern?

55

Ist es möglich, Code zu schreiben (oder eine vollständige Software anstelle eines Codeteils), der auf einer CPU mit weniger als N Kernen nicht ordnungsgemäß funktioniert? Ohne es explizit zu überprüfen und absichtlich zu versagen:

WENN (noOfCores <4) DANN absichtlich nicht richtig ausgeführt wird

Ich schaue mir die Mindestsystemanforderungen eines Spiels ( Dragon Age: Inquisition ) an, und es gibt ein Minimum von einer Vier-Kern-CPU an. Viele Spieler sagen, es läuft NICHT auf Zwei-Kern-CPUs und sogar auf Intel Core i3s mit zwei physischen und zwei logischen Kernen. Und es ist kein Problem der Rechenleistung.

Nach meinem Verständnis sind Threads vom Betriebssystem vollständig von der CPU isoliert, da dies nicht möglich ist.

Nur um das zu klären:

Ich frage NICHT "Kann ich die Anzahl der CPU-Kerne aus dem Code herausfinden und absichtlich versagen?" ... Ein solcher Code wäre nicht beabsichtigt (zwingt Sie dazu, eine teurere CPU zu kaufen, um ein Programm auszuführen - ohne Rechenleistung). Ich frage, dass Ihr Code beispielsweise vier Threads hat und fehlschlägt, wenn zwei Threads auf demselben physischen Kern ausgeführt werden (ohne explizite Überprüfung der Systeminformationen und absichtlich fehlgeschlagen) .

Kurz gesagt, kann es Software geben, die mehrere Kerne benötigt, ohne dass zusätzliche Rechenleistung von mehreren Kernen benötigt wird? Es wären lediglich N separate physische Kerne erforderlich.

Uylmz
quelle
11
Wenn Sie meine Frage sorgfältig lesen, werden Sie feststellen, dass sie nicht dasselbe fragen.
Uylmz
21
Da die Anzahl der Kerne abgerufen werden kann, kann sie mit N verglichen werden, und wenn dieser Vergleich als wahr ausgewertet wird, kann der Code das tun, was zum Teufel es will, einschließlich, aber nicht beschränkt auf Verhaltensweisen, die nicht beworben werden. Was ist deine Frage?
3
Sind Sie sicher, dass das Problem wirklich und direkt mit der Anzahl der Kerne zusammenhängt? Vielleicht basiert das erwähnte Spiel teilweise auf einer Funktion, die nur (korrekt) von einer CPU mit mindestens 4 Kernen bereitgestellt wird?
mgoeminne
25
Beachten Sie, dass "Mindestsystemanforderungen" häufig "Mindestsystemanforderungen für die Ausführung mit akzeptabler Leistung" sind, insbesondere bei Spielen. Es ist sehr wahrscheinlich, dass Dragon Age theoretisch auf einer einzelnen Core-Box ausgeführt werden kann, aber wenn Sie dies tun, werden massive Frame-Drops angezeigt. Daher ist diese Anzahl von Kernen erforderlich, um Sie nicht zum Kauf von Hardware zu zwingen, sondern um Qualitätsbeschwerden von Benutzern von Hardware der unteren Preisklasse zu vermeiden.
Gort the Robot
3
@ Sebb: Ich denke, Sie sind auf etwas fixiert: Wenn 4 physische Kerne mit mehr Cache als 2 physischen / 4 logischen Kernen korrelieren, könnte das Spiel natürlich auf 2x2-Rechnern ersticken, ohne die Rechenleistungsgrenzen zu überschreiten, da der gesamte Cache fehlt Zeit. Der Test würde darin bestehen, eine CPU mit 2x2 Kernen und viel Cache oder 4 Kernen und wenig Cache zu finden und zu sehen, was passiert.
Steve Jessop

Antworten:

45

Es kann möglich sein, dies "aus Versehen" mit unachtsamer Verwendung der Kernaffinität zu tun. Betrachten Sie den folgenden Pseudocode:

  • Einen Thread starten
  • Finden Sie in diesem Thread heraus, auf welchem ​​Core er ausgeführt wird
  • Setzen Sie die CPU-Affinität auf diesen Kern
  • starte etwas rechenintensives / loop für immer

Wenn Sie vier davon auf einer Zwei-Kern-CPU starten, liegt entweder ein Fehler bei der Einstellung der Kernaffinität vor, oder Sie haben zwei Threads, die die verfügbaren Kerne blockieren, und zwei Threads, die niemals geplant werden. Zu keinem Zeitpunkt wurde explizit gefragt, wie viele Kerne es insgesamt gibt.

(Wenn Sie Threads mit langer Laufzeit verwenden, verbessert das Festlegen der CPU-Affinität im Allgemeinen den Durchsatz.)

Die Idee, dass Spielefirmen die Leute dazu "zwingen", teurere Hardware ohne guten Grund zu kaufen, ist nicht sehr plausibel. Es kann nur Kunden verlieren.

Bearbeiten: Dieser Beitrag hat jetzt 33 Upvotes, was ziemlich viel ist, da er auf fundiertem Rätselraten basiert!

Es scheint, dass die Leute DA haben: Ich muss schlecht auf Dual-Core-Systemen laufen: http://www.dsogaming.com/pc-performance-analyses/dragon-age-inquisition-pc-performance-analysis/ Diese Analyse erwähnt, dass sich die Situation erheblich verbessert, wenn das Hyperthreading aktiviert ist. Da HT keine Anweisungseinheiten oder keinen Cache mehr hinzufügt, lässt es lediglich zu, dass ein Thread ausgeführt wird, während sich ein anderer in einem Cache-Stall befindet, was stark darauf hindeutet, dass er nur mit der Anzahl der Threads verknüpft ist.

Ein anderes Poster behauptet, dass das Ändern der Grafiktreiber funktioniert: http://answers.ea.com/t5/Dragon-Age-Inquisition/Working-solution-for-Intel-dual-core-CPUs/td-p/3994141 ; Angesichts der Tatsache, dass Grafiktreiber in der Regel ein erbärmlicher Schwarm sind, überrascht dies nicht. Eine berüchtigte Gruppe von Treibern hatte einen "richtigen & langsamen" gegenüber "schnellen & falschen" Modus, der ausgewählt wurde, wenn er von QUAKE.EXE aufgerufen wurde. Es ist durchaus möglich, dass sich die Treiber für eine unterschiedliche Anzahl von scheinbaren CPUs unterschiedlich verhalten. Vielleicht wird (zurück zur Spekulation) ein anderer Synchronisationsmechanismus verwendet. Missbrauch von Spinlocks ?

"Missbrauch von Sperr- und Synchronisationsprimitiven" ist eine sehr, sehr häufige Fehlerquelle. (Der Fehler, den ich beim Schreiben bei der Arbeit beobachten soll, ist "Absturz, wenn die Druckereinstellungen gleichzeitig mit dem Abschluss des Druckauftrags geändert werden").

Edit 2: Kommentare erwähnen das Betriebssystem, das versucht, das Verhungern von Threads zu vermeiden. Beachten Sie, dass das Spiel möglicherweise einen eigenen internen Quasi-Scheduler zum Zuweisen von Arbeit zu Threads hat und es einen ähnlichen Mechanismus in der Grafikkarte selbst gibt (was praktisch ein eigenes Multitasking-System ist). Die Wahrscheinlichkeit eines Fehlers in einem dieser Ordner oder der Interaktion zwischen ihnen ist sehr hoch.

Bei www.ecsl.cs.sunysb.edu/tr/ashok.pdf (2008) handelt es sich um eine Abschlussarbeit zur besseren Planung von Grafikkarten, in der ausdrücklich darauf hingewiesen wird, dass sie normalerweise die First-Come-First-Served-Planung verwenden, die einfach zu implementieren ist nicht vorbeugende Systeme. Hat sich die Situation verbessert? Wahrscheinlich nicht.

pjc50
quelle
1
Ja, die Beantwortung dieser Frage besteht aus zwei Teilen: Durch die CPU-Affinität kann man etwas codieren, das dies unter Windows zu einer technischen Anforderung macht. Die alternative Antwort lautet, dass Echtzeitsysteme solche Dinge auf jeden Fall erfordern können. +1 für die einzige Person, die die CPU-Affinität erwähnt, die am wahrscheinlichsten für die hier gestellten Fragen verantwortlich ist.
Jimmy Hoffa
3
Was kann schief gehen, wenn Sie die Affinität auf den aktuellen Kern setzen? Mit preemptives Multitasking die Warte Thread wird geplant werden , es sei denn , aktuelle maximal mögliche Priorität ( „Realtime“ in Windows) hat. Ich würde ein anderes Szenario sehen: Jedem der 4 Threads wird eine statisch definierte Affinität von 1,2,4,8 zugewiesen. In diesem Fall werden die letzten beiden Threads nie geplant (obwohl ich nicht sicher bin, ob die Affinität auf "effektiv" gesetzt wird Null wird erfolgreich sein).
Ruslan
@ Ruslan Wenn Sie versuchen, eine ungültige Affinität festzulegen, stürzt die Anwendung möglicherweise ab?
Luaan
1
@Luaan naja, das ist nicht so riskant, um zum Absturz zu führen. Maximal würde ich erwarten, dass ein Fehler vom Betriebssystem zurückgegeben wird. Ich habe gerade geprüft, in Linux erhalte ich die Fehlermeldung "Ungültiges Argument". Ich weiß nicht, was Windows sagen würde.
Ruslan
@ Ruslan Jedes wichtige Betriebssystem enthält seit mehr als einem Jahrzehnt Code, um das Verhungern von Threads zu vermeiden (normalerweise durch Erhöhen der Priorität eines Threads, nachdem er nicht lange genug ausgeführt wurde).
Voo
34

Möglicherweise sind 4 Kerne erforderlich, da die Anwendung vier Tasks in parallelen Threads ausführt und erwartet, dass diese fast gleichzeitig beendet werden.

Wenn jeder Thread von einem separaten Kern ausgeführt wird und alle Threads genau die gleiche Rechenlast haben, werden sie mit ziemlicher Wahrscheinlichkeit (aber bei weitem nicht garantiert) ungefähr zur gleichen Zeit beendet. Wenn jedoch zwei Threads auf einem Kern ausgeführt werden, ist das Timing viel weniger vorhersehbar, da der Kern die ganze Zeit über den Kontext zwischen den beiden Threads wechselt.

Fehler, die aufgrund eines unerwarteten Thread-Timings auftreten, werden als " Race Conditions " bezeichnet.

Im Kontext der Spieleentwicklung könnte eine plausible Architektur mit dieser Art von Problem darin bestehen, dass verschiedene Features des Spiels in Echtzeit von verschiedenen CPU-Threads simuliert werden. Wenn jede Funktion auf einem eigenen Kern ausgeführt wird, werden sie alle mit ungefähr derselben Geschwindigkeit simuliert. Wenn jedoch zwei Features auf einem Kern ausgeführt werden, werden beide nur halb so schnell simuliert wie der Rest der Spielwelt, was zu allen möglichen seltsamen Verhaltensweisen führen kann.

Beachten Sie, dass eine Softwarearchitektur, die von unabhängigen Threads abhängt, die mit bestimmten Timings ausgeführt werden, äußerst zerbrechlich ist und ein Zeichen für ein sehr schlechtes Verständnis der gleichzeitigen Programmierung ist. In praktisch allen Multithreading-APIs stehen Funktionen zur Verfügung, mit denen Threads explizit synchronisiert werden können, um solche Probleme zu vermeiden.

Philipp
quelle
11
Bei jedem Spiel besteht jedoch eine fragile Abhängigkeit davon, ob die gesamte Berechnung für den nächsten Frame rechtzeitig abgeschlossen werden kann, um sie mit einer angemessenen Häufigkeit zu rendern. Selbst wenn Ihre 4 Threads korrekt synchronisiert sind, kann es unmöglich sein, rechtzeitig zu rendern, und ein Spiel, das rechnerisch korrekt, aber aufgrund von Verzögerung und Ruckeln nicht spielbar ist, hat keinen Vorteil.
Nutzlos
1
@Useless: Das stimmt nicht wirklich. Sie können beispielsweise Frames oder Simulationsdaten puffern, um ein Ruckeln auszublenden, und es gibt gleichzeitig Designs, die konsistenter sind. Die Ausführung Ihrer gesamten Verarbeitung in X-Zeit und die exakte Synchronisierung dieser Verarbeitung sind verschiedene Aspekte.
DeadMG
23
"Eine Software-Architektur, die von unabhängigen Threads abhängt, die mit bestimmten Timings laufen, ist extrem fragil." Genau deshalb kann ich mir kein Spiel vorstellen, das überhaupt nicht mit 2 Kernen läuft, sondern zuverlässig mit 4 Kernen arbeitet. Selbst mit 4 Kernen ist das Timing unvorhersehbar, so dass die Racebedingung auch dann eintritt, wenn sie seltener auftritt.
Svick
8
@svick natürlich. Aber die Frage lautet: "Ist es möglich?" nicht "ist es gesund?"
user253751
5
Jeder Code mit dieser Art von "Rennbedingungen" ist völlig kaputt , egal auf wie vielen Kernen Sie ihn ausführen. (Zumal es absolut keine Garantie gibt, was sonst noch auf dem System läuft.) Ich bezweifle ernsthaft, dass dies die Ursache ist, da es das Spiel selbst auf einem Hexacore-System leicht auslösen würde ...
DevSolar
16

Es ist unwahrscheinlich, dass diese "Mindestanforderungen" etwas darstellen, unter dem das Spiel nicht ausgeführt werden kann. Viel wahrscheinlicher ist, dass sie etwas darstellen, unter dem das Spiel nicht mit akzeptabler Leistung läuft. Keine Spielefirma möchte mit vielen Kunden fertig werden, die sich über schlechte Leistung beschweren, wenn sie diese auf einer Single-Core-1-GHz-Box betreiben, selbst wenn die Software technisch laufen könnte. Aus diesem Grund werden sie wahrscheinlich absichtlich so konzipiert, dass sie bei Boxen mit weniger Kernen nicht so gut funktionieren, als dies bei einer akzeptablen Leistung der Fall wäre.

Eine wichtige Messgröße für die Spieleleistung ist die Framerate. Normalerweise werden sie mit 30 oder 60 Bildern pro Sekunde ausgeführt. Dies bedeutet, dass die Game Engine die aktuelle Ansicht aus dem Spielstatus in einer festgelegten Zeit rendern muss. Um 60 fps zu erreichen, sind dafür nur etwas mehr als 16 ms erforderlich. Spiele mit High-End-Grafik sind extrem CPU-gebunden, und daher gibt es ein großes Auf und Ab zwischen dem Versuch, eine höhere Qualität zu erzielen (was mehr Zeit in Anspruch nimmt) und der Notwendigkeit, in diesem Zeitbudget zu bleiben. Somit ist das Zeitbudget für jeden Rahmen extrem eng.

Da das Zeitbudget knapp ist, möchte der Entwickler im Idealfall exklusiven Zugriff auf einen oder mehrere Kerne. Sie möchten wahrscheinlich auch in der Lage sein, ihre Rendering-Aufgaben ausschließlich in einem Kern zu erledigen, da dies mit dem Zeitbudget geschehen muss, während andere Aufgaben wie die Berechnung des Weltzustands in einem separaten Prozess ablaufen, in dem dies nicht der Fall ist eindringen.

Theoretisch könnte man das alles auf einen Kern packen, aber dann wird alles viel schwieriger. Plötzlich musst du sicherstellen, dass alles, was mit dem Spielstatus zu tun hat, schnell genug vonstatten geht und dass dein Rendering funktioniert. Sie können sie nicht einfach zu zwei Software-Threads machen, da es keine Möglichkeit gibt, dem Betriebssystem klar zu machen, dass "Thread A X-Arbeit in 16 ms erledigen muss, unabhängig davon, was Thread B tut".

Spieleentwickler haben kein Interesse daran, dass Sie neue Hardware kaufen. Der Grund für die Systemanforderungen ist, dass sich die Kosten für die Unterstützung von Maschinen der unteren Preisklasse nicht lohnen.

Gort den Roboter
quelle
Dies ist zwar der Fall, aber es kann vorkommen, dass Sie Dual-Core-Hardware kaufen, die leistungsstark genug ist, um in einem bestimmten Zeitrahmen mehr zu erreichen als die in den Mindestspezifikationen beschriebene Quad-Core-Hardware. Warum würde der Anbieter eine solche Hardware nicht als akzeptabel einstufen, eine Entscheidung, die nur zu Umsatzverlusten führen kann?
Jules
4
Die Sache zu vergleichen ist nicht 2 gegen 4 Kerne. Es sind im Wesentlichen 1 vs. 3 Kerne, da CPU # 0 vom Grafiktreiber und den DPCs ziemlich stark abhängig ist. Es gibt auch erhebliche Cache- und Migrationseffekte, wenn Sie eine CPU mit mehreren Arten von Aufgaben in einem typischen modernen Job-System überbelegen. Die Anforderung ist da, weil Frostbite (DA: I's Motor) von Grund auf mit sehr sorgfältiger Abstimmung entworfen wurde, die eine bestimmte Anzahl von Kernen erfordert.
Lars Viklund,
6
@ LarsViklund Es hört sich so an, als wüssten Sie mehr Details als jeder andere hier. Haben Sie darüber nachgedacht, eine Antwort zusammenzustellen?
Gort the Robot
1
"Es ist unwahrscheinlich, dass diese" Mindestanforderungen "etwas darstellen, unter dem das Spiel nicht ausgeführt werden kann. Viel wahrscheinlicher ist, dass sie etwas darstellen, unter dem das Spiel nicht mit akzeptabler Leistung ausgeführt werden kann." - Intels G3258 ist ein sehr leistungsfähiger Dual-Core-Prozessor, der von Spielern verwendet wird und in der Lage ist, Spiele auszuführen, die mindestens so ressourcenintensiv sind wie Dragon Age Inquisition. Viele Spieler berichten jedoch, dass das Spiel nicht darauf ausgeführt wird.
Uylmz
2
@Reek Ich bezweifle, dass ein Endbenutzer leicht erkennen kann, wie ressourcenintensiv ein bestimmtes Spiel im Vergleich zu einem anderen ist.
Gort the Robot
9

Drei Echtzeit-Threads, die niemals schlafen, und ein weiterer Thread. Wenn weniger als vier Kerne vorhanden sind, wird der vierte Thread nie ausgeführt. Wenn der vierte Thread mit einem der Echtzeit-Threads kommunizieren muss, damit der Echtzeit-Thread beendet wird, wird der Code nicht mit weniger als vier Kernen beendet.

Wenn Echtzeit-Threads auf etwas warten, das sie nicht schlafen lässt (z. B. ein Spinlock), hat der Programmdesigner offensichtlich Fehler gemacht.

Joshua
quelle
1
Argumentieren, wenn eine Benutzeranwendung Echtzeit - Threads in den ersten Platz anfordert, geschraubt der Designer up: D
Luaan
2
Ich habe es getan. Eine halbe Million Codezeilen. Ein Fall mit ca. 300 Zeilen. Der Echtzeit-Thread verbringt die meiste Zeit damit, auf Eingaben zu warten, damit er die Eingabe mit einem Zeitstempel versehen und an einen Thread mit geringerer Priorität übergeben kann.
Joshua
2
@Luaan Für die meisten Anwendungen würde ich Ihnen zustimmen, aber Spiele sind ein anderes Biest, ebenso wie eingebettete Anwendungen. In beiden Fällen geht die Sorge, mit anderen gleichzeitigen Anwendungen gut zu spielen, meistens zugunsten der Leistung aus dem Fenster.
Reirab
Obwohl es nicht besonders effizient wäre, würde dieses Szenario nicht zu Deadlocks führen - die Prioritätsinversion würde sich darum kümmern (vorausgesetzt, ein halbwegs anständiger Scheduler in einem wichtigen Betriebssystem des letzten Jahrzehnts)
Voo
2
@Joshua > Windows weiß nicht, welche Priorität die Inversion hat. Was? support.microsoft.com/kb/96418 , msdn.microsoft.com/en-us/library/windows/desktop/ms684831.aspx . Prioritätsumkehrung ist auch der Begriff, der das Problem beschreibt , keine Lösung (@Voo).
Bob
3

Zunächst einmal haben Softwarethreads nichts mit Hardwarethreads zu tun und werden häufig vertauscht. Software-Threads sind Codeteile, die im Prozesskontext einzeln abgesetzt und ausgeführt werden können. Hardware-Threads werden zumeist vom Betriebssystem verwaltet und bei normalen Programmen an den Prozessorkern gesendet. Diese Hardwarethreads werden basierend auf der Last gesendet. Der Hardware-Thread-Dispatcher verhält sich mehr oder weniger wie ein Load Balancer.

Wenn es jedoch um Spiele geht, insbesondere High-End-Spiele, werden die Hardware-Threads manchmal vom Spiel selbst verwaltet oder das Spiel weist den Hardware-Thread-Dispatcher an, was zu tun ist. Das liegt daran, dass nicht jede Aufgabe oder Aufgabengruppe die gleiche Priorität hat wie in einem normalen Programm. Da Dragon Age aus einem High-End-Game-Studio stammt, das High-End-Game-Engines verwendet, kann ich mir vorstellen, dass es den manuellen Versand verwendet und dann die Anzahl der Kerne zu einer minimalen Systemanforderung wird. Jedes Programm stürzt ab, wenn ich einen Code an den 3. physischen Kern sende, der auf einem Computer mit nur 1 oder 2 Kernen ausgeführt wird.

dj bazzie wazzie
quelle
Diese. Denken Sie daran, dass das Sprichwort "Nein von Kernen überprüfen" bedeutet, dass ein Unternehmen sein Softwareprodukt auf eine bestimmte Weise herstellt, um Benutzer zum Kauf teurerer Hardware zu zwingen (was nicht beabsichtigt wäre).
Uylmz
2
Diese Probleme bestehen, solange es PC-Spiele gibt. Zu Beginn hatten wir 486dx und 486sx, später den MMX- und Nicht-MMX-Pentium, Core und Non-Core, und heute haben wir n-Core-Anforderungen. Dies ist einer der Gründe, warum Konsolen immer noch existieren.
DJ Bazzie Wazzie
4
Haben Sie eine Referenz für Spiele, die die CPU-Planung selbst übernehmen? Soweit mir bekannt ist, ist dies unter Windows nicht direkt möglich, zumindest nicht so, wie Sie es vorschlagen.
Jules
2
@djbazziewazzie Tatsächlich bietet Windows eine API, um genau das zu tun. Das heißt, Sie legen einen Thread fest, um immer den gleichen Kern zu verwenden. Dies wird als Thread-Affinität bezeichnet. Sie können nicht manuell auswählen, welcher Codeteil wo und wann ausgeführt werden soll, und können keinen Systemfehler verursachen, wie Sie vorschlagen (das System ignoriert die Anforderung, die Affinität für einen nicht vorhandenen Kern festzulegen Ich bin mir ziemlich sicher, dass dies das ist, was id Tech verwendet, und es läuft nicht wirklich darauf hinaus, "die Hardware-Threads selbst zu verwalten".
Jules
1
@djbazziewazzie Sie scheinen auch den Punkt von Grand Central Dispatch falsch zu verstehen, der Entwicklern keine bessere Kontrolle darüber gibt, wie ihr Code für einen Kern geplant ist. Der eigentliche Zweck ist das genaue Gegenteil: Sie müssen festlegen, wie viele Threads erstellt werden sollen und welcher Code auf welchem ​​Thread in den Händen von Anwendungen ausgeführt werden soll, damit er systemweit für die verfügbare Hardware optimiert werden kann. Die Abhängigkeit von einer bestimmten Anzahl von Kernen ist genau das Problem, das GCD verhindern soll.
Jules
1

Da es möglich ist, virtualize zu verwenden, um mehr virtuelle Kerne als physische zu haben, und die Software nicht weiß, dass es auf einem virtualize ausgeführt wird, und stattdessen denkt, dass es so viele physische Kerne hat, würde ich sagen, dass eine solche Software nicht möglich ist.

Das heißt, es ist nicht möglich, Software zu schreiben, die immer auf weniger als N Kernen stoppt.

Wie bereits erwähnt, gibt es Softwarelösungen, die möglicherweise überprüfen können, insbesondere wenn das verwendete Betriebssystem und der verwendete Code nur einen geringen Schutz vor Race-Bedingungen bieten, wenn N Prozesse auf <N Prozessoren ausgeführt werden. Der eigentliche Trick ist Code, der fehlschlägt, wenn Sie weniger als N Prozessoren haben, aber nicht fehlschlägt, wenn Sie N Prozessoren haben, aber ein Betriebssystem haben, das möglicherweise weniger als N Prozessoren Arbeit zuweist.

Lawtonfogle
quelle
1

Es kann sein, dass drei Threads etwas tun (Hintergründe generieren oder NPC-Bewegungen generieren) und Ereignisse an einen vierten Thread übergeben, der die Ereignisse aggregieren / filtern und das Ansichtsmodell aktualisieren soll. Wenn der vierte Thread nicht alle Ereignisse abruft (weil er nicht für einen Core geplant ist), wird das Ansichtsmodell nicht korrekt aktualisiert. Dies kann nur sporadisch vorkommen, diese Kerne müssen jedoch jederzeit verfügbar sein. Dies könnte erklären, warum Sie nicht die ganze Zeit über eine hohe CPU-Auslastung feststellen, das Spiel jedoch trotzdem nicht ordnungsgemäß funktioniert.

TMN
quelle
1
In einem solchen Szenario würde das Spiel auch nach dem Zufallsprinzip fehlschlagen, wenn die Ausführung von Hintergrunddiensten geplant ist, was bei den meisten PCs häufig der Fall ist.
Jules
1

Ich denke, Joshua ist auf dem richtigen Weg, nur nicht zu seinem Ende.

Angenommen, Sie haben eine Architektur, in der drei Threads geschrieben sind, um so viel wie möglich zu tun. Wenn sie fertig sind, was sie tun, tun sie es erneut. Um die Leistung aufrechtzuerhalten, geben diese Threads keine Kontrolle für irgendetwas frei - sie möchten nicht die Verzögerung durch den Windows-Taskplaner riskieren. Solange es 4 oder mehr Kerne gibt, funktioniert dies einwandfrei. Andernfalls tritt ein schwerer Fehler auf.

Im Allgemeinen wäre dies eine schlechte Programmierung, aber Spiele sind eine andere Sache - wenn Sie vor der Wahl stehen zwischen einem Design, das der gesamten Hardware unterlegen ist, oder einem Design, das der ausreichend guten Hardware überlegen ist, oder einem Fehler, für das sich Entwickler für unterlegene Hardware entscheiden die Hardware benötigen.

Loren Pechtel
quelle
Es ist normalerweise nicht möglich, einen Thread zu schreiben, der die Kontrolle nicht an andere Threads abgibt. Alle modernen Nicht-RTOS-Betriebssysteme verwenden preemptives Multitasking, wodurch es einem (Benutzermodus-) Thread absichtlich unmöglich wird, die Kontrolle über einen bestimmten Kern nicht freizugeben. Kernel-Threads sind natürlich eine andere Sache.
Reirab
@reirab Steigern Sie die Priorität.
Loren Pechtel
@Loren Ändert nichts an der Tatsache, dass der Scheduler immer noch seine Arbeit einstellt, was bedeutet, dass Sie Zeit mit anderen Threads gleicher Priorität teilen müssen und der Scheduler die Priorität von ausgehungerten Threads erhöht. Dies ist unter normalen Betriebssystemen nicht möglich, und selbst wenn dies möglich wäre, wären Spiele sicherlich auch keine akzeptable Anwendung dafür.
Voo,
1

Is it possible to write code (or complete software, rather than a piece of code) that won't work properly when run on a CPU that has less than N number of cores?

Absolut. Die Verwendung von Echtzeit-Threads wäre ein gutes Beispiel für eine Situation, in der dies nicht nur möglich ist, sondern auch der gewünschte (und häufig der einzig richtige) Weg, um die Arbeit zu erledigen. Echtzeit-Threads sind jedoch in der Regel auf den Betriebssystemkern beschränkt, in der Regel für Treiber, die gewährleisten müssen, dass ein Hardwareereignis in einem definierten Zeitraum verarbeitet wird. Sie sollten keine Echtzeit-Threads in normalen Benutzeranwendungen haben und ich bin nicht sicher, ob es überhaupt möglich ist, einen in einer Windows-Benutzeranwendung zu haben. Im Allgemeinen machen es Betriebssysteme absichtlich unmöglich, dies vom Benutzerland aus zu tun, da es einer bestimmten Anwendung ermöglicht, die Kontrolle über das System zu übernehmen.

In Bezug auf User-Land-Anwendungen: Ihre Annahme, dass die Überprüfung einer bestimmten Anzahl von Threads für die Ausführung zwangsläufig böswillig ist, ist nicht korrekt. Zum Beispiel könnten Sie zwei langfristige, leistungsintensive Aufgaben haben, die einen eigenen Kern benötigen. Unabhängig von der Geschwindigkeit des CPU-Kerns kann die gemeinsame Nutzung eines Kerns mit anderen Threads eine ernsthafte und inakzeptable Verschlechterung der Leistung bedeuten, da der Cache überlastet wird. Insbesondere für ein Spiel müssen Sie festlegen, dass jeder dieser Threads eine Affinität nur für einen bestimmten Kern für jeden von ihnen hat, und anschließend alle anderen Threads so festlegen, dass sie keine Affinität für diese 2 Kerne haben. Um dies zu tun, müssen Sie

reirab
quelle
1

Jeder Code, der Spinlocks mit einer bemerkenswerten Menge an Sperrkonflikten verwendet, wird eine schreckliche Leistung erbringen (in einem Ausmaß, in dem Sie für eine Anwendung wie ein Spiel "Funktioniert nicht" sagen können ), wenn die Anzahl der Threads die Anzahl der Kerne überschreitet.

Stellen Sie sich zum Beispiel einen Producer-Thread vor, der Aufgaben an eine Warteschlange sendet, die 4 Consumer-Threads bedient. Es gibt nur zwei Kerne:

Der Produzent versucht, den Spinlock zu erhalten, aber er wird von einem Verbraucher gehalten, der auf dem anderen Kern läuft. Die beiden Kerne laufen im Gleichschritt, während sich der Produzent dreht und darauf wartet, dass die Sperre freigegeben wird. Das ist schon schlimm, aber nicht so schlimm wie es wird.
Leider befindet sich der Consumer-Thread am Ende seiner Zeitmenge, sodass er vorab freigegeben wird und ein weiterer Consumer-Thread geplant ist. Es versucht, das Schloss zu erreichen, aber natürlich wird das Schloss genommen, also drehen sich jetzt zwei Kerne und warten auf etwas, das unmöglich passieren kann.
Der Produzententhread erreicht das Ende seiner Zeitscheibe und ist vorbelegt, wacht ein anderer Konsument auf. Wieder warten zwei Verbraucher auf die Freigabe einer Sperre, und dies wird erst geschehen, wenn zwei weitere Zeitquanten verstrichen sind.
[...] Schließlich hat der Verbraucher, der das Spinlock hielt, das Schloss freigegeben. Es wird sofort von dem genommen, der sich auf dem anderen Kern dreht. Es besteht eine 75% ige Chance (3 zu 1), dass es sich um einen weiteren Verbraucher-Thread handelt. Mit anderen Worten, es ist zu 75% wahrscheinlich, dass der Produzent noch festsitzt. Das bedeutet natürlich auch, dass die Verbraucher ins Stocken geraten. Ohne die Aufgaben des Produzenten haben sie nichts zu tun.

Beachten Sie, dass dies im Prinzip bei jeder Art von Sperre funktioniert, nicht nur bei Spinlocks - aber die verheerende Wirkung ist bei Spinlocks viel ausgeprägter, da die CPU die Brennzyklen beibehält, während sie nichts erreicht.

Stellen Sie sich nun vor, dass einige Programmierer zusätzlich zu den oben genannten die brillante Idee hatten, einen dedizierten Thread zu verwenden, dessen Affinität auf den ersten Kern festgelegt ist, sodass RDTSC auf allen Prozessoren zuverlässige Ergebnisse liefert (dies wird ohnehin nicht der Fall sein, aber manche Leute denken es).

Damon
quelle
Das ist der Grund, warum gute Spinlocks nach kurzer Zeit auf andere Lock-Typen herabgestuft werden, und noch bessere sehr viel schneller, wenn frühere Verwendungen desselben Locks herabgestuft werden mussten.
Ian
-1

Wenn ich verstehe, was Sie fragen, ist es möglich, aber es ist eine sehr, sehr schlechte Sache.

Das kanonische Beispiel für das, was Sie beschreiben, wäre die Pflege eines Zählers, der um mehrere Threads erhöht wird. Dies erfordert fast nichts an Rechenleistung, erfordert jedoch eine sorgfältige Koordination zwischen den Threads. Solange jeweils nur ein Thread ein Inkrement ausführt (bei dem es sich tatsächlich um einen Lesevorgang gefolgt von einer Addition gefolgt von einem Schreibvorgang handelt), ist sein Wert immer korrekt. Dies liegt daran, dass ein Thread immer den richtigen "vorherigen" Wert liest, einen hinzufügt und den richtigen "nächsten" Wert schreibt. Bringen Sie zwei Threads gleichzeitig in die Aktion, und beide lesen denselben "vorherigen" Wert, erhalten dasselbe Ergebnis aus dem Inkrement und schreiben denselben "nächsten" Wert. Der Zähler wurde effektiv nur einmal inkrementiert, obwohl zwei Threads glauben, dass sie es jeweils getan haben.

Diese Abhängigkeit zwischen Timing und Korrektheit wird in der Informatik als Race Condition bezeichnet .

Wettlaufsituationen werden häufig vermieden, indem Synchronisationsmechanismen verwendet werden, um sicherzustellen, dass Threads, die mit einem Teil der gemeinsam genutzten Daten arbeiten möchten, für den Zugriff in der Warteschlange stehen müssen. Der oben beschriebene Zähler könnte hierfür eine Lese- / Schreibsperre verwenden .

Ohne Zugriff auf das interne Design von Dragon Age: Inquisition kann jeder nur darüber spekulieren, warum es sich so verhält wie es ist. Aber ich werde versuchen, basierend auf einigen Dingen, die ich in meiner eigenen Erfahrung gesehen habe:

Möglicherweise basiert das Programm auf vier Threads, die optimiert wurden, sodass alles funktioniert, wenn die Threads größtenteils ohne Unterbrechung auf ihren eigenen physischen Kernen ausgeführt werden. Die "Optimierung" könnte in Form einer Neuanordnung des Codes oder der Einfügung von Ruhezuständen an strategischen Stellen erfolgen, um rassenzustandsbedingte Fehler, die während der Entwicklung aufgetreten sind, zu mindern. Auch dies ist alles eine Vermutung, aber ich habe gesehen, dass sich die Rennbedingungen mehrmals auf diese Weise "gelöst" haben, als ich zählen möchte.

Das Ausführen eines Programms auf diese Weise in einer Umgebung, die weniger leistungsfähig ist als die Umgebung, für die es optimiert wurde, führt zu Zeitänderungen, die darauf zurückzuführen sind, dass der Code nicht so schnell ausgeführt wird oder eher Kontextwechsel. Kontextwechsel erfolgen auf physische Weise (dh die physischen Kerne der CPU wechseln zwischen der Arbeit, die ihre logischen Kerne halten) und auf logische Weise (dh, das Betriebssystem in der CPU weist den Kernen Arbeit zu) wäre der "erwartete" Ausführungszeitpunkt. Das kann schlechtes Benehmen hervorrufen.

Wenn Dragon Age: Inquisition nicht den einfachen Schritt unternimmt, um sicherzustellen, dass genügend physische Kerne verfügbar sind, bevor Sie fortfahren, ist dies die Schuld von EA. Wahrscheinlich geben sie ein kleines Vermögen für Supportanrufe und E-Mails von Leuten aus, die versuchten, das Spiel mit zu wenig Hardware zu betreiben.

Blrfl
quelle
1
Einige Spieler sagen, dass DRM auf 2 Kernen und das eigentliche Spiel auch auf 2 Kernen läuft. Wenn DRM- und Game-Threads auf demselben Core ausgeführt werden, kommt es zu einem Durcheinander. Aber das klingt für mich nicht richtig, es könnte sich um eine kleine Geschichte handeln, die von einem Spieler erfunden wurde, der nicht viel über SW- oder Hardware-Architektur weiß.
Uylmz
4
Die Race-Bedingungen haben wirklich nicht viel mit der Core-Anzahl zu tun, -1 ... Eine einzelne Core-Maschine mit mehreren virtuellen Threads kann Race-Bedingungen aufweisen, die vollständig von der Time-Slicing-Technik der Laufzeit abhängen, oder ein System mit vielen Cores kann alle Race-Bedingungen vermeiden, die von den jeweiligen Threads abhängen darüber, wie streng es mit Membar-Operationen ist ...
Jimmy Hoffa
1
@Reek: Ohne genaue Kenntnis der Funktionsweise des Programms ist alles möglich. Zwei Kerne, um nur den DRM zu machen, scheinen mir ein wenig übertrieben zu sein.
Blrfl
1
@ JimmyHoffa: Ich bin anderer Meinung. Eine Racebedingung ist immer noch eine Racebedingung, auch wenn sie kein unerwünschtes Verhalten hervorruft. Die Kernanzahl kann beeinflussen, ob dieses Verhalten auftritt oder nicht, was der Fragesteller gefragt hat, aber ich habe es nicht als einzige Variable angegeben.
Blrfl
-1

Windows hat hierfür eine integrierte Funktionalität: Die Funktion GetLogicalProcessorInformation befindet sich in der Windows- API . Sie können es von Ihrem Programm aus aufrufen, um Informationen zu Kernen, virtuellen Kernen und Hyperthreading abzurufen.

Die Antwort auf Ihre Frage wäre also: Ja.

Pieter B
quelle
3
Ich frage nicht "Kann ich keine Kerne aus dem Code herausfinden?" ... Ein solcher Code ist nicht beabsichtigt (er zwingt Sie dazu, eine teurere CPU zu kaufen, um ein Programm auszuführen - ohne Rechenleistung).
Uylmz
3
Diese Funktion liefert viel mehr Informationen als nur eine rohe "Anzahl von Kernen". Mit diesen Informationen können Sie physische Kerne, logische Kerne und mehr abziehen. Wenn Sie das abziehen können, können Sie Software schreiben, um diese Informationen zu verwenden. In einer guten oder schlechten Weise (Absturzprogramm, wenn Sie 4 Kerne sehen, aber weniger als 4 physische Kerne).
Pieter B
1
Dies mag unter Windows funktionieren, aber was ist mit OSX / Linux / iOS / Android / etc.? Es bezieht sich zwar auf ein Spiel als eine Instanz, in der dieses Verhalten auftritt (und die natürliche Korrelation wäre Windows = Gaming), es scheint jedoch keine spielspezifische Anforderung zu sein.
Robert
Bei einem Spiel wie Dragon Age handelt es sich um Windows / XBox / PS4.
Gort the Robot
Linux hat /proc/cpuinfound sysconf(_SC_NPROCESSORS_ONLN)(letzteres wird in POSIX erwähnt). Das Verwenden der Informationen zum Erzwingen eines Mindestleistungsschwellenwerts ist jedoch immer noch eine ziemlich schlechte Form.
CHAO