Apple M1 - Mythen, Mutmaßungen und warum x86 doch (nicht?) am Ende ist! (Teil 1)

Geöffnet als Baustelle! ;) Umbauarbeiten erfolgen noch über einige Bereiche!
Bild von Apple.com.

Als Apple vor knapp einem halben Jahr den M1 vorstellte, war man auf der einen Seite erstaunt und doch kam das, was man erwarten konnte, denn es hat sich in Gerüchten bereits seit einigen Jahren angekündigt und vor allem: ARMv8 hat dazu auch durchaus das Potenzial gehabt.


Natürlich gibt es so einige Versuche ARM auch auf dem PC fit zu bekommen - unter anderem auch der Qualcom 8CX - und auch seit einigen Jahren gibt es Versuche im Serverbereich, die aber bisher an der dann doch eher bescheidenen Leistung und ebenso auch an dem fehlenden Softwaresupport scheitern. Erst der M1 zeigte in verschiedenen Tests, dass ARM-Kerne es durchaus auch mit ihren modernen x86-Gegenstücken aufnehmen können und diese gar übertreffen können, was natürlich - wie könnte es anders sein - zu Abwehrreaktionen führt und manche Journalisten dazu bewegt allen Kollegen kollektives Versagen beim Tests zu bescheinigen. Dabei gibt es aber immer noch Probleme für ARM, nämlich immer noch den Softwaresupport. Zwar wird an virtuellen Maschinen (VM) gearbeitet und Parallels unterstützt den M1 auch, aber es gibt eben noch viele Baustellen, gerne den verlinkten Artikel von Golem lesen.


In diesem Artikel möchte ich - bevor ich auf meine allgemeine Erklärung kommen - auf Gastbeitrag bei Igorslab eingehen, Ausgangspunkt ist dabei ein Beitrag bei Computerbase von mir. Kurztenor: Der Gastautor bei Igorslab macht sich lächerlich, weil man nach einem Strohhalm greift um das alte Weltbild - ARM effizient aber langsam und x86 sehr schnell - beibehalten zu können.

Single-Core-Performance - nur 1 Thread ist unfair! - Oder doch nicht?

Normalerweise wäre ich erst auf ein paar technische Eigenheiten von ARM und x86 eingegangen, hätte die grundlegenden Überlegungen versucht darzustellen und hätte euch anschließend erläutert, warum die IPC bei Apples Firestorm-Kernen so hoch ist und welche Fallstricke bei x86 herrschen und warum man dort teilweise über andere Aspekte gehen muss. Fangen wir aber mal mit dem Thema Performance an und wie man heute die Leistungsfähigkeit eines Prozessors bestimmt.


Wenn ihr Tests auf verschiedenen Webseiten lest, gibt es in der Regel zwei Begriffe, die einem sofort ins Gesicht springen: Single-Core-Performance und Multie-Core-Performance. Mit beiden Begriffen versucht man die Leistungsfähigkeit heutiger Prozessoren auszudrücken, die dabei auf verschiedene Szenarien zielt und genau hier fängt das Dilemma auch mit dem Beitrag von Herrn Prizada an. Seine Grundaussage ist - vereinfacht dargestellt - das alle Single-Core-Tests x86-Kerne benachteiligen, weil diese nur mit 1-Thread getestet werden, obwohl dieser zwei Threads verarbeiten kann und die Kerne daher auch mehr leisten, als ein Firestorm-Kern im M1. Die zweite Aussage ist, dass moderne x86-Kerne ja mit einem Thread unterfordert sind, während der Firestorm-Kern bereits am Ende wäre. Beide Aussagen sind in dieser Form pauschal und damit eigentlich auch falsch.


Dazu kommt, dass der Journalist eine Möglichkeit überhaupt nicht erwähnt oder in Betracht gezogen hat: Wird nicht einfach die falsche Begrifflichkeit verwendet für den Test? Und genau das ist hier nun der Knackpunkt, auf den ich kurz eingehen möchte, bevor wir auf die weiteren Punkte zum M1 gehe. Wir lesen seit geraumer Zeit, dass zum Beispiel für Spiele die Single-Core-Performance wichtig ist, nur warum ist bei Spielen die Single-Core-Performance so wichtig? Das hat unter Windows etwas mit DirectX 11 und den Vorgängerschnittstellen zu tun und wie diese arbeiten: Es gibt unter DX11-Spielen einen Haupt-Render-Thread, der die Anweisungen an den Treiber schickt, der diese Anweisungen anschließend an die GPU weiter gibt. Je schneller dieser Thread ausgeführt wird, um so mehr Bilder kann die CPU zur Grafikkarte schicken. Für Spiele, gerade pre-DX12, ist es also vollkommen irrelevant, ob ein x86-Core 1 oder 2 Threads ausführen kann, sondern entscheidend ist, dass der Main-Render-Thread entsprechend schnell ausgeführt wird, das erste Indiz.


Für die meisten Leser - noch - hier gibt es aber ein noch viel greifbareres Beispiel: PHP. PHP bietet zurzeit keine wirkliche asynchrone Ausführung und auch keine Möglichkeit mehrere Threads zu verwenden für ein CMS - es gibt entsprechend Erweiterung, ich weiß! Für uns alle ist es daher entscheidend, wie schnell wird das CMS als ganzes ausgeführt und wenn ein Besucher meine Seite ansteuert, wird ein PHP-Prozess gestartet, der dann das Skript ausführt und das Ergebnis über den Server zurückgibt und es gibt hier nun zwei Werte, mit der Wir an der Stelle nun Indiz Zwei und Drei haben: Für die heute wichtige Response-Time und für den Flow der Webseite ist es wichtig, wie schnell der PHP-Thread ausgeführt wird. Es ist irrelevant, ob noch ein zweiter Thread auf dem Kern parallel laufen kann, sondern es ist wichtig, dass die Seite so schnell wie möglich gerendert und an den Browser übermittelt wird. Indiz Nummer 2. Für einen Webserver daneben wiederum ist relevant, wie viele Anfragen er parallel beantworten kann und da kommen wir nun zum Indiz Nummer 3: Es kommt darauf an, welcher Webserver am Laufen ist. Es gibt Webserver, die arbeiten mit einem Thread, andere können mehrere aufmachen, aber auch hier: Für die Antwort an den Nutzern ist die Leistung eines Threads relevant, wenn es aber darum geht möglichst viele Anfragen zu bedienen, ist neben der Laufzeit des einzelnen Threads auch die Anzahl der möglichen Threads relevant, die parallel ausgeführt werden können. Oder anders ausgedrückt: für mich als Entwickler, aber auch für euch als Anwender gibt es die Leistung bei 1-T und eben n-T.


Auch wenn die Punkte von Herrn Prizada im ersten Augenblick nachvollziehbar sind und logisch erscheinen, geht es bei den meisten Single-Core-Performance-Messungen darum, wie schnell 1-T ausgeführt wird, nicht darum, was der Kern theoretisch mit zwei oder mehr Threads leisten könnte. Es wird einfach nur der falsche Begriff verwendet.


Das soll es an dieser Stelle zu dem Thema auch im Ganzen gewesen sein, es wird aber durchaus noch ein paar Seitenhiebe auf den Journalisten geben, das sei mir aber verziehen.

Wie Leistungsfähig ist denn der M1 eigentlich?

Da ich aktuell leider noch kein neues MacBookPro habe, bin ich auf die Tests von anderen Seiten angewiesen, ich werde an dieser von Golem.de und andere Seiten einzelne Benchmarks aufnehmen und auch kurz darauf eingehen, aber um im weiteren Verlauf wirklich auch Zahlen zu haben, hier einmal die Übersicht:


Golem.de - Cinebench R23 - Single Threaded:

CPU Score Takt Bemerkung
Apple M1
1508 3,2 GHz
Nativ ausgeführt - 10 Watt
Apple M1
986 3,2 GHz
Rosetta 2
Core i7 - 1185G7
1547 4,8 GHz
28 Watt → maximaler Turbo von 4,8 GHz angenommen.
Core i7 - 1185G7
1330 4,1 GHz
15 Watt → Wert von 4,3 GHz stammt aus einer News von Computerbase.


Golem.de - Cinebench R23 - Multi Threaded

CPU Score Takt Bemerkung
Apple M1
7641 3,2 GHz + 2,06 GHz
FireStorm und IceStorm werden beide wohl arbeiten. - ca.10 Watt
Apple M1
4972 3,2 GHz + 2,06 GHz
Rosetta 2
Core i7 - 1185G7
6258 2,8 GHz - 4,3 GHz
Basis und All-Core.


Ich habe an dieser Stelle die Werte mit Rosetta 2 mit angegeben, weil diese durchaus interessant sind, wir sehen an der Stelle am Cinebench recht gut, dass ein FireStorm-Kern mit den aktuellen WillowCove-Kernen von Intel mit halten kann. Ohne Taktnormierung, beträgt der Vorsprung des Core i7 2,5 %. Geht man nun davon aus, das 3,2 GHz wirklich 10 Watt im Apple M1 verbraten und der Core i7 die 28 Watt, dann stehen hier 280 % mehr Verbrauch auf der Uhr für nur 2,5 % Leistung. Aber da ich das alles nicht direkt nachprüfen kann: Milchmädchenrechnung.


Interessanter ist hier schon eher die Leistung pro GHz: 471 Punkte gegen 322 Punkte oder in Prozent: Der M1 leistet pro GHz ganze 46 % mehr. Beeindruckend. An dieser Stelle verweise ich nun auf den Herrn Prizada und seiner Argumentation zur Single-Core-Performance und den Hinweis auf Intels HyperThreading. HT steigert laut Intel im Schnitt die Leistung um 10 - 20 % und bei hoch optimierten Programmen auch mal um 33 %. AMDs SMT gilt allgemein als etwas besser als Intels SMT und auch hier kann je nach Szenario deutlich mehr bringen, aber eben auch Leistung kosten, weil zwei Threads um die Ressourcen kämpfen. Nimmt man Werte von Anandtech, stehen zwar bis zu 76 % auf der Uhr, im Mittel sind es aber 25 %. Streichen wir das beste und schlechteste Ergebnis, kommen wir auf 118 %. Nehmen wir diese 18 % - was sich auch mit dem SMT-Tests bei Anandtech deckt zu Cinebench - dann würde der Core i7 ca. 1825 Punkte erreichen, macht dann Takt normiert 380 Punkte pro GHz und der M1 würde immer noch ganze 23 % vorne sein. Klar, es ist nun eine theoretische Betrachtung, ich habe beide Geräte nicht zur Hand, doch wir sehen auch an dieser Stelle, dass selbst SMT Intels CPU nicht retten kann und die IPC immer noch ein gutes Stück zurückliegt.


Bei den Multi-Threaded ist SMT natürlich auf der Intel CPU aktiviert und wir kommen einmal auf 7641 bei 8 Kernen und 6258 bei 8T auf 4 Kernen. An dieser Stelle wird es aber schwer: Da eine genaue Taktangabe fehlt - wie gerne hätte ich beide Geräte jetzt zum Prüfen - muss man hier nun raten, welcher Takt anlag, da Intel jedoch mit ihren ganzen Modi zum kurzzeitigen Überschreiten der TDP wirbt, nehmen wir einfach die 4,3 GHz und wir tun so, als wäre beim M1 alles Firestorm-Kerne. Der M1 kommt damit auf ca. 298 Punkte pro Kern und der Intel Core i7 auf 364 Punkte und damit liegt M1 nun ca. 19 % zurück oder der i7 22 % bei der IPC in Front. Natürlich ist das stark vereinfacht und in dem Fall zuungunsten des M1, es ist aber der einfachste Rechenweg und der i7 steht damit sogar sehr gut da, wäre da nicht die TDP von 28 W und eben die 10 W für den M1. Nehmen wir die Punkte pro Watt, kommen wir einmal auf 764 und eben auf 224: 447 %. 1T wären es 151 gegen 55 und damit ganze 274 % und selbst wenn wir die 18 % SMT einrechnen, stehen 151 gegen 65 Punkte und damit 232 % mehr Leistung beim M1.


Natürlich bin ich ein Freund von Tabellen aller Werte:

M1 Punkte/Ghz
Core i7 Punkte/GHz
Delta M1 Punkte/Watt
Core i7 Punkte/Watt
Delta
Bemerkung
471 322 46 %
151 55 274 %
1T - Ohne SMT-Bonus
471 380 23 %
151 65 232 %
1T - Mit SMT-Bonus
298 364 - 19 %
764 224 341 %
nT


Um noch einmal darauf hinzuweisen: Ich habe nun nur die TPD genommen als Ausgangspunkt und die Zahlen sind damit auf jeden Fall angreifbar, bitte verwendet die Zahlen daher in Diskussionen mit der gebotenen Vorsicht, am besten gar nicht!


Wir sehen aber anhand der Tabellen, dass der M1 durchaus ein sehr leistungsfähiger Prozessor ist und dass Apple hier ein ARM-Design hat, dass es sehr wohl mit den aktuell größten Kernen von AMD und Intel aufnehmen kann. Eine mehr als beeindruckende Leistung. Aber woran liegt das?

Warum ist der M1 so schnell? Kann Intel und AMD das nicht auch?

Gehen wir erst mal auf die zweite Frage ein: Ja, Intel und AMD können das theoretisch auch, denn die Rezepte sind relativ einfach: breites Frontend, breites Backend. Apple den FireStorm-Kern 6-fach Skalar ausgelegt, heutige AMD und Intel-Prozessoren sind 4-fach Skalar ausgelegt. Das bedeutet, dass im Backend 6 Rechenwerke vorhanden sind, die 6 Befehle zur gleichen Zeit ausführen können, man nennt das ganze auch Superskalarität. Auf kleine Besonderheiten - wie ein eigenes Rechenwerk für Divisionen - gehe ich an der Stelle nicht ein, denn dann wird das Erklären sehr komplex und auch schnell unverständlich, wir bleiben bei den 6 Rechenwerken und im groben könnt ihr es euch so vorstellen:

Apple M1 - Firestorm Backend (Vereinfacht) / Bild von Teralios.de


Im Bereich Dispatch werden die Befehle, die die CPU ausführen soll, gesammelt und auch umsortiert, anschließend gehen die Befehle weiter in den Block für die Register und werden um von Dort die Daten mit zu den 6 darauf folgenden Rechenwerken mitzunehmen und genau hier liegt das erste Geheimnis, warum der Apple M1 so schnell ist und quasi 40 % IPC schafft als aktuelle Intel CPUs, denn aktuelle Willow Cove Kerne sehen ca. so aus:


Vereinfachtes Zen3 Backend. / <span class="icon fa-creative-commons"></span> Bild von Teralios.de


Fällt euch was auf? Natürlich fallen sofort die zwei fehlenden Rechenwerke auf, denn Intel und AMD CPUs arbeiten aktuell in der Regel 4-fach skalar, nicht 6-fach. Somit kann ein M1-Prozessor 50 % mehr Befehle gleichzeitig ausführen und äußert sich aktuell in ca. 40 % mehr IPC, was kein so schlechter Schnitt ist.


Natürlich kann ich mir einen kleinen Seitenhieb auf Igorslab an dieser Stelle nicht verkneifen, dort wird nämlich als nächstes Argument angebracht - für SMT - das Apple ja keine Schwierigkeiten hat das Backend auszulasten, während moderne x86 ja SMT brauchen um ihr Backend auszulasten, sehen wir uns das Backend an, dann sehen wir aber, dass Apples Backend breiter ist und man daher hier theoretisch noch schwerer hat das Backend auszulasten, 6 ALUs benötigen mehr Befehle und mehr Daten als 4 ALUs. Die Frage ist also, wie es Apple schafft das Backend besser auslasten?


Nun, auch hier ist die Antwort ganz einfach und wird durch dieses Bild veranschaulicht:


Links das Backend des Zen 3, Rechts vom Firestorm. / Bild von Teralios.de

Links zu sehen ist - stark vereinfacht - der Decoder der aktuellen x86-CPUs, rechts der des Firestorms. Die aktuellen Decoder von Intel und AMD CPUs liefern 4 Befehle pro Takt und damit genau so viele Befehle wie ALUs vorhanden sind, der Firestorm-Decoder decodiert 8 Befehle pro Takt und damit 2 mehr als ALUs vorhanden sind. Natürlich ist das an dieser Stelle stark vereinfacht, denn ich habe euch bisher noch die FPUs unterschlagen und noch etwas anderes, aber da wollen wir auch noch mal gesondert drauf eingehen, zuerst einmal die FPUs beider CPUs:


Zeigt das FPU-Backend eines Zen 3 und eines Firestorm. Im Text sind die Werte für aktuelle Willowcoves-Kerne genannt (AVX512). / Bild von Teralios.de


Wie auch im vorherigen Bild, Willow Cove ist Links, der Firestorm von Apple rechts: Bei heutigen x86-Kernen haben wir in der Regel 2 Vektor-ALUs 256/512 Bit - je nachdem ob nur AVX2 (bis Zen3) oder schon AVX512 (Intel) unterstützt werden. Apple setzt auf 4 128 Bit ALUs aus ARMs Neon-Extension. Die theoretische Rechenleistung der Intel CPU ist an dieser Stelle doppelt so hoch, da 1024 Bit verarbeitet werden können, beim M1 nur 512 Bit. Die einfache Formel hier ist: Anzahl der Werte * Operationen pro Takt * Takt, eine genauere Erklärung liefer ich im Artikel zum Kommentar der GameStar. Bei 32 Bit pro Wert, verarbeitet eine moderne Intel CPU 32 Werte, der M1 nur 16 Werte. Die Operation, die zwei Opertationen verbindet ist das MAD/MAC (Multiplikation + Addition), damit kommen wir - bei 1 GHz - auf einmal 64 GFLOP/s und eben auf 32 GFLOP/s - theoretisch. Da ich an dieser Stelle nicht auf Vektoren eingehen will und deren Probleme, will ich nur anmerken: Breite Vektoren sind schwerer zu füllen als kleine.


Wir kommen bei Intel nun auf 4 Befehle für 6 ALUs und auf 8 Befehle für 10 ALUs bei Apple und so ist das Verhältnis Befehle zu ALUs mit 0,66 zu 0,80 für Apple besser und damit sehen wir auch: Ja Apple kann sein Backend besser auslasten.