Bei einem bestimmten Computersystem ist es möglich, die tatsächliche genaue Laufzeit eines Assembly-Codes zu schätzen

23

Dies ist ein Teil des Assembly-Codes

section .text
    global _start       ;must be declared for using gcc
_start:                     ;tell linker entry point
    mov edx, len    ;message length
    mov ecx, msg    ;message to write
    mov ebx, 1      ;file descriptor (stdout)
    mov eax, 4      ;system call number (sys_write)
    int 0x80        ;call kernel
    mov eax, 1      ;system call number (sys_exit)
    int 0x80        ;call kernel

section .data

msg db  'Hello, world!',0xa ;our dear string
len equ $ - msg         ;length of our dear string

Bei einem bestimmten Computersystem ist es möglich, die tatsächliche Laufzeit eines Assembly-Codes genau vorherzusagen.

yaojp
quelle
30
Ist "Code auf diesem Computer ausführen und Stoppuhr verwenden" eine gültige Antwort?
Draconis
4
Ich vermute, dass die meiste Zeit, die für die Ausführung dieses Codeteils aufgewendet wird, auf die Eingabe / Ausgabe wartet. Die Zeit, die für die Ausführung der einzelnen Anweisungen benötigt wird, ist einigermaßen vorhersehbar, wenn Sie den Speicherort des Codes und alle Details des Prozessors (die heutzutage äußerst komplex sind) kennen. Die Geschwindigkeit wird jedoch auch vom Speicher und der Festplatte beeinflusst. Ich muss auch eine Menge Details über sie wissen. Wenn Sie also nicht physikalische Phänomene berücksichtigen (die sich auch auf die Zeit auswirken), können Sie sagen, dass dies vorhersehbar, aber unvorstellbar schwierig ist.
IllidanS4 will, dass Monica
4
sudo rm -rf slash
3
Ist das nicht auch wegen des Halteproblems unmöglich? Wir können für einige Codes nachweisen, ob sie anhalten, aber wir können keinen Algorithmus haben, der dies für alle möglichen Codes bestimmt.
kutschkem
2
@ Falco Das wäre eine Eigenschaft des gegebenen Systems. Einige freistehende C-Implementierungen haben kein Betriebssystem. alles, was läuft, ist eine Hauptschleife (oder nicht einmal eine Schleife ;-)), die von Hardware-Adressen zur Eingabe lesen kann oder auch nicht.
Peter - Setzen Sie Monica

Antworten:

47

Ich kann nur aus dem Handbuch einer eher primitiven CPU, eines 68020-Prozessors aus der Zeit um 1986, zitieren: "Die exakte Berechnung der Laufzeit einer Befehlsfolge ist schwierig, auch wenn Sie genaue Kenntnisse über die Prozessorimplementierung haben." Was wir nicht haben. Und im Vergleich zu einem modernen Prozessor war diese CPU primitiv .

Ich kann die Laufzeit dieses Codes nicht vorhersagen, und Sie können es auch nicht. Aber Sie können nicht einmal definieren, was "Laufzeit" eines Codeteils ist, wenn ein Prozessor über massive Caches und massive Funktionen für fehlerhafte Reihenfolge verfügt. Ein typischer moderner Prozessor kann 200 Anweisungen "im Flug" haben, dh in verschiedenen Phasen der Ausführung. Die Zeit vom Versuch, das erste Befehlsbyte zu lesen, bis zur Beendigung des letzten Befehls kann also ziemlich lang sein. Die tatsächliche Verzögerung für alle anderen Arbeiten, die der Prozessor ausführen muss, ist jedoch möglicherweise (und in der Regel) viel geringer.

Durch zwei Aufrufe des Betriebssystems ist dies natürlich völlig unvorhersehbar. Sie wissen nicht, was "Schreiben an stdout" tatsächlich bewirkt, daher können Sie die Zeit nicht vorhersagen.

Und Sie können die Taktrate des Computers nicht genau in dem Moment kennen, in dem Sie den Code ausführen. Es kann sein, dass sich der Computer in einem Energiesparmodus befindet und die Taktrate aufgrund der Hitze verringert ist, sodass selbst die gleiche Anzahl von Taktzyklen unterschiedlich viel Zeit in Anspruch nehmen kann.

Alles in allem: Völlig unvorhersehbar.

gnasher729
quelle
11
Ich denke, Ihre Schlussfolgerungen sind zu stark. Latenz und Durchsatz sind gängige Messgrößen zur Messung der "Laufzeit" eines Programms. Sie können sich auch einfach auf eine geeignete Definition von "Laufzeit" festlegen. Darüber hinaus können Sie die Laufzeit vorhersagen, wenn Sie eine vollständige Momentaufnahme des Systemzustands (hw und sw) und eine perfekte Kenntnis der CPU-Interna haben. Bei Intel können sie wahrscheinlich die Laufzeit abschätzen, auch hier können wir Latenzen und Tputs zyklusgenau vorhersagen. In diesem Fall ist es, abgesehen von den Systemanrufen, nicht einmal so schwer.
Margaret Bloom
9
@MargaretBloom auch dann nicht. Ich stelle mein Handy zu nahe an den Ofen, die CPU ist zu schwach, um die Temperatur zu regeln, Ihre Laufzeitschätzung ist plötzlich zu niedrig. Und selbst wenn Sie in Zyklen zählen und keine Systemaufrufe durchführen, können andere Threads und CPUs mit dem RAM-Inhalt gut umgehen oder Ihren Speicher auf der Festplatte ablegen, während Sie aufgrund unvorhersehbarer Umstände, die von der Stromversorgung abhängen, ausgelagert werden Spannungsspitzen, die die Festplatte gerade so stark verlangsamen, dass ein konkurrierender Thread rechtzeitig genug Speicher erhält, um Ihren zu zerstören, bis hin zu Threads, die gerade Würfel rollen, um zu sehen, wie viel Zeit verschwendet werden muss.
John Dvorak
6
Außerdem ist "vollständige Kenntnis des Systemzustands, hw und sw" eine ziemlich große Aufgabe, meint. Fügen Sie "10 ms im Voraus" hinzu, und Sie fragen bereits nach dem Unmöglichen. Und wenn Ihre CPU bei der Implementierung der Hardware-Zufallszahlengenerierung Quantenphänomene verwendet (was wahrscheinlich der Fall ist) und ein Thread auf der CPU dies aufruft, können Sie nicht einmal den vollständigen Zustand des Universums 3000 km um den Computer herum kennen. Und in MWI kann man nicht einmal richtig raten.
John Dvorak
8
@Nat: Auch in der Kryptographie „constant-time“ nicht wirklich bedeuten , absolut konstant - es ist nur bedeutet , dass die Laufzeit keine systematischen Variationen hat , die auf geheime Daten abhängen und statistisch mit ihm in Beziehung gesetzt werden konnte. In der Praxis wird häufig nur davon ausgegangen, dass der verwendete Codepfad und das Muster der ausgeführten Speicherzugriffe nicht von geheimen Daten abhängen und dass bestimmte Anweisungen, von denen bekannt ist, dass sie eine variable Zeitdauer benötigen, vermieden werden (oder deren Eingaben maskiert werden) hoffentlich die Korrelation beseitigen), ist es wahrscheinlich gut genug. Darüber hinaus muss man es wirklich nur messen.
Ilmari Karonen
2
Ein 68020 ist ein komplexes Biest ... versuchen Sie es mit einem MCS51 ...
Rackandboneman
29

Sie können dies im Allgemeinen nicht tun, aber in gewisser Hinsicht können Sie sehr viel, und es gab einige historische Fälle, in denen Sie tatsächlich mussten .

Der Atari 2600 (oder Atari Video Computer System) war eines der frühesten Heimvideospielsysteme und wurde erstmals 1978 veröffentlicht. Im Gegensatz zu späteren Systemen der damaligen Zeit konnte Atari es sich nicht leisten, dem Gerät einen Bildpuffer zu geben, was bedeutet, dass die CPU dies hatte Code an jeder Scanlinie ausführen, um zu bestimmen, was zu produzieren ist - wenn dieser Code mehr als 17,08 Mikrosekunden zum Ausführen benötigt (das HBlank-Intervall), werden die Grafiken nicht richtig eingestellt, bevor die Scanlinie mit dem Zeichnen beginnt. Schlimmer noch, wenn der Programmierer komplexere Inhalte zeichnen wollte, als es der Atari normalerweise zuließ, musste er die genauen Zeiten für Anweisungen messen und die Grafikregister während des Zeichnens des Strahls mit einer Zeitspanne von 57,29 Mikrosekunden für die gesamte Scanlinie ändern.

Der Atari 2600 hatte jedoch wie viele andere Systeme auf Basis des 6502 eine sehr wichtige Funktion, die ein sorgfältiges Zeitmanagement ermöglichte, das für dieses Szenario erforderlich war: Die CPU, der RAM und das TV-Signal liefen alle mit Uhren, die auf demselben Master basierten Uhr. Das TV-Signal lief von einem 3,98-MHz-Takt ab, wobei die obigen Zeiten in eine ganze Zahl von "Farbtakten" aufgeteilt wurden, die das TV-Signal handhabten, und ein Zyklus der CPU- und RAM-Takte bestand aus genau drei Farbtakten, so dass der CPU-Takt erhalten blieb ein genaues Zeitmaß in Bezug auf das aktuelle TV-Fortschrittssignal. (Weitere Informationen hierzu finden Sie im Stella-Programmierhandbuch , das für den Emulator Stella Atari 2600 geschrieben wurde. )

Diese Betriebsumgebung bedeutete außerdem, dass jeder CPU-Befehl in jedem Fall eine bestimmte Anzahl von Zyklen benötigte, und viele 6502-Entwickler veröffentlichten diese Informationen in Referenztabellen. Betrachten Sie zum Beispiel diesen Eintrag für die CMPAnweisung (Speicher mit Akku vergleichen) aus der folgenden Tabelle :

CMP  Compare Memory with Accumulator

     A - M                            N Z C I D V
                                    + + + - - -

     addressing    assembler    opc  bytes  cycles
     --------------------------------------------
     immediate     CMP #oper     C9    2     2
     zeropage      CMP oper      C5    2     3
     zeropage,X    CMP oper,X    D5    2     4
     absolute      CMP oper      CD    3     4
     absolute,X    CMP oper,X    DD    3     4*
     absolute,Y    CMP oper,Y    D9    3     4*
     (indirect,X)  CMP (oper,X)  C1    2     6
     (indirect),Y  CMP (oper),Y  D1    2     5*

*  add 1 to cycles if page boundary is crossed

Mit all diesen Informationen konnten Atari 2600 (und andere 6502-Entwickler) genau bestimmen, wie lange die Ausführung ihres Codes dauerte, und Routinen erstellen, die genau das taten, was sie brauchten und dennoch die Timing-Anforderungen des Atari für TV-Signale erfüllten. Und weil dieses Timing so genau war (insbesondere für zeitraubende Anweisungen wie NOP), konnten sie es sogar verwenden, um die Grafiken beim Zeichnen zu ändern.


Natürlich ist der 6502 des Atari ein sehr spezieller Fall, und all dies ist nur möglich, weil das System über Folgendes verfügt:

  • Eine Hauptuhr, die alles lief, einschließlich RAM. Moderne Systeme haben unabhängige Takte für die CPU und den RAM, wobei der RAM-Takt oft langsamer ist und die beiden nicht unbedingt synchron sind.
  • Kein Caching jeglicher Art - der 6502 hat immer direkt auf DRAM zugegriffen. Moderne Systeme verfügen über SRAM-Caches, die die Vorhersage des Zustands erschweren. Das Verhalten eines Systems mit einem Cache lässt sich zwar noch vorhersagen, es ist jedoch definitiv schwieriger.
  • Keine anderen Programme laufen gleichzeitig - das Programm auf der Kassette hatte die vollständige Kontrolle über das System. Moderne Systeme führen mehrere Programme gleichzeitig mit nicht deterministischen Planungsalgorithmen aus.
  • Eine Taktrate, die langsam genug ist, damit die Signale rechtzeitig über das System übertragen werden können. Bei einem modernen System mit einer Taktrate von 4 GHz (zum Beispiel) benötigt ein Photon von Licht 6,67 Taktzyklen , um die Länge eines Motherboards von einem halben Meter zu erreichen. Man könnte nicht erwarten, dass ein moderner Prozessor mit etwas anderem auf dem Board interagiert in nur einem Zyklus, da es mehr als einen Zyklus dauert, bis ein Signal auf der Platine das Gerät erreicht.
  • Eine gut definierte Taktrate, die sich selten ändert (1,19 MHz im Fall des Atari) - die CPU-Geschwindigkeiten moderner Systeme ändern sich ständig, während ein Atari dies nicht tun könnte, ohne auch das TV-Signal zu beeinflussen.
  • Veröffentlichte Zykluszeiten - Der x86 definiert nicht, wie lange eine seiner Anweisungen dauert.

All diese Dinge haben sich zu einem System zusammengeschlossen, in dem es möglich war, Anweisungen zu erstellen, die genau so viel Zeit in Anspruch nahmen - und für diese Anwendung war genau das erforderlich. Die meisten Systeme verfügen nicht über diese Genauigkeit, nur weil sie nicht benötigt werden. Berechnungen werden entweder ausgeführt, wenn sie ausgeführt werden, oder wenn eine genaue Zeitdauer erforderlich ist, kann eine unabhängige Uhr abgefragt werden. Wenn die Anforderungen jedoch erfüllt sind (z. B. auf einigen eingebetteten Systemen), wird dies möglicherweise weiterhin angezeigt, und Sie können genau bestimmen, wie lange der Code in diesen Umgebungen ausgeführt werden muss.


Und ich möchte noch den großen, massiven Haftungsausschluss hinzufügen, dass all dies nur für die Erstellung einer Reihe von Montageanleitungen gilt, die eine genaue Zeitspanne in Anspruch nehmen. Wenn das, was wollen Sie einige beliebige Stück Montage tun nehmen, auch in diesen Umgebungen und fragen : „Wie lange dauert diese nehmen ausführen“ können Sie kategorisch das nicht tun - das ist das ist Halting Problem , das unlösbare bewiesen wurde.


EDIT 1: In einer früheren Version dieser Antwort gab ich an, dass der Atari 2600 keine Möglichkeit hatte, den Prozessor darüber zu informieren, wo er sich im TV-Signal befand, was ihn zwang, das gesamte Programm von Anfang an gezählt und synchronisiert zu halten. Wie in den Kommentaren erwähnt, gilt dies für einige Systeme wie das ZX Spectrum, nicht jedoch für das Atari 2600, da es ein Hardware-Register enthält, das die CPU anhält, bis das nächste horizontale Austastintervall auftritt eine Funktion, um das vertikale Austastintervall nach Belieben zu starten. Daher ist das Problem des Zählens von Zyklen auf jede Scanlinie beschränkt und wird nur dann genau, wenn der Entwickler den Inhalt ändern möchte, während die Scanlinie gezeichnet wird.

Der Hansinator
quelle
3
Es sollte auch beachtet werden, dass die meisten Spiele nicht perfekt funktionierten - Sie konnten viele Artefakte in der Videoausgabe sehen, weil das Timing des Videosignals nicht übereinstimmte, entweder aufgrund eines Programmierfehlers (falsche Schätzung des CPU-Timings) oder einfach zu viel Arbeit zu tun. Es war auch sehr zerbrechlich - wenn Sie einen Fehler beheben oder neue Funktionen hinzufügen mussten, brachen Sie sehr wahrscheinlich das Timing, manchmal unvermeidlich. Es hat Spaß gemacht, war aber auch ein Albtraum :) Ich bin mir nicht mal sicher, ob die Taktrate immer genau stimmte - z. B. bei Überhitzung, Störungen usw. Aber es zeigt definitiv, dass es selbst dann schwer war.
Luaan,
1
Gute Antwort, obwohl ich nicht erwähnen möchte, dass Sie nicht die Anzahl der Zyklen für jede Anweisung auf dem Atari 2600 zählen müssen. Es gibt zwei Funktionen, die Ihnen dabei helfen, dies nicht zu tun: Einen Countdown-Timer, den Sie initialisieren und Dann wird abgefragt, ob der Wert 0 erreicht hat, und ein Register, das die CPU anhält, bis die nächste horizontale Austastung beginnt. Bei vielen anderen Geräten, wie dem ZX Spectrum, gibt es so etwas nicht, und Sie müssen tatsächlich jeden einzelnen Zyklus zählen, der nach der vertikalen Austastunterbrechung verbracht wurde, um zu wissen, wo Sie sich auf dem Bildschirm befinden.
Martin Vilcans
1
Ich würde argumentieren, dass das Halting-Problem nicht ausschließlich für den Atari gilt. Wenn Sie die E / A-Funktionen des Atari ausschließen und auf ein typisches Cartridge-ROM beschränken, ist der Speicher begrenzt. Zu welchem ​​Zeitpunkt haben Sie eine endliche Zustandsmaschine, so dass jedes Programm darauf entweder anhalten muss oder einen Zustand eingeben muss, den es zuvor eingegeben hat, was zu einer beweisbaren Endlosschleife in endlicher Zeit führt.
user1937198
1
@ user1937198 128 Byte Status (plus was auch immer in den Registern enthalten ist) sind MEHR als ausreichend Statusraum, um den Unterschied zwischen diesem und dem theoretischen Endlosband der Turing-Maschine zu einer Unterscheidung zu machen, die nur theoretisch von Bedeutung ist. Verdammt, wir können praktisch nicht die 128 BITS eines AES-Schlüssels durchsuchen ... Der Zustandsraum wächst beängstigend schnell, wenn Sie Bits hinzufügen. Vergessen Sie nicht, dass das Äquivalent von 'Interrupts deaktivieren; halt 'wäre mit ziemlicher sicherheit möglich gewesen.
Dan Mills
1
"Das ist das Halteproblem, das sich als unlösbar erwiesen hat. Wenn Sie darauf stoßen, müssen Sie die Stoppuhr ausbrechen und Ihren Code ausführen." - das macht keinen Sinn. Sie können Turings Beweis nicht umgehen, indem Sie den Code "tatsächlich" ausführen, anstatt ihn zu simulieren. Wenn es anhält, können Sie festlegen, wie lange es dauert, bis es anhält. Wenn es nicht anhält, können Sie (im Allgemeinen) nie sicher sein, ob es in Zukunft anhalten oder für immer laufen wird. Es ist das gleiche Problem mit einer echten oder einer simulierten Stoppuhr. Zumindest in einer Simulation können Sie den internen Zustand leichter auf Anzeichen von Schleifen untersuchen.
3.
15

Hier spielen zwei Aspekte eine Rolle

Wie @ gnasher729 betont, ist es immer noch schwierig, die exakte Laufzeit zu schätzen, wenn wir die genauen auszuführenden Anweisungen kennen, beispielsweise aufgrund von Caching, Verzweigungsvorhersage, Skalierung usw.

Die Situation ist jedoch noch schlimmer. Bei einem Teil der Assembly ist es unmöglich zu wissen, welche Anweisungen ausgeführt werden oder wie viele Anweisungen ausgeführt werden. Dies liegt am Satz von Rice: Wenn wir das genau bestimmen könnten, könnten wir diese Informationen verwenden, um das Halteproblem zu lösen, das unmöglich ist.

Assembly-Code kann Sprünge und Verzweigungen enthalten, die ausreichen, um die vollständige Ablaufverfolgung eines Programms möglicherweise unendlich zu machen. Es wurde an konservativen Annäherungen der Ausführungszeit gearbeitet, die Obergrenzen für die Ausführung ergeben, beispielsweise durch Kostensemantik oder kommentierte Typsysteme. Ich kenne nichts spezielles für die Montage, aber ich wäre nicht überrascht, wenn es so etwas gäbe.

jmite
quelle
4
Ich meine, das Problem des Anhaltens trifft hier direkt zu, denn wenn wir die Laufzeit kennen, wissen wir, ob es anhält. Auch die Tatsache, dass es keine Bedingungen gibt, hilft hier nicht einmal weiter, da in x86 movTuring-Complete
BlueRaja - Danny Pflughoeft
7
Reis und das Problem des Anhaltens sind Aussagen über beliebige Programme - aber das OP hat hier einen bestimmten Code in der Frage spezifiziert. Sie können semantische und stoppende Eigenschaften für einzelne oder eingeschränkte Kategorien von Programmen bestimmen, oder? Es gibt nur kein allgemeines Verfahren, das alle Programme abdeckt.
Daniel R. Collins
2
Wir können definitiv wissen, welche Anweisung als nächstes ausgeführt wird, was wir nicht sagen können, ob wir jemals eine sys_exitdrücken und somit die Stoppuhr anhalten. Wenn wir uns auf das Beenden von Programmen beschränken, was für eine solche praktische Frage angemessen ist, lautet die Antwort tatsächlich Ja (vorausgesetzt, Sie haben eine perfekte Momentaufnahme des Zustands, hw und sw, des Systems, kurz bevor Sie das Programm starten).
Margaret Bloom
1
@ BlueRaja-DannyPflughoeft Mov ist absolut vollständig, aber nicht in dem Code, den das OP hier hat. Aber das ist ohnehin nicht der Punkt - die ints können beliebigen Code ausführen, auf beliebige I / O-Operationen warten usw.
Luaan
2

Würde die Wahl des "Computersystems" Mikrocontroller beinhalten? Einige Mikrocontroller haben sehr vorhersagbare Ausführungszeiten, zum Beispiel haben die 8-Bit-PIC-Reihen vier Taktzyklen pro Befehl, es sei denn, der Befehl verzweigt zu einer anderen Adresse, liest aus dem Flash oder ist ein spezieller Zwei-Wort-Befehl.

Interrupts unterbrechen diese Art von Timimg offensichtlich, aber es ist möglich, in einer "Bare-Metal" -Konfiguration viel ohne einen Interrupt-Handler zu tun.

Mit Hilfe von Assembly und einem speziellen Codierungsstil ist es möglich, Code zu schreiben, dessen Ausführung immer die gleiche Zeit in Anspruch nimmt. Es ist nicht mehr so ​​verbreitet, dass die meisten PIC-Varianten mehrere Timer haben, aber es ist möglich.

Oliver Broad
quelle
2

In der Ära der 8-Bit-Computer haben einige Spiele so etwas getan. Programmierer verwenden die genaue Zeit, die für die Ausführung von Befehlen benötigt wird, basierend auf der Zeit, die sie benötigt haben, und der bekannten Taktrate der CPU, um sich mit den genauen Timings der Video- und Audio-Hardware zu synchronisieren. Damals war das Display ein Kathodenstrahlröhrenmonitor, der jede Bildschirmzeile mit einer festgelegten Geschwindigkeit abwechselte und diese Pixelreihe durch Ein- und Ausschalten des Kathodenstrahls zum Aktivieren oder Deaktivieren der Leuchtstoffe malte. Da Programmierer der Videohardware mitteilen mussten, was angezeigt werden soll, bevor der Strahl diesen Teil des Bildschirms erreichte, und den Rest des Codes in die verbleibende Zeit einpassen mussten, nannten sie dies „Rennen um den Strahl“.

Es würde auf keinem modernen Computer oder für Code wie Ihrem Beispiel absolut funktionieren.

Warum nicht? Hier sind einige Dinge, die das einfache, vorhersehbare Timing durcheinander bringen würden:

CPU-Geschwindigkeit und Speicherabruf sind beide Engpässe bei der Ausführungszeit. Es ist eine Geldverschwendung, eine CPU schneller laufen zu lassen, als Anweisungen zum Ausführen abgerufen werden können, oder Speicher zu installieren, der Bytes schneller liefern kann, als die CPU sie akzeptieren kann. Aus diesem Grund liefen alte Computer mit derselben Uhr. Moderne CPUs laufen wesentlich schneller als der Hauptspeicher. Sie verwalten das, indem sie Instruktions- und Datencaches haben. Die CPU bleibt immer noch stehen, wenn sie auf Bytes warten muss, die sich nicht im Cache befinden. Dieselben Anweisungen werden daher viel schneller ausgeführt, wenn sie sich bereits im Cache befinden, als wenn sie nicht vorhanden sind.

Darüber hinaus haben moderne CPUs lange Pipelines. Sie halten ihren hohen Durchsatz aufrecht, indem ein anderer Teil des Chips die nächsten Befehle in der Pipeline vorarbeitet. Dies schlägt fehl, wenn die CPU die nächste Anweisung nicht kennt. Dies kann passieren, wenn eine Verzweigung vorliegt. Daher versuchen CPUs , bedingte Sprünge vorherzusagen. (In diesem Code-Snippet ist kein Code-Snippet enthalten, aber möglicherweise gab es einen falsch vorhergesagten bedingten Sprung, der die Pipeline verstopfte. Außerdem eine gute Entschuldigung, um diese legendäre Antwort zu verknüpfen.) Ebenso die Systeme, die int 80tatsächlich aufrufen , um in den Kernel-Modus einzufangen verwenden eine komplizierte CPU-Funktion, ein Interrupt-Gate, das zu einer unvorhersehbaren Verzögerung führt.

Wenn Ihr Betriebssystem preemptives Multitasking verwendet, kann der Thread, der diesen Code ausführt, jederzeit seine Zeitscheibe verlieren.

Racing the Beam funktionierte auch nur, weil das Programm auf dem Bare Metal lief und direkt auf die Hardware knallte. Hier rufen Sie int 80an, um einen Systemaufruf zu tätigen. Das übergibt die Kontrolle an das Betriebssystem, was Ihnen keine Zeitgarantie gibt. Anschließend teilen Sie ihm mit, dass E / A in einem beliebigen Stream ausgeführt werden soll, der möglicherweise auf ein beliebiges Gerät umgeleitet wurde. Es ist viel zu abstrakt, als dass Sie sagen könnten, wie viel Zeit die E / A benötigt, aber es wird sicherlich die Zeit dominieren, die für die Ausführung von Anweisungen aufgewendet wird.

Wenn Sie in einem modernen System ein genaues Timing wünschen, müssen Sie eine Verzögerungsschleife einführen. Sie müssen dafür sorgen, dass die schnelleren Iterationen mit der Geschwindigkeit der langsamsten ausgeführt werden. Das Gegenteil ist nicht möglich. Ein Grund, warum dies in der realen Welt der Fall ist, besteht darin, zu verhindern, dass kryptografische Informationen an einen Angreifer weitergegeben werden, der die Zeit für diese Anforderungen länger als andere beanspruchen kann.

Davislor
quelle
1

Dies ist etwas tangential, aber das Space Shuttle verfügte über 4 redundante Computer, bei denen es darauf ankam, dass sie genau synchronisiert wurden, dh dass ihre Laufzeit genau übereinstimmte.

Der allererste Startversuch des Space Shuttles wurde abgebrochen, als der Backup Flight Software-Computer (BFS) die Synchronisierung mit den vier PASS-Computern (Primary Avionics Software System) verweigerte. Details in "The Bug Heard Round the World" hier . Faszinierende Lektüre darüber, wie die Software entwickelt wurde, um Zyklus für Zyklus übereinzustimmen und Ihnen interessante Hintergrundinformationen zu geben.

Edgar H
quelle
0

Ich denke, wir mischen hier zwei verschiedene Themen. (Und ja, ich weiß, dass dies von anderen gesagt wurde, aber ich hoffe, ich kann es klarer ausdrücken.)

Zuerst müssen wir vom Quellcode zu der Abfolge von Anweisungen gelangen, die tatsächlich ausgeführt wird (die Kenntnis der Eingabedaten sowie des Codes erfordert - wie oft durchlaufen Sie eine Schleife? Welche Verzweigung wird nach einem Test ausgeführt?). ). Aufgrund des Halteproblems kann die Reihenfolge der Anweisungen unendlich sein (Nichtbeendigung), und Sie können dies auch bei Kenntnis der eingegebenen Daten nicht immer statisch feststellen.

Nachdem Sie die Reihenfolge der auszuführenden Anweisungen festgelegt haben, möchten Sie die Ausführungszeit bestimmen. Das kann man sicherlich mit einigem Wissen über die Systemarchitektur abschätzen. Das Problem ist jedoch, dass bei vielen modernen Maschinen die Ausführungszeit stark vom Caching von Speicherabrufen abhängt, was bedeutet, dass dies sowohl von den Eingabedaten als auch von den ausgeführten Befehlen abhängt. Es kommt auch darauf an, bedingte Verzweigungsziele richtig zu erraten, was wiederum datenabhängig ist. Es wird also nur eine Schätzung sein, es wird nicht genau sein.

Michael Kay
quelle