Gibt es bei der Verwendung von Kernel-Objekten zur Synchronisierung von Threads, die auf verschiedenen CPUs ausgeführt werden, möglicherweise zusätzliche Laufzeitkosten, wenn Windows Server 2008 R2 relativ zu anderen Betriebssystemen verwendet wird?
Bearbeiten: Und wie über die Antwort herausgefunden, sollte die Frage auch den Ausdruck "bei niedriger CPU-Auslastung" enthalten. Ich habe mehr Informationen in meine eigene Antwort auf diese Frage aufgenommen.
Ich arbeite an einem Produkt, das gemeinsamen Speicher und Semaphoren für die Kommunikation zwischen Prozessen verwendet (wenn die beiden Prozesse auf demselben Computer ausgeführt werden). Berichte von Leistungsproblemen auf Windows Server 2008 R2 (die ich nachher auf Win2008R2 verkürze) führten mich zu der Feststellung, dass die gemeinsame Nutzung eines Semaphors zwischen zwei Threads auf Win2008R2 im Vergleich zu anderen Betriebssystemen relativ langsam war.
Ich konnte es reproduzieren, indem ich den folgenden Bitcode gleichzeitig für zwei Threads ausführte:
%Vor%Beim Testen mit einer Maschine, die in Windows Server 2003 R2 SP2 und Windows Server 2008 R2 gestartet wird, würde das obige Snippet auf der Win2003R2-Maschine etwa sieben Mal schneller als die Win2008R2 ( 3 Sekunden für Win2003R2 und 21 Sekunden) für Win2008R2 ).
Das Folgende ist die Vollversion des oben genannten Tests:
%Vor%Ich habe den Test aktualisiert, um die Threads zum Ausführen einer einzelnen Iteration zu erzwingen und einen Wechsel zum nächsten Thread in jeder Schleife zu erzwingen. Jeder Thread signalisiert dem nächsten Thread, dass er am Ende jeder Schleife ausgeführt wird (Round-Robin-Stil). Und ich habe es auch aktualisiert, um einen Spinlock als Alternative zum Semaphor zu verwenden (was ein Kernel-Objekt ist).
Alle Maschinen, an denen ich getestet habe, waren 64-Bit-Maschinen. Ich habe den Test meist als 32-Bit kompiliert. Wenn es als 64-Bit erstellt wurde, lief es insgesamt etwas schneller und änderte die Verhältnisse etwas, aber das Endergebnis war dasselbe. Neben Win2008R2 habe ich auch Windows 7 Enterprise SP 1, Windows Server 2003 R2 Standard SP 2, Windows Server 2008 (nicht R2) und Windows Server 2012 Standard ausgeführt.
Hier sind einige aktuelle Zahlen aus dem aktualisierten Test (Zeiten sind in Millisekunden):
%Vor%Jeder der 2 Threads im Test hat 1 Million Iterationen ausgeführt. Diese Hoden wurden alle auf identischen Maschinen ausgeführt. Die Win Server 2008- und Server 2003-Nummern stammen von einem Dual-Boot-Computer. Die Win 7-Maschine hat genau die gleichen Spezifikationen, war aber eine andere physische Maschine. Die Maschine ist in diesem Fall ein Lenovo T420 Laptop mit Core i5-2520M 2.5GHz. Offensichtlich keine Server-Klasse-Maschine, aber ich bekomme ein ähnliches Ergebnis auf echter Server-Klasse-Hardware. Die Zahlen in Klammern sind das Verhältnis der ersten Spalte zur angegebenen Spalte.
Jede Erklärung, warum dieses eine OS zusätzliche Kosten für die Kernel-Level-Synchronisation über die CPUs bringen würde? Oder kennen Sie einen Konfigurations- / Tuning-Parameter, der dies beeinflussen könnte?
Obwohl es diesen äußerst ausführlichen und langen Beitrag länger machen würde, könnte ich die verbesserte Version des Testcodes, von der die obigen Zahlen kommen, veröffentlichen, wenn jemand es möchte. Das würde die Durchsetzung der Round-Robin-Logik und der Spinlock-Version des Tests anzeigen.
Um zu versuchen, einige der unvermeidlichen Fragen zu beantworten, warum Dinge so gemacht werden. Und ich bin genauso ... wenn ich einen Beitrag lese, frage ich mich oft, warum ich überhaupt frage. Also hier sind einige Versuche zu klären:
Von den Kommentaren in eine Antwort gezogen:
Vielleicht ist der Server nicht auf den Hochleistungs-Energiesparplan eingestellt? Win2k8 hat möglicherweise einen anderen Standard. Viele Server sind nicht standardmäßig, was die Leistung sehr stark beeinträchtigt.
Das OP hat dies als Hauptursache bestätigt.
Dies ist ein lustiger Grund für dieses Verhalten. Die Idee blitzte in meinem Kopf auf, während ich etwas völlig anderes machte.
Es kann durchaus sein, dass die OS-Installationskonfiguration variiert. Möglicherweise ist das langsame System so konfiguriert, dass mehrere Threads aus Ihrem Prozess nicht gleichzeitig geplant werden. Wenn ein anderer Prozess mit hoher Priorität immer (oder meistens) zur Ausführung bereit ist, besteht die einzige Alternative darin, dass die Threads sequenziell und nicht parallel ausgeführt werden.
Ich füge diese zusätzlichen "Antwort" Informationen hier hinzu, anstatt sie in meinem überlangen OP zu vergraben. @usr hat mich mit dem Vorschlag zur Energieverwaltung auf die richtige Richtung gebracht. Der erfundene Test im OP sowie das ursprüngliche Problem beinhalten eine Menge Handshake zwischen verschiedenen Threads. Der Handshake in der Real-World-App erfolgte über verschiedene Prozesse hinweg, aber Tests zeigten, dass sich die Ergebnisse nicht unterscheiden, wenn es Threads oder Prozesse sind, die das Handshake durchführen. Die Freigabe des Semaphors (Kernel-Sync-Objekt) über die CPUs hinweg scheint in Windows Server 2008 R2 durch die Energieeinstellungen stark beeinträchtigt zu sein, wenn sie bei niedriger (z. B. 5% bis 10%) CPU ausgeführt wird. Mein Verständnis davon basiert an dieser Stelle rein auf Mess- und Timing-Anwendungen.
Eine verwandte Frage zu Serverfault spricht auch davon .
Einstellungen für die Energieeinstellungen des Betriebssystems Der standardmäßige Energiesparplan für Windows Server 2008 R2 lautet "Ausgewogen". Durch die Umstellung auf die "High Performance" -Option wurde die Leistung dieses Tests erheblich verbessert. Insbesondere scheint eine bestimmte Einstellung unter "Erweiterte Einstellungen ändern" kritisch zu sein. Die erweiterten Einstellungen haben eine Option unter Prozessor-Energieverwaltung mit dem Namen Minimaler Prozessorstatus . Der Standardwert dafür unter dem Balanced-Plan scheint 5% zu sein. Es war der Schlüssel, dies in meinem Test auf 100% zu setzen.
BIOS-Einstellung Außerdem hat eine BIOS-Einstellung diesen Test stark beeinflusst. Ich bin mir sicher, dass dies in der Hardware sehr unterschiedlich ist, aber die primäre Maschine, auf der ich getestet habe, hat eine Einstellung namens "CPU Power Management". Die Beschreibung der BIOS-Einstellung lautet, "Aktiviert oder deaktiviert die Energiesparfunktion, die die Mikroprozessoruhr automatisch stoppt, wenn keine Systemaktivitäten stattfinden." Ich habe diese Option auf "Deaktiviert" geändert.
Die zwei gezeigten Testfälle sind:
Die drei Testszenarien sind:
Die angegebenen Zeiten sind in Sekunden:
%Vor%Nachdem beide Änderungen vorgenommen wurden (OS und BIOS), liefen sowohl der reale Test als auch der künstliche Test ungefähr 5 mal schneller als unter der Standardinstallation und den Standard-BIOS-Einstellungen.
Während ich diese Fälle getestet habe, bin ich manchmal auf ein Ergebnis gestoßen, das ich nicht erklären konnte. Wenn die CPU beschäftigt war (ein Hintergrundprozess würde anspringen), würde der Test schneller laufen. Ich würde es in meinem Kopf ablegen und für eine Weile verwirrt sein. Aber jetzt macht es Sinn. Wenn ein anderer Prozess ausgeführt würde, würde dies die CPU-Nutzung über den Schwellenwert hinaus erhöhen, der benötigt wurde, um es in einem Zustand hoher Leistung zu halten, und die Kontextwechsel würden schnell sein. Ich weiß immer noch nicht, welcher Aspekt langsam ist (die primären Kosten sind im WaitForSingleObject-Aufruf begraben), aber die Endergebnisse sind jetzt alle irgendwie sinnvoll.
Das ist kein vernünftiger Benchmark, Ihre Semaphore werden immer im gleichen Prozess (und damit vermutlich auf derselben CPU / demselben Kern) ausgetobt. Ein wichtiger Teil der Kosten der Sperrung in realen Fällen sind die Speicherzugriffe, die beteiligt sind, wenn verschiedene CPUs / Kerne um exklusiven Zugriff auf den Speicherbereich kämpfen (der zwischen Caches hin und her springt). Suchen Sie nach mehr realen Benchmarks (sorry, nicht mein Bereich), o (noch besser) messen Sie Ihre Anwendung mit (gekünstelten, aber realistischen) Testdaten (eine etwas reduzierte Version von).
[Testdaten für Benchmarks sollten nie für Testzwecke oder Regressionstests sein: die späteren Stocherkästen bei (wahrscheinlich selten genutzten) Eckfällen, Sie wollen "typische" Läufe für Benchmarks.]
Tags und Links c multithreading synchronization performance windows-server-2008