In diesem Array-Zugriffs-Mikrobenchmark (relativ zu GCC) erleidet Go einen 4-fachen Leistungsverlust. Was verursacht das? Dieses Problem betrifft viele Aspekte wie den Laufzeitmechanismus und die Compileroptimierung der Go-Sprache. Erstens verwendet die Go-Sprache beim Zugriff auf Arrays einen Grenzprüfungsmechanismus, dh bei jedem Zugriff auf ein Array-Element werden Grenzprüfungen durchgeführt, was zu einem gewissen Leistungsverlust führt. Zweitens ist der Go-Sprachcompiler relativ schwach optimiert und kann den Array-Zugriff nicht gut optimieren. Darüber hinaus hat der Garbage-Collection-Mechanismus der Go-Sprache auch einen gewissen Einfluss auf die Leistung. Zusammengenommen führten diese Faktoren dazu, dass Go im Array-Zugriffs-Mikrobenchmark einen vierfachen Leistungsverlust erlitt.
Ich habe diesen Mikrobenchmark geschrieben, um die Leistungsmerkmale von go besser zu verstehen, damit ich fundierte Entscheidungen darüber treffen kann, wann ich es verwenden möchte.
Aus Sicht des Performance-Overheads wäre dies meiner Meinung nach ein ideales Szenario für go:
Trotzdem sah ich einen 4-fachen Geschwindigkeitsunterschied im Vergleich zu gcc -o3
auf amd64. Warum das?
(Verwenden Sie das Shell-Timing. Es dauert jedes Mal ein paar Sekunden, daher ist der Start vernachlässigbar)
package main import "fmt" func main() { fmt.println("started"); var n int32 = 1024 * 32 a := make([]int32, n, n) b := make([]int32, n, n) var it, i, j int32 for i = 0; i < n; i++ { a[i] = i b[i] = -i } var r int32 = 10 var sum int32 = 0 for it = 0; it < r; it++ { for i = 0; i < n; i++ { for j = 0; j < n; j++ { sum += (a[i] + b[j]) * (it + 1) } } } fmt.printf("n = %d, r = %d, sum = %d\n", n, r, sum) }
c-Version:
#include <stdio.h> #include <stdlib.h> int main() { printf("started\n"); int32_t n = 1024 * 32; int32_t* a = malloc(sizeof(int32_t) * n); int32_t* b = malloc(sizeof(int32_t) * n); for(int32_t i = 0; i < n; ++i) { a[i] = i; b[i] = -i; } int32_t r = 10; int32_t sum = 0; for(int32_t it = 0; it < r; ++it) { for(int32_t i = 0; i < n; ++i) { for(int32_t j = 0; j < n; ++j) { sum += (a[i] + b[j]) * (it + 1); } } } printf("n = %d, r = %d, sum = %d\n", n, r, sum); free(a); free(b); }
Update:
range
kann die Fahrgeschwindigkeit um das Zweifache erhöht werden. -march=native
将 c 速度提高了 2 倍。 (并且-mno-sse
给出编译错误,显然与-o3
in meinen Tests range
gccgo sieht hier gleichwertig mit gcc aus (und erfordert kein
-march=native
Dies erklärt auch gut, warum Sie eine vierfache Leistungssteigerung feststellen würden, da GCC SSE anstelle von AVX verwendet, wenn es nicht auf eine bestimmte Architektur abzielt, was bedeutet, dass skalare 32-Bit-Anweisungen viermal so breit sind, um damit zu arbeiten. Tatsächlich führte das Hinzufügen von
Ich bin mit Go nicht gut genug vertraut, um Ihnen sagen zu können, ob der Go-Compiler grundsätzlich nicht in der Lage ist, automatisch Vektoren zu erstellen, oder ob es nur dieses spezielle Programm ist, das aus irgendeinem Grund den Fehler verursacht, aber das scheint die Hauptursache zu sein 🎜
Das obige ist der detaillierte Inhalt vonWas verursacht den vierfachen Leistungsverlust von Go bei diesem Array-Zugriffs-Mikrobenchmark (im Vergleich zu GCC)?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!