Date: Wed, 11 Sep 2024 21:53:58 +0000 From: Giacomo Tesio <giacomo@tesio.it>
Ciao Giuseppe,
Il 11 Settembre 2024 16:38:55 UTC, Giuseppe Attardi <attardi@di.unipi.it> ha scritto:
Mi spiace dover dissentire da Enrico.
Dissenti anche da me o solo da Enrico?
Ti ho proposto una semplice dimostrazione dell'equivalenza fra dato e programma:
``` Ogni dato è software eseguibile da almeno una macchina programmabile.
Puoi infatti facilmente costruire una macchina programmabile che avanza il proprio program counter se riceve in input il byte corrente del proprio programma e si ferma altrimenti. ``` (qui <https://server-nexa.polito.it/pipermail/nexa/2024-September/053214.html>)
Non ti convince?
Te ne propongo un'altra: ho qui una macchina programmabile che ad ogni ciclo legge un nuovo bit dal programma caricato e chiude un circuito se il bit vale 1, mentre lo apre se vale 0.
Ho provato a caricargli un binario ARM e l'ha eseguito senza problemi. Ho provato con un COFF e un ELF e li ha eseguiti senza problemi. Allora ho provato con una foto, e ha continuato ad accendere e spegnere una lampadina esattamente secondo l'ordine dei bit forniti. Infine ho provato a caricare la tua mail, e la macchina (me ne scuso) ne ha eseguito ogni bit, dal primo all'ultimo.
Perché la mia macchina irriverente continua ad eseguire qualsiasi dato che io gli carico senza distinguere fra istruzioni e non?
Il tuo programma esegue istruzioni che leggono dei dati qualunque, non eseguono quei dati. Il fatto che quei dati siano una *rappresentazione* in un certo formato di istruzioni non li fa eseguire dalla tua macchina, perché non passano dal suo interprete (CPU), ma dalla sua ALU. L’architettura Von Neumann e la MTU prevedono che i programmi vengano rappresentati nella stessa forma, per comodità nel primo caso (in alternativa alla Harvard architecture) e per generalità la seconda (una singola macchina anziché infinite), ma c’è un passo ineludibile passaggio di trasformazione prr ottenere larappresentazione come dato di un programma, tipicamente un compilatore.
In altri termini, qualunque istruzione può essere rappresentata come dato, ma non ogni dato può essere interpretato come istruzione...
Perché questo predicato diventi vero è necessario aggiungere "da una qualsiasi macchina programmabile"
No, qualunque sia la macchina, esiste un dato (anzi infiniti) che non sono interpretabili da quella macchina, o, se vuoi, che danno errore se eseguiti. L’insieme delle rappresentazioni dei programmi è un sottoinsieme stretto di quello dei dati.
La verità di tale predicato però non esclude in alcun modo che possano esistere infinite macchine programmabili in grado di eseguire un qualsiasi dato.
Ossia la semantica di un’istruzione è strettamente legata al suo interprete, quella di un dato no.
Anche qui, perché il predicato diventi vero dobbiamo sostiire "dato" con "quasiasi dato": molte macchine infatti possolo eseguire solo certe sequenze di bit e non altre.
Un x86 non eseguirà correttamente un eseguibile ARM o JVM.
D'altto canto ogni Vector Reducing Machine è in grado di eseguire solo le matrici numeriche la cui dimensionalità è compatibile
Sono macchine programmabili diverse, ma pur sempre macchine il cui comportamento dipende esclusivamente dal programma fornito.
Mi puoi spiegare dove sbaglio?
L’errore sta nel verbo “eseguire”: si eseguono istruzioni, sui dati si opera. Le Vector Reducing Machine effettuano operazioni matriciali su vettori e matrici, le matrici non eseguono alcunché. C’è una circuiteria apposta nelle GPU per operare su matrici, seguendo le *istruzioni* fornite tramite la libreria CUDA; se le matrici eseguissero, potresti fare a meno delle GPU e di CUDA.
Giacomo