| |
|
|
- Seite 1 - |
|
HofK | Auf einen heißen Tipp von IF hin, habe ich mir mal three.js [...] angeschaut. Da [...] (ganz unten) die ersten Resultate. |
|
|
| |
|
|
| |
|
- Seite 40 - |
|
|
HofK | Lange angekündigt ist es nun soweit.
Die anfängerfreundliche aber im professionellen Einsatz nicht so günstige Geometry verschwindet stückweise aus three.js. Dazu gibt es eine Diskussionsthema [...]
Das hat mich veranlasst, die alte Problematik der Performance noch einmal genauer unter die Lupe zu nehmen. Siehe [...]
Dort auch der Link zur Lösung [...]
Bei BufferGeometrie muss man persönlich die zwei Dreiecke des Rechtecks in eine Materialgruppe packen. Bei der Umwandlung von Geometry zu BufferGeometry packt es das System irgendwie selbst. Und mehr Gruppen bedeutet mehr Last, also weniger Performance. |
|
|
| |
|
|
|
HofK | Das Maschinenprogramm, der Binärcode läuft.
Wenn auch bisher nur mit einer minimalen Befehlsanzahl:
NOP SWD LDC
Nachdem ich zu NOP noch einige Befehle, teils ohne vollständigen Code, hinzugenommen hatte, gab es ein merkwürdiges Verhalten. Der Befehlszähler machte unerklärliche Sprünge.
Es hat eine Weile gedauert, bis ich die Ursache gefunden habe.
Die Zuordnung der Funktionen zur Befehlsausführung geschieht über eine stark verschachtelte Struktur mit switch, in XProfan select.
Im Unterschied zu XProfan muss in JavaScript jeder Fall mit break; abgeschlossen werden, da sonst der nächste Fall auch bearbeitet wird. Das ist für einige Anwendungsfälle eventuell sinnvoll, aber insgesamt eher nervig. Da die verschachtelte Struktur mit ca. 200 Zeilen und wenig Leerzeilen recht umfangreich ist, führen wenige fehlende break; zu merkwürdigem Verhalten.
Wenn ich seinerzeit die Simulation mit JavaScript programmiert hätte, dann hätte ich sicher eine andere Möglichkeit der Zuordnung genutzt. Denkbar ist ein mehrdimensionales Array. Da ich aber möglichst eng am Original-Quellcode bleiben möchte, habe ich keine andere Wahl, als alle breaks; korrekt zu setzen.
Ohne eine solche Faltung, sieht man überhaupt nicht mehr durch!
aktuell bei /dev |
|
|
| |
|
|
|
HofK | Weil die Umwandlung der CPU Simulation ziemlich viel Feinarbeit und hohe Konzentration erfordert (Stand unter /dev), beschäftige ich mich parallel mit einem kleinerem, etwas lockerem und abwechslungsreicherem Projekt.
Der Rausschmiss der alten Geometry aus three.js erfordert ein Anfängerbeispiel, um Interessenten nicht gleich mit Buffern zu vergraulen, sonder sie ihnen näher zu bringen.
Auch kann man in der Dokumentation nur die Hauptbegriffe suchen und findet so auf Anhieb die anfangs benötigten Dinge nicht immer gleich.
Dort die Idee: [...]
Das Beispiel entwickelt sich Schritt für Schritt.
Siehe [...] BeginnerExample
Der Quellcode ist mit vielen Kommentaren gespickt. |
|
|
| |
|
|
|
HofK | Bereits vor einiger Zeit hatte ich angemerkt, dass sich die recht verschachtelte Verarbeitungslogik mit Schleifen und waitinput nicht einfach so von XProfan/Widows nach Javascript/Browser übertragen läßt.
Der Browser duldet keine Art von extra Warteschleifen oder sogar einen Stopp bei schrittweiser Abarbeitung. Er reagiert sehr schnell mit einer Fehlermeldung.
Die Idee, einfach mal setTimeout() zu benutzen ist daher zeitlich sehr begrenzt. Nach einem Test stellte sich heraus, das der Befehl schlichtweg ignoriert wird. Wie das?
Die Antwort fand ich an dieser Stelle: [...]
"Javascript stellt drei Methoden für Animationen:
setTimeout () setInterval () wiederholt Anweisungen in einem Interval Beim requestAnimationFrame () übernimmt der Browser die Schnittstelle und optimiert das Verfahren"
Aber die Funktion animate mit dem rekursiven Aufruf
function animate() {
requestAnimationFrame( animate ); ...
ist unabdinglich für three.js bzw. die dynamische 3D Darstellung.
Dann habe ich etwas tiefer gegraben und interessante, aber teils schwer verdauliche Dinge ausprobiert.
promise, async function, response, await und ähnliche Dinge. Siehe z.B. [...] [...]
Aber ich benötige es synchron, und alle Versuche brachten keinen Erfolg.
Also ein völlig neuer Ansatz!
three.js liefert die Uhr mit:
"Clock Object for keeping track of time. This uses performance.now if it is available, otherwise it reverts to the less accurate Date.now. " Wenn man passende Statusvariablen definiert, kann man vollständig in der rekursiven animate-Funktion bleiben und dort nach passender Zeit das nächste Teilstück der jeweiligen Funktion aufrufen. Damit kann man auch total stoppen, da ja die animate-Schleife weiterläuft.
Problem: Man muss alle Funktionen an den "Wartestellen" zerlegen und stückweise verfügbar machen. Das erhöht nicht gerade die Übersichtlichkeit.
Schaut man sich allerdings die Verschachtelungen im XProfan Original genauer an, ist das auch nicht trivial. Ich kann mich erinnern, das ich auch eine Weile gebraucht habe, um das so ineinander zu bekommen. Es ist eine ganz andere Vorgehensweise.
Mit der Eingabe, _NOP, _CMP und der in vielen anderen Befehlen benötigten function add_ALU_9( ) funktioniert es bereits.
(Hier nicht als Quelltext sinnvoll darstellbar, da if ohne { ... falsch strukturiert.)
function animate() {
requestAnimationFrame( animate );
... if ( progRuns ) { // binary code runs
if ( !cmdExec && nextCmd ) decode_binary( ); // decode binary machine instruction and execute it
if ( stop === 1 ) progAss = true; // binary code stoped
}
if ( !cmdExec && !nextCmd ) {
dt = clock.getElapsedTime( ) - ts;
nextCmd = dt < delay ? false : true;
}
if ( cmdExec && !goAdd ) {
dt = clock.getElapsedTime( ) - ts;
goAdd = go = dt < delay ? false : true; //go = dt < delay ? false : true;
}
if ( cmdExec ) { // command is processed
if ( onInput ) make_input( ); if ( finInput ) finalize_input( );
if ( onAdd1 && goAdd ) add_ALU_9_1( );
if ( cmd === 'CMP1' && go ) _CMP1( ); if ( cmd === 'CMP2' && go ) _CMP2( );
}
if( prevrow !== ramrow ) {
rf_assFlagsRAM( prevrow ); prevrow = ramrow;
}
rendererLeft.render( sceneLeft, cameraLeft ); rendererRight.render( sceneRight, cameraRight );
}
Am Ende des Einstiegsteils der Funktion add_ALU_9( ) steht dann
onAdd1 = true; goAdd = false; ts = clock.getElapsedTime( );
Am Ende des letzten Teilstücks von _CMP (_CMP2) findet sich
cmdExec = false; nextCmd = false; ts = clock.getElapsedTime( );
Der Rest ist nun konzentrierte und etwas zeitraubende Kleinarbeit, bis alle Befehle zerlegt sind. Dabei sind zwei Stufen zu realisieren, einmal auf Bytebene und für die ALU auch bitweise.
|
|
|
| |
|
|
|
p.specht
| |
|
| XProfan 11Computer: Gerät, daß es in Mikrosekunden erlaubt, 50.000 Fehler zu machen, zB 'daß' statt 'das'... | 09.02.2021 ▲ |
|
|
|
|
HofK | Zwischendurch noch eine interessante geometrische Lösung, die ich eventuell abgewandelt in das Anfängerbeispiel übernehme.
Da war die Frage: [...] , dann die Lösung von prisoner849 [...]
und danach kommt meine Erweiterung [...]
|
|
|
| |
|
|
|
HofK | Die Spirale ist als Blumenstiel im Anfängerbeispiel [...]
Nur eine halbe Umdrehung mit sehr hoher Steigung! |
|
|
| |
|
|
|
HofK | Nach Überarbeitung der Statusvariablen und des Schemas innerhalb der Funktion animate, konnte ich auch das bitweise pausieren realisieren.
Wenn man von der Multiplikation und der Division absieht, die noch nicht bearbeitet sind, ist der recht unscheinbare Befehl CMP (compare) neben SUB (Subtraktion, noch unvollständig) der Befehl mit sehr starker Zerstückelung. Es müssen neben dem Hauptbefehl zum Einstieg vier Unterbefehle gebildet werden. Dabei wird auch einmal die bitweise Verarbeitung realisiert. Die console.log Ausgabe:
Zwischen den Schritten pausiert die Berechnung mit festgelegter Zeit.
Kann momentan unter [...] getestet werden. Die Konsole mit Strg+Shift+i öffnen, dann einfach nur den Befehl CMP auswählen und mit grünem Knopf starten. Zur Wiederholung muss derzeit noch mit F5 neu geladen werden, da die Gesamtschleife noch nicht richtig realisiert ist. |
|
|
| |
|
|
|
HofK | Mit dem Anfängerbeispiel [...] geht es voran, bei der Simulation gibt es ein scheinbar unüberwindbares Hindernis.
Die Realisierung der Warteintervalle durch Zerlegung, stößt bei den komplexen Befehlen Multiplikation und Division an ihre offensichtlich unüberwindbaren Grenzen.
Bereits das bitweise pausieren erfordert einen extra Trick, ist aber möglich. Statt der Zählschleife realisiert man das über eine Abfrage in der animate Funktion und sichert den Rücksprung. Allerdings muss das für jeden der Befehle gesondert geschehen, da sonst gerade der Rücksprung nicht klappt.
Da nicht viele Befehle Bitstep benötigen, ist das machbar.
Bereits bei der Multiplikation ( mul_Booth_ALU ) gibt es nun aber eine Schleife mit if ... Verschachtelung der Aufrufe. Bei XProfan kein Problem mit der proc ALU_step (3 mal aufgerufen)
Aber das funktioniert eben nicht im Browser, der wartet nicht.
Dazu kommt, dass innerhalb der Schleife auch noch die proc add_ALU_9 benötigt wird. Der Rücksprung in die Schleife ist so nicht möglich. Auch add_ALU_9 enthält zwei Pausen ALU_step und muss in drei Teile zerlegt werden. Das scheint mir zusammen genommen unmöglich.
Ich gebe nicht schnell auf, aber diesmal sieht es düster aus. Die Division ist noch wesentlich komplexer.
Ohne die schrittweise Darstellung gerade der Multiplikation und Division ist die Simulation aber nicht wirklich viel Wert. |
|
|
| |
|
|
|
HofK | Wenn es düster ist, muss man sich besonders ins Zeug legen und Licht in die Sache bringen.
Es ist mir gelungen, das Knäul zu entwirren.
Man schreibt normalerweise Prozeduren bzw. Funktionen, um sich wiederholende Dinge nur einmal im Code zu haben. Andererseits ist das jedes mal ein Funktionsaufruf der (etwas) Zeit kostet. Ich will gerade nicht Zeit sparen, sondern schrittweise arbeiten, aber hier hilft es, statt des Funktionsaufrufs den Code jeweils an die Stelle zu kopieren. Damit schränkt man die Verschachtelungstiefe bei der Auswahl in der animate Funktion ein. Die einige Hundert Zeilen mehr spielen keine Rolle. Um den Überblick zu behalten, kann man diese Teile in Kommentare setzen und z.B. extra einrücken. So sind auch die knapp 10 Wiederholungen der Verschachtelung bei der Division zu meistern.
Trotzdem ist das "Strickmuster" mit den vielen Statusvariablen schon recht komplex. Momentan von Zeile 1945 bis 2262 mit den console.log Befehlen zur Kontrolle.
Noch nicht fehlerfrei, aber das Prinzip ist erkennbar.
Bei [...] die Konsole öffnen, den Befehl MUL in eine der ersten RAM Zeilen eingeben und den grünen Startknopf drücken. Am Ende verhakt es sich noch in einer Endlosschleife bei der Addition, ich muss da noch nacharbeiten. Auch was in der ALU selbst passiert ist noch fehlerhaft. Bisher habe ich nur von XProfan formal übernommen und muss alle Befehle der Reihe nach prüfen. Es gibt z.B. unterschiedliche Indizierungen bei XProfan und JavaScript.
|
|
|
| |
|
|
|
HofK | Die Endlosschleife hatte eine einfache Ursache.
Bei for-Schleifen ist die Zählvariable lokal, man kann schachteln.
Statt for ( let i = 0 ... wird aber in der Auswahl innerhalb der animate Funktion die Variable erhöht. Um das knappe i nicht zu übersehen, habe ich bit genommen. Die Variable ist global. Solange das sequentiell läuft und man stets den Anfangswert korrekt setzt, kein Problem.
Aber bei Verschachtelung geht das schief, der Wert wurde immer wieder zurückgesetzt. Man muss dann also verschiedene Variablen nehmen.
Nun also bit und für die Verschachtelungen extra addBit und mulBit.
Die Zeilen in animate gehen nun von 1945 bis 2278, da es Ergänzungen gibt.
( UPDATE 9. März: ab Zeile 2064)
Jetzt muss die Sache noch in allen möglichen Varianten getestet werden um sicherzustellen, das kein weiterer Bug drin ist. |
|
|
| |
|
|
|
RudiB. |
Aber bei Verschachtelung geht das schief, der Wert wurde immer wieder zurückgesetzt. Man muss dann also verschiedene Variablen nehmen.
Ich misch mich hier ungern in dieses Thema ein."Verfolge ich mit regem Interesse.....". Meine Programmierkünste sind nicht so der Hit.... Aber wenn ich das ZITAT oben so lese, dann glaube ich ja eher das der Fehler in den Programmzeilen sitzt. " Variable wird zurückgesetzt". Immer neue Variablen zu nehmen führt ja nun wirklich nicht zum wahren Ergebnis. Ist mir bereits auch so ergangen, man verliert einfach den Überblick.....
Das Thema ist mir eh ein wenig zu hoch, aber ich hatte noch "SENF" den musste ich dazugeben...
Trotzdem Viele Grüße aus München
Rudi |
|
|
| |
|
|