Diese Frage untersucht den unerwarteten Leistungsabfall bei der Einführung von Parallelität in ein vorhandenes Go-Programm. Der Code simuliert Interaktionen mit Monstern in einem Spiel und verfolgt erfolgreiche Item-Drops. Um die Effizienz zu verbessern, versuchte der Programmierer, die Arbeitslast mithilfe von Parallelität auf die verfügbaren Prozessoren aufzuteilen, was jedoch zu einer erheblichen Verlangsamung führte.
Ohne Parallelität führt das Programm eine Reihe von Simulationen aus (in diesem Fall 1.000) und jede Simulation führt eine bestimmte Anzahl von Interaktionen aus (in diesem Beispiel 1.000.000). Die Ergebnisse werden dann verwendet, um die Gesamtzahl erfolgreicher Interaktionen zu berechnen.
Um den Code zu parallelisieren, erstellt der Programmierer mehrere Goroutinen, von denen jede für die Ausführung eines Teils der Simulationen verantwortlich ist. Sie verteilen die Arbeitslast korrekt auf die verfügbaren CPUs und passen die Anzahl der Goroutinen an die Anzahl der Prozessoren an.
Überraschenderweise wurde der gleichzeitige Code vier- bis sechsmal ausgeführt, anstatt die Leistung zu verbessern langsamer als sein sequentielles Gegenstück.
Das Problem liegt im gemeinsamen Status, auf den zugegriffen wird gleichzeitige Goroutinen. Insbesondere verwendet die Funktion rand.Float64() eine gemeinsam genutzte globale Rand-Instanz mit einer zugehörigen Mutex-Sperre. Wenn mehrere Goroutinen versuchen, auf die globale Rand-Instanz zuzugreifen, müssen sie die Mutex-Sperre erwerben, was zu Konflikten führt und den Code verlangsamt.
Um das Leistungsproblem zu beheben, erstellt der Programmierer eine separate Rand-Instanz für jede Goroutine. Dadurch entfällt die Konkurrenz um die globale Rand-Instanz, sodass Goroutinen unabhängig voneinander ausgeführt werden können.
Das Erstellen einer separaten Rand-Instanz für jede Goroutine verbessert die Leistung erheblich. Der gleichzeitige Code läuft jetzt etwa 2,5-mal schneller als die nicht-gleichzeitige Version auf einer Dual-Core-CPU.
Dieses Szenario zeigt, wie wichtig es ist, die von gemeinsam genutzten Ressourcen verwendeten Synchronisierungsmechanismen zu verstehen bei der Implementierung der Parallelität. Es unterstreicht den Einfluss von Datenzugriffsmustern auf die Leistung und die Notwendigkeit, den Kompromiss zwischen Prozessorauslastung und Synchronisierungsaufwand zu berücksichtigen.
Das obige ist der detaillierte Inhalt vonWarum ist mein gleichzeitiger Go-Code langsamer als sein sequentielles Gegenstück?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!