C # Aufruf von nativem Code ist schneller als systemeigener nativer Aufruf

9

Bei einigen Leistungstests bin ich auf eine Situation gestoßen, die ich nicht zu erklären vermag.

Ich habe den folgenden C-Code geschrieben:

%Vor%

Ich verwende gcc, um es zusammen mit einem Testtreiber in eine einzelne Binärdatei zu kompilieren. Ich benutze auch gcc, um es selbst zu einem gemeinsamen Objekt zu kompilieren, das ich von C # über p / invoke rufe. Die Absicht ist, den Leistungsaufwand beim Aufrufen von systemeigenem Code aus C # zu messen.

In C und C # erzeuge ich Eingabedatenfelder gleicher Länge mit zufälligen Werten und messe dann, wie lange es dauert, bis multi_arr ausgeführt wird. In C # und C verwende ich den POSIX clock_gettime () Aufruf für das Timing. Ich habe die Timing-Aufrufe unmittelbar vor und nach dem Aufruf von multi_arr positioniert, so dass die Vorbereitungszeit usw. keine Auswirkungen auf die Ergebnisse hat. Ich führe 100 Iterationen durch und melde sowohl die durchschnittliche als auch die minimale Zeit.

Obwohl C und C # die exakt gleiche Funktion ausführen, kommt C # etwa 50% der Zeit vor, normalerweise um einen signifikanten Betrag. Zum Beispiel, für eine Länge von 1.048.576, C # ist min 768.400 ns vs C's min von 1.344.105. C # 's ist durchschnittlich 1.018.865 vs C's 1.852.880. Ich füge einige verschiedene Zahlen in dieses Diagramm ein (beachten Sie die Log-Skalen):

Diese Ergebnisse scheinen mir extrem falsch zu sein, aber das Artefakt ist über mehrere Tests konsistent. Ich habe die ASM und IL überprüft, um die Richtigkeit zu überprüfen. Bitness ist gleich. Ich habe keine Ahnung, was die Leistung in diesem Ausmaß beeinflussen könnte. Ich habe ein minimales Reproduktionsbeispiel hier hier eingerichtet.

Diese Tests wurden alle auf Linux (KDE neon, basierend auf Ubuntu Xenial) mit dotnet-core 2.0.0 und gcc 5.0.4 ausgeführt.

Hat jemand das schon mal gesehen?

    
Xcelled194 24.09.2017, 20:24
quelle

1 Antwort

2

Es hängt von der Ausrichtung ab, wie Sie bereits vermuten. Der Speicher wird zurückgegeben, so dass der Compiler ihn für Strukturen verwenden kann, die beim Speichern oder Abrufen von Datentypen wie Doubles oder Integers keine unnötigen Fehler verursachen, aber keine Zusicherung gibt, wie der Speicherblock in den / die Cache (s) passt / p>

Wie dies variiert, hängt von der Hardware ab, auf der Sie testen. Angenommen, Sie sprechen hier über x86_64, bedeutet dies den Intel- oder AMD-Prozessor und seine relative Geschwindigkeit der Caches im Vergleich zum Hauptspeicherzugriff.

Sie können dies simulieren, indem Sie verschiedene Ausrichtungen testen.

Hier ist ein Beispielprogramm, das ich zusammengeschustert habe. Auf meinem i7 sehe ich große Variationen, aber der erste nicht ausgerichtete Zugriff ist zuverlässig langsamer als der mehr ausgerichtete Versionen.

%Vor%     
fork2execve 03.10.2017, 08:57
quelle

Tags und Links