Ich habe ein kleines C++ - Programm, das mit MSVC v140 kompiliert wurde, zerlegt und versuche die Zyklen pro Anweisung zu schätzen, um besser zu verstehen, wie Code-Design die Leistung beeinflusst. Ich habe Mike Actons CppCon 2014 Talk auf "Data-Oriented Design and C++" verfolgt, speziell den Teil, den ich verlinkt habe.Schätzung der Zyklen pro Anweisung
Darin weist er diese Zeilen aus:
movss 8(%rbx), %xmm1
movss 12(%rbx), %xmm0
Er behauptet dann, dass diese 2 x 32-Bit liest sind wahrscheinlich auf der gleichen Cache-Zeile kostet damit in etwa ~ 200 Zyklen.
Die Intel 64 and IA-32 Architectures Optimization Reference Manual war eine große Ressource, insbesondere "Anhang C - Befehlswartezeit und Durchsatz". Allerdings auf Seite C-15 in "Tabelle C-16. Streaming SIMD Extension Gleitkomma-Anweisungen mit einfacher Genauigkeit" es besagt, dass Movss ist nur 1 Zyklus (es sei denn, ich verstehe, was Latenz bedeutet hier falsch ... Wenn ja, wie lese ich dieses Ding?)
Ich weiß, dass ein theoretical prediction of execution time nie richtig sein wird, aber dennoch ist dies wichtig zu lernen. Wie lauten diese beiden Befehle 200 Zyklen, und wie kann ich lernen, über die Ausführungszeit hinauszugehen, die über dieses Snippet hinausgeht?
Ich habe begonnen, einige Dinge über CPU-Pipelining zu lesen ... vielleicht wird die Mehrheit der Zyklen dort abgeholt?
PS: Ich bin nicht daran interessiert, Hardware Leistungsindikatoren hier zu messen. Ich suche nur, wie man vernünftige Sicht ASM und Zyklen liest.
Haben Sie sich Agner Fogs Arbeit angesehen? http://www.agner.org/optimize/instruction_tables.pdf –
Sie können keine Zyklen mehr zählen. nicht für eine lange Zeit jetzt. Pipelining, Caches, Branch Prädiktion, etc ... Pipelining ist nur ein Fließband wie in einer Fabrik. Sie können 117 Schritte oder Stationen haben, um eine Sache zu bauen, und jeder kann 30 Sekunden dauern, aber das bedeutet, dass Sie theoretisch alle 30 Sekunden einen Artikel produzieren können, nicht einen pro Stunde wegen der Produktionslinie. So schnell kommen sie aus dem Backend heraus. –
Die meisten, wenn nicht alle Befehle eine Uhr zur Ausführung benötigen, können 15 bis 1000 Takte benötigen, um Cache-Misses zu relativ langsamem Dram zu holen, und alle anderen Schritte sin die Pipeline, aber sobald alle Eingaben an der Ausführungseinheit vorhanden sind, es braucht dann eine Uhr für diesen einen Schritt in der Pipeline. Dann all die Dinge, die folgt, speichern die Ergebnisse in Registern oder langsamen Speicher, etc. –