Wie vorhin geschrieben, hier die Ergebnisse:
Code: Alles auswählen
386sx16 386dx25 486dx100 duron750
MOD64=00 56 155 1397 10267
MOD64=01 62 155 1397 11974
MOD64=02 59 146 1397 11972
MOD64=03 58 146 1397 10073
MOD64=04 56 155 1397 10073
MOD64=05 62 155 1397 10073
MOD64=06 59 146 1397 11712
MOD64=07 58 146 1397 11260
MOD64=08 56 155 1397 11257
MOD64=09 62 155 1289 11965
MOD64=10 59 146 1289 8994
MOD64=11 58 146 1397 10080
MOD64=12 56 155 1397 10081
MOD64=13 62 155 1397 9940
MOD64=14 59 146 1397 11712
MOD64=15 58 146 1397 10267
MOD64=16 56 155 1397 10267
MOD64=17 62 155 1397 11973
MOD64=18 59 146 1397 11971
MOD64=19 58 146 1397 10073
MOD64=20 56 155 1397 10073
MOD64=21 62 155 1397 10073
MOD64=22 59 146 1397 11712
MOD64=23 58 146 1397 11261
MOD64=24 56 155 1397 11257
MOD64=25 62 155 1289 11965
MOD64=26 59 146 1289 8994
MOD64=27 58 146 1397 10081
MOD64=28 56 155 1397 10081
MOD64=29 62 155 1397 9940
MOD64=30 59 146 1397 11712
MOD64=31 58 146 1397 10267
MOD64=32 56 155 1397 10267
MOD64=33 62 155 1397 11973
MOD64=34 59 146 1397 11973
MOD64=35 58 146 1397 10073
MOD64=36 56 155 1397 10073
MOD64=37 62 155 1397 10073
MOD64=38 59 146 1397 11712
MOD64=39 58 146 1397 11261
MOD64=40 56 155 1397 11257
MOD64=41 62 155 1289 11964
MOD64=42 59 146 1289 8994
MOD64=43 58 146 1397 10082
MOD64=44 56 155 1397 10081
MOD64=45 62 155 1397 9940
MOD64=46 59 146 1397 11712
MOD64=47 58 146 1397 10267
MOD64=48 56 155 1397 10267
MOD64=49 62 155 1397 11975
MOD64=50 59 146 1397 11971
MOD64=51 58 146 1397 10073
MOD64=52 56 155 1397 10073
MOD64=53 62 155 1397 10073
MOD64=54 59 146 1397 11712
MOD64=55 58 146 1397 11261
MOD64=56 56 155 1397 11258
MOD64=57 62 155 1289 11963
MOD64=58 59 146 1289 8994
MOD64=59 58 146 1397 10083
MOD64=60 56 155 1397 10081
MOD64=61 62 155 1397 9941
MOD64=62 59 146 1397 11712
MOD64=63 58 146 1397 10267
Die erste Spalte gibt das Modulo des Procedure-Beginns an. Die nachfolgenden Spalten beinhalten die Durchläufe auf dem 386sx16, dem 386dx25, dem 486dx4-100 und dem amd duron 750 Mhz.
Ich versuche das mal mutig zu interpretieren

:
(1) 386sx16
Der 386sx mag offensichtlich ein dword alignment. Wie schon mal geschrieben, hat mich das sehr überrascht: der 386sx holt sich den auszuführenden Code ja über einen 16-bittigen Datenbus, so dass ich ein word alignment erwartet hatte. Ursache dürfte aber sein, dass der 386sx wie der 386dx seine Prefetch-Queue immer nur dann auffüllt, wenn dort 4 byte frei sein.
(2) 386dx25
Hier gab`s für mich die nächste Überraschung. Der 386dx25 führt denselben 16bit-Real-Mode-Code fast 3 Mal so schnell aus wie der 386sx16! Ich hatte lediglich einen Faktor von 1,5 erwartet, wie es auch der Fall ist, wenn man nicht die Code-Ausführungszeit, sondern den Durchsatz von 16bit-Daten (REP STOSW) mißt. Aber Code und Daten sind zwei unterschiedliche Schuhe, zumal die einzelnen Code-Befehle auf x86 in ihrer Größe ziemlich unterschiedlich sind. Der 386dx kann sich den Code - sofern der Hauptspeicher 32-bittig angeschlossen ist - im 4-Byte-Rutsch in seine Prefetch-Queue holen, was doppelt so viel ist wie beim 386sx. Im besten Fall kann daher der 386dx den gleichen Code doppelt so schnell ausführen wie ein gleich getakter 386sx.
Ich muß hier aber dazu sagen, dass mein 386dx25 auf einem 32-bittigen MCA-Board sitzt. Ob der Speicher bei einem 16-bit ISA - Board auch 32-bittig an die CPU angeschlossen ist, weiß ich nicht.
(3) 486dx4 - 100
Der 486dx mag offensichtlich ein Paragraphen-Alignment. Als Ursache tippe ich mal darauf, dass beim 486dx eine Cacheline immer 16 byte groß ist.
Was mich immer wieder erstaunt, ist das Tempo des 486 gegenüber einem 386sx. Wenn ich mal die Best-Case-Werte vergleiche, dann schafft der 386sx 3,875 Durchläufe pro Mhz, der 386dx 6,2 Durchläufe pro Mhz und der 486dx4 13,97 Durchläufe pro Mhz. Da ist der AMD Duron mit 15,97 Durchläufe pro Mhz auch nicht viel schneller! Wenn ich mir die Worst-Case-Szenarien angucke, dann ist der 486dx4 pro Mhz sogar schneller als der AMD Duron: Der 486dx4 schafft im worst case 12,89 Durchläufe pro Mhz, während der AMD Duron nur 11,99 Durchläufe pro Mhz schafft.
(4) Duron 750
Der Duron benötigt offensichtlich ebenfalls nur eine Modulo16 - Ausrichtung. Interessant wäre zu wissen, wie der Pentium sich da verhält. Ich habe gerade gegoogelt: der Pentium hat wohl für jede seiner beiden Pipelines eine 64-Byte Cacheline. Um das Anzutesten müßte man wohl die Testprocedure 256 Mal um ein Byte im Speicher verschieben, um da ein Muster zu erkennen. Mein Programm versagt da bereits an dem Punkt!
Interessant wäre für mich, wie das Ganze auf einem 286, einem 386dx mit Standard ISA-Bus und auf einem Pentium aussieht. Beim 286er wird ja immer gesagt, dass er 286er-Code ca. um 5-10% schneller ausführt als ein gleich getakteter 386sx. Wenn das stimmt, würde ich mal raten, dass der 286er seine Prefetch-Queue word-weise auffüllt und er deswegen bei kleinen OpCodes (1-3 byte) je nach Situation die Prefetch-Queue schneller nachladen als der 386sx. Denn der muß ja immer warten, bis 4 byte frei sind...
Praktische Relevanz hat das Ganze m.E. jedoch nicht. Zum einen genügt es in der Praxis ja nicht, den Procedureanfang zu alignen. Außerdem hat man auf jeder CPU auch noch ein anderes worst/best case - Szenario: z.B. hat der 386sx bei Modulo64=60 ein worst case, der 386dx dagegen hat dort genau ein best case usw. In einer praktischen Umsetzung würde man (jedenfalls ich) wahrscheinlich mehr verschlimmern als verbessern.