• Hallo Gast, du kaufst gerne günstig ein und erfährst oft vor deinen Freunden von interessanten Angeboten? Dann kannst du dein Talent als Schnäppchenjäger jetzt zu Geld machen und anderen PCGH-Lesern beim Sparen helfen! Schau einfach mal rein - beim Test der Community Deals!

Benchmarkergebnisse, Teilnehmer Benchmark gesucht

larslrs

Komplett-PC-Aufrüster(in)
Hallo,

bei einem Performance-Test haben wir (gaussmath, ich) unerwartete Unterschiede zwischen Intel/AMD und Windows/Linux festgestellt.
Daher suchen wir weitere Ergebnisse zu diesem Benchmark.

Würdest Du zwecks Benchmark folgenden Algo bei Dir laufen lassen?
Für den Test möglichst alle anderen Programme schließen.

Wir haben zwei Varianten: Python Script für CPython >=3.5 sowie C#.
Interessant sind die Ergebnisse beider Varianten.

Für das Python-Script ist es unter Windows erforderlich, CPython zu installieren: Download Python | Python.org
Anschließend das Script mit Python öffnen und, falls sie nicht automatisch startet, mit F5 starten.

SC_bench_memPy3x.py (CPython >=3.5)
lars lrs, i3 7100 stock, DDR4@2400, CL10-12-12-28, Ubuntu 16.04 (alle patches installiert): 38s
HisN, i7 5960X@4.5Ghz, DDR4@2600, CL15-15-15-35, Windows10: 45.6s
Krolgosh, Xeon E5 2687W@3.10Ghz (stock), 64 GB DDR3@800, CL11-11-11-28, Windows 7: 80.9s
gaussmath, Ryzen 1950X@4Ghz + Game Mode (16MB Level 3 Cache aktiv, Dual Channel), DDR4@3446, CL14-14-14-30, Windows10: 54.8s
Olstyle, i5 5675c stock, Windows: 77.6s

SC_bench_memcs.cs:
lars lrs, i3 7100 stock, DDR4@2400, CL10-12-12-28, Ubuntu 16.04 (alle patches installiert): 9.3s
HisN, i7 5960X@4.5Ghz, DDR4@2600, CL15-15-15-35, Windows10: 9.0s
HisN, i7 5960X@4.5Ghz, DDR4@2600, CL15-15-15-35, Ubuntu16.04 Live-USB-Stick: 9.5s
Krolgosh, Xeon E5 2687W@3.10Ghz (stock), 64 GB DDR3@800, CL11-11-11-28, Windows 7: 12.2s
gaussmath, Ryzen 1950X@4Ghz + Game Mode (16MB Level 3 Cache aktiv, Dual Channel), DDR4@3446, CL14-14-14-30, Windows10: 13.3s
gaussmath, i7 3630QM@3.4Ghz, DDR3@1333, CL9-9-9-24, Windows10: 10.5s
Olstyle, i5 5675c stock, Windows: 8.6s

SC_bench_memcs16mb.cs
lars lrs, i3 7100 stock, DDR4@2400, CL10-12-12-28, Ubuntu 16.04 (alle patches installiert): 3.1s
gaussmath, i7 3630QM@3.4Ghz, DDR3@1333, CL9-9-9-24, Windows10: 3.9s
gaussmath, Ryzen 1950X@4Ghz + Game Mode (16MB Level 3 Cache aktiv, Dual Channel), DDR4@3446, CL14-14-14-30, Windows10: 2.1s
Olstyle, i5 5675c stock, Windows: 3.2s
_LS_ , i7 6700k@4,3GHz(Allcore), Cache@4,2GHz, DDR4@2400MHz CL14-14-14-36-1T Windows 10: 2.6s

Spectre und Meltdown-Patch
Olstyle, i5 5675c stock, Windows: Jeweils (fast) keine Unterschiede

Je mehr mitmachen, umso besser.

Vielen Dank,
Lars

Funktionsweise:
Es wird ein Array mit 16M Zufallszahlen (1...255) angelegt. Anschließend wird 2048 mal über das Array iteriert (äußere for-Schleife).
Pro Iteration wird in Abhängigkeit von der Zufallszahl im aktuellen Element das nächste Element ausgewählt (innere While-Schleife). Dh, die Schrittgröße ist abhängig von der gerade ausgewählten Zufallszahl. Wird 16M überschritten, so beginnt die nächste Iteration.
Hier und da wird etwas addiert, damit es auch etwas zu rechnen gibt: In der inneren while-Schleife ist dies der "Elemente-Index", der in Abhängigkeit von der gerade betrachteten Zufallszahl erhöht (+) oder verkleinert (-) wird. Letztlich wird insgesamt mehr addiert als subtrahiert.
In der äußeren for-Schleife werden alle Überläufe der inneren Schleife >16M modulo 2048 aufsummiert.
Jede der 2048 Iterationen startet mit einem anderen Wert, so dass sich die ausgewählten Werte pro Iteration teilweise voneinander unterscheiden.
 

Anhänge

Zuletzt bearbeitet:

gaussmath

Lötkolbengott/-göttin
@larslrs: Ich vermute, dass mit meinem Ryzen System was nicht stimmt. Normalerweise war die Single Core Leistung leicht höher oder vergleichbar mit dem i7. Jetzt liegen stattdessen rund 30% dazwischen. Ich werde das System demnächst mal frisch aufsetzen.
 
TE
L

larslrs

Komplett-PC-Aufrüster(in)
Mh, naja. 30% sind jetzt immer zwischen threadripper und i7 oder nur bei diesem Test? Falls nur bei diesem Test:
Du schriebst, die 13s sind mit NUMA. Könntest Du auch noch Legacy=On mit NUMA/UMA probieren? Bzw. mit Thread-to-core-pinning?
Das Problem ist mit 16MB gerade so zu groß für einen Die, bzw die Inter-Die-Kommunikation ist zu langsam.
 

gaussmath

Lötkolbengott/-göttin
Ich komme auf mind. 67MB Context Data. Hier greift wahrscheinlich die große Schwäche von Ryzen: parallele Datenzugriffe/Prefetches
 
TE
L

larslrs

Komplett-PC-Aufrüster(in)
Edit: Mir fällt gerade auf, Du hast das Array als Int-Werte angelegt, nicht als (unsigned) char. Das ist keine Entschuldigung dafür, dass es auf dem Threadripper langsamer läuft. Aber es kann erklären, warum es nicht in 32MByte Cache passt.


Der gesamte Kontext beinhaltet die Generierung der Zufallszahlen. Ich weiß nicht, wie effizient C# ist, aber nach der Erzeugung der Zufallszahlen gehen wir 2048x immer wieder über das gleiche 16MByte Array; Jedoch nicht in eine trivialen (einfach vorhersehbaren) Art und Weise. Das Bisschen Algorithmus sollte dann auch noch in 32MByte hinein passen (zumindest bei C, vielleicht nicht bei C# und vielleicht nicht bei Python)

Parallelen Datenzugriff macht der Algorithmus gerade nicht. Mit prefetch ist auch nicht viel. Dafür stehen die Zufallswerte im Array. Und davon hängt ab, was als nächstes überprüft/addiert wird.
 
Zuletzt bearbeitet:

gaussmath

Lötkolbengott/-göttin
Wie kommst du auf 16 MB für das Array? Es sind 2^24×4 Byte.

Parallele Datenzugriffe müssen ja auch nicht im Code explizit definiert werden. Das baut der Compiler so. Davon bekommt man als Programmierer nichts mit.
 
TE
L

larslrs

Komplett-PC-Aufrüster(in)
Wie kommst du auf 16 MB für das Array? Es sind 2^24×4 Byte.

Parallele Datenzugriffe müssen ja auch nicht im Code explizit definiert werden. Das baut der Compiler so. Davon bekommt man als Programmierer nichts mit.
Siehe Edit in meinem vorherigen Post: Hatte Deinen Code dahingehend nicht überprüft. Im Python script ist es 16M*char.

Parallel die Daten holen kann er ja. Eine Cache-Line ist ja nicht nur Byte breit. Er dürfte die Daten halt nur nicht (unnötig) wegwerfen, damit er sie noch hat, wenn im überübernächsten Durchlauf wieder darauf zugegriffen wird. Der Compiler hat IMHO keinen Grund, Daten zu holen, die der Algo nirgends braucht. Und die Zufallszahlen (wann wird auf welches Array-Element zugegriffen), kennt der Compiler auch nicht.
 

gaussmath

Lötkolbengott/-göttin
Ok, ich teste das mal uint8 morgen. Parallele Datenzugriffe machen hier keinen Sinn, ja. Was die Prefetches betrifft, wäre ich mir allerdings nicht so sicher. Kann der Compiler keine statistische Betrachtung durchführen, also jene Daten in den Cache laden, die mit hoher Wahrscheinlichkeit benötigt werden?

Mein System hat eine sehr hohe Bandbreite. Woher kommt der Unterschied? Das muss doch irgendeine Cache Magic sein.
 
TE
L

larslrs

Komplett-PC-Aufrüster(in)
Soweit ich es überblicke, sind die Latenzen beim Threadripper schlechter als bei Intel. Der Speicherzugriff des Scriptes ist Random und nicht vorhersehbar. Dh, hohe Latenzen sind besonders schlecht. Allerdings ist der Zugriff auf einen relativ kleinen Speicherbereich begrenzt, was man jedoch beim Betrachten von beispielsweise 100 Zugriffen nicht erkennen kann.

Eine Frage ist, ob Probleme einer bestimmten Größe extrem schnell (schneller als Intel) bearbeitet werden können, insofern das Problem (die Daten dazu) komplett in den L3-Cache passen. Dann hängt es davon ab, dass die Daten/Cachelines nicht wieder gelöscht/überschrieben werden. Wenn die CPU also zu dem Schluss kommt, dass der Prefetch nichts genützt hat, weil die nächsten Befehle die Prefetch-Daten nicht benötigen, die CPU jedoch nicht beliebig weit voraussehen kann, und deshalb die Daten einfach wieder überschreibt, dann stehen die Daten 2Sekunden später eben nicht mehr zur Verfügung und müssen erneut mit hoher Latenz geholt werden. In den Prefetch- und Cache-Mechanismen stecke ich im Moment auch nicht drin.

Mir stellt sich noch die Frage, ob man mit bestimmten (weiteren) Einstellungen (zB Legacy=On) etwas zum positiven hin bewegen kann. Dies würde darauf hin deuten, dass das Betriebssystem noch nicht mit der CPU zu recht kommt.

Wenn 256 Byte auf einmal geholt werden, dann hat man mit einer gewissen Wahrscheinlichkeit bereits das nächste benötigte Byte bekommen (siehe Algorithmus). Aber man hat 256 Byte geholt und nur 2 Byte davon benötigt.
 

gaussmath

Lötkolbengott/-göttin
Ich teste morgen mal weitere Settings. Da die 2000er Ryzen hinsichtlich der Latenzen verbessert wurden, wäre es super, wenn jemand mit einer solchen CPU das mal testen könnte.

Im allgemeinen ist die Beteiligung hier im PCGH Forum nicht so gut. Deshalb habe ich schon überlegt, ob wir nicht ins 3DCenter wechseln sollten.
 

Olstyle

Moderator
Teammitglied
Erklärt doch z.B. mal im Anfangspost genauer was das Programm rechnet bevor du direkt über mangelnde Beteiligung schimpfst ;).
Werde es bei Gelegenheit Mal auf dem Bratwell laufen lassen. Dessen "L4-Cache" dürfte auch interessant agieren.
 
TE
L

larslrs

Komplett-PC-Aufrüster(in)
Ich teste morgen mal weitere Settings. Da die 2000er Ryzen hinsichtlich der Latenzen verbessert wurden, wäre es super, wenn jemand mit einer solchen CPU das mal testen könnte.
Wahrscheinlich ist auch 16MByte zu groß für den 1950-Cache.
Es schaut so aus, als ob SC den Cache der anderen Dies nicht nutzbringend verwenden kann.
(AMD Ryzen's Infinity Fabric & Memory Subsystem, Explained)
Das ist dann bei 2950 wahrscheinlich auch so und für mich etwas unerwartet: Ich würde vermuten, dass man von einem Die zum anderen wesentlich besser Daten übertragen kann, als aus dem Speicher...
 

HisN

Kokü-Junkie (m/w)
Ich hab mal die ganze Sache unter Windows ausprobiert.


HisN, i7 5960X@4.5Ghz, DDR4@2600, CL15-15-15-35, Windows10

die von gaussmath bereitgestellte Exe
Runtime in seconds:00:00:09.0201888

das Python-Script
Runtime in seconds: 45.583479166030884

HisN, i7 5960X@4.5Ghz, DDR4@2600, CL15-15-15-35, Ubuntu16.04 Live-USB-Stick^^

Das Python-Script läuft auf der Live-Variante scheinbar nicht, erzählt was von Fehlerhaften Daten.
Das C-Script allerdings lässt sich mit Mono übersetzen und läuft dann etwas langsamer als unter Windows, nämlich 9,5 Sekunden.


Das Script läuft nur auf einem Kern? Mein alter Haswell taktet dabei nicht mal hoch^^ Also sind die 4.5Ghz eher mit sehr großer Vorsicht zu genießen.
 
Zuletzt bearbeitet:
TE
L

larslrs

Komplett-PC-Aufrüster(in)
Ja, das Script läuft nur auf einem Kern. Die Performance hängt jedoch auch vom Cache ab, so dass ein Mehrkerner mit mehr (oder anderem) Cache eine andere Performance haben kann.
 

Krolgosh

Software-Overclocker(in)
Hab das ganze mal auf meiner Workstation getestet:

SC_bench_memPy3x.py
Krolgosh, Xeon E5 2687W@3.10Ghz (stock), 64 GB DDR3@800, CL11-11-11-28, Windows 7 = 80.93665623664856 sec

SC_bench_memcs.cs:
Krolgosh, Xeon E5 2687W@3.10Ghz (stock), 64 GB DDR3@800, CL11-11-11-28, Windows 7 = 12.2413849 sec

Kann das heut Abend dann gern auch nochmal mit meinem i7 daheim machen.
 

gaussmath

Lötkolbengott/-göttin
Ok, jetzt wirds interessant. Ich habe den Datentyp auf byte umgestellt, uint8 gibt's übrigens unter C# nicht. Der Code ist somit jetzt erst äquivalent zum Python Skript.

gaussmath, i7 3630QM@3.4Ghz, DDR3@1333, CL9-9-9-24, Windows10, Runtime in seconds:00:00:03.9727339

gaussmath, Ryzen 1950X@4Ghz + Game Mode (16MB Level 3 Cache aktiv, Dual Channel), DDR4@3446, CL14-14-14-30, Windows10, Runtime in seconds:00:00:02.1354053

Erklärt doch z.B. mal im Anfangspost genauer was das Programm rechnet bevor du direkt über mangelnde Beteiligung schimpfst
.
Gerechnet wird da im Grunde gar nicht. Es ist ein Cache/Speicherbenchmark, der sich dadurch auszeichnet, dass die Speicherzugriffe zufällig verteilt sind. Das Speichermanagement "hasst" derartige Speicherzugriffe, weil sequentielle Zugriffe besser verarbeitet werden können. Das System "weiß" sozusagen, was als nächstes benötigt wird und kann entsprechend optimieren.
 

Anhänge

Zuletzt bearbeitet:

gaussmath

Lötkolbengott/-göttin
Code:
[COLOR=blue]using[/COLOR] System;
[COLOR=blue]using[/COLOR] System.Diagnostics;
 
[COLOR=blue]namespace[/COLOR] TestPythonBenchmark
{
    [COLOR=blue]class[/COLOR] [COLOR=#2b91af]Program[/COLOR]
    {
        [COLOR=blue]private[/COLOR] [COLOR=blue]static[/COLOR] [COLOR=#2b91af]Random[/COLOR] _random = [COLOR=blue]new[/COLOR] [COLOR=#2b91af]Random[/COLOR](241500528);
 
        [COLOR=blue]static[/COLOR] [COLOR=blue]void[/COLOR] Main([COLOR=blue]string[/COLOR][] args)
        {
            [COLOR=blue]const[/COLOR] [COLOR=blue]int[/COLOR] cycles = 2048;
            [COLOR=blue]int[/COLOR] testsize = ([COLOR=blue]int[/COLOR])[COLOR=#2b91af]Math[/COLOR].Pow(2, 24);
 
            [COLOR=blue]byte[/COLOR][] testdata = [COLOR=blue]new[/COLOR] [COLOR=blue]byte[/COLOR][testsize];
 
            [COLOR=blue]for[/COLOR] ([COLOR=blue]int[/COLOR] i = 0; i < testsize; i++)
            {
                testdata[i] = ([COLOR=blue]byte[/COLOR])_random.Next(1, 255);
            }
 
            [COLOR=blue]int[/COLOR] the_sum = 0;
 
            [COLOR=#2b91af]Stopwatch[/COLOR] stopwatch = [COLOR=blue]new[/COLOR] [COLOR=#2b91af]Stopwatch[/COLOR]();
            stopwatch.Start();
 
            [COLOR=blue]for[/COLOR] ([COLOR=blue]int[/COLOR] k = 0; k < cycles; k++)
            {
                [COLOR=blue]int[/COLOR] value = k;
                [COLOR=blue]while[/COLOR] (value < testsize)
                {
                    [COLOR=blue]if[/COLOR] (testdata[value] > 128)
                    {
                        value += testdata[value];
                    }
                    [COLOR=blue]else[/COLOR]
                    {
                        value--;
                    }
                }
                the_sum += (value % cycles);
            }
 
            stopwatch.Stop();
 
            [COLOR=blue]if[/COLOR] (the_sum != 200704)
            {
                [COLOR=blue]throw[/COLOR] [COLOR=blue]new[/COLOR] [COLOR=#2b91af]Exception[/COLOR]([COLOR=#a31515]"wrong test result"[/COLOR]);
            }
            [COLOR=blue]else[/COLOR]
            {
                [COLOR=#2b91af]Console[/COLOR].WriteLine([COLOR=#a31515]"Runtime in seconds:"[/COLOR] + stopwatch.Elapsed);
            }
 
            [COLOR=#2b91af]Console[/COLOR].ReadKey();
        }
    }
}
 

gaussmath

Lötkolbengott/-göttin
Ich habe auch noch die Werbetrommel gerührt im Thread "AMD Ryzen". Leider noch keiner hier vorbeigeschaut mit einem 2000er Ryzen... :(
 
TE
L

larslrs

Komplett-PC-Aufrüster(in)
3.1s auf dem i3.

L4-Cache würde mich noch interessieren. Schaut so aus, als ob Python (bei den bisher getesteten Systemen) nur wenig Nutzen aus dem Cache ziehen kann.

Ich werde die Ergebnisse etwas sortieren im ersten Post.
 
TE
L

larslrs

Komplett-PC-Aufrüster(in)
@gaussmath:
sind die Threadripper 54.8s (python3) und die 13.3s (csV1) auch nur mit 16MByte L3-Cache, oder mit mehr? Siehe erster Post.
 

Olstyle

Moderator
Teammitglied
Mal der Bratwell i5 mit und ohne Spectre. Da der L4 nur Victim-Cache ist dürfte er für die Anwendung hier nicht soo spannend sein, schließlich liegt der Witz im Programm ja darin dass es Daten nicht mehrfach nutzt.
cacheBench.jpgcacheBenchNoSpectre.jpg
 
TE
L

larslrs

Komplett-PC-Aufrüster(in)
Mal der Bratwell i5 mit und ohne Spectre. Da der L4 nur Victim-Cache ist dürfte er für die Anwendung hier nicht soo spannend sein, schließlich liegt der Witz im Programm ja darin dass es Daten nicht mehrfach nutzt.
Interessante Ergebnisse.
...wobei das Problem aber in den L4-Cache passen würde und dies der Laufzeit durchaus zuträglich sein könnte, insofern die Cache-Lines nicht gelöscht werden.
 

Olstyle

Moderator
Teammitglied
Generell sind interpretierte Sprachen und JIT nicht gerade ideal für sowas da noch ein unbekannter Anteil Runtime dazu kommt. Nur so zum Spaß hab ich es gerade auch mal auf einem MotoZ Play laufen lassen.https://uploads.tapatalk-cdn.com/20180716/72a6241e37e5c5255c2f238ef7159ccb.jpg
 
TE
L

larslrs

Komplett-PC-Aufrüster(in)
Mir geht es jedoch nicht um Längenvergleich, sondern um die Vergleichbarkeit von RealeWelt-Szenarien. Ich nutze viel Python. gaussmath nutzt c#.
Man kann das Python-Script auch vorkompilieren, dann wäre es schneller. Dann kann man noch dies und jenes machen...oder den Algo Cache-freundlich umschreiben, usw. ...oder man bemüht sich um Computer, die Python-Scripte "schnell" ausführen. Teilweise kann man raten, was nutzbringend ist, aber Performance-Vergleiche sind auch sehr hilfreich.
 

Olstyle

Moderator
Teammitglied
Der 5675 läuft übrigens @Stock (Dank H97 geht auch nichts Anderes), boostet also auch über die 3,1GHz hinaus (bis 3,6GHz).
 

gaussmath

Lötkolbengott/-göttin
Ich verstehe nicht, warum der TR bei der 16MB Variante so viel schneller ist, bei der 64MB Variante hingegen deutlich langsamer.
 

_LS_

Freizeitschrauber(in)
Hab die SC_bench_memcs16mb.exe bei mir mal getestet (11 Durchläufe in kurzen Abständen):
(Davor hab ich mal mit Hintergrundprogrammen getestet und hatte etwa 0,3s mehr)

Mittelwert: 2,673805064s
Minimum: 2,5925139s
Maximum: 2,8438305s

System: Windows 10 (Build 1803), CPU: i7 6700k@4,3GHz(Allcore), Cache@4,2GHz, RAM: DDR4@2400MHz CL14-14-14-36-1T

C#Bench.PNG

Morgen teste ich nochmal die anderen Varianten
 
Zuletzt bearbeitet:

amdahl

Volt-Modder(in)
Sehe ich richtig dass der Benchmark letzten Endes zufällige Speicherzugriffe testet? Bzw. ob das ganze Array in den Cache passt? Bei einer Sprungweite von maximal 255 bencht man zusätzlich was der Hardware-Prefetcher macht.

Das würde auch erklären warum der Threadripper mit einem 16MB Array deutlich schneller ist als mit 64MB. Die 16MB passen in den L3-Cache eines einzelnen dies, 64MB eben nicht mehr.
 
Zuletzt bearbeitet:

amdahl

Volt-Modder(in)
Selbst wenn das Array nicht komplett rein passt betrifft es vielleicht ein paar Prozent der Zugriffe. Das macht den Kohl wirklich nicht fett so wie der Algorithmus arbeitet.
 
TE
L

larslrs

Komplett-PC-Aufrüster(in)
das python script will leider nicht wie HisN schon geschrieben hatte, Ubuntu Server 16.04 :P
Du sollst Python ab Version 3.5 nehmen. Steht im Eingangspost, im Sourcecode und im Dateiname.

Ich arbeite sonst ja auch mit dem 2er. Aber gab bereits Leute, die nur das 3er installiert haben. Deshalb habe ich eine 3er Version gemacht. Durchläufe mit 2er und 3er sind nicht vergleichbar. Für das eine Script kann mal man schon mal das 3er starten :)
 
TE
L

larslrs

Komplett-PC-Aufrüster(in)
Das läuft quasi mit dem Faktor 2400/3466 schlechter... Ich kapier's nicht.
Da bräuchte es nun noch die Zeiten für cycles={128,256,512,1024}

EDit: ne, moment. Passt doch. Ich sehe bei Dir kaum noch durch. Poste doch mal bitte immer komplett, was Du hast gerade laufen lassen sowie im Vergleich vollständig dazu, was unstimmig ist.
 
Oben Unten