ELABORATORI ELETTRONICI
(v. calcolatrici, macchine, VIII, p. 352; App. I, p. 339; II, I, p. 482; III, I, p. 281; elaboratori elettronici, IV, I, p. 650)
La diffusione e lo sviluppo degli e. nell'arco di tempo che va dalla metà degli anni Settanta fino all'inizio degli anni Novanta sono stati caratterizzati da un'iniziale, impetuosa espansione dell'uso degli e. personali (personal computers) con tassi annui d'incremento che, alla fine degli anni Ottanta, erano ancora superiori al 30%, e da un improvviso successivo calo all'inizio degli anni Novanta dovuto alla saturazione del mercato e che ha determinato una crisi di varie case costruttrici. È comunque da sottolineare che si è venuto creando anche un mercato di sostituzione di modelli obsoleti con modelli più potenti, più facili da usare e, soprattutto, leggeri, portatili. Ciò rende peraltro difficile la valutazione di quanti e. personali siano effettivamente in uso fra quelli venduti.
L'e. personale e la sua diffusione capillare caratterizzano l'arco di tempo considerato e contribuiscono in modo rilevante alla diffusione dell'informatica, specialmente nelle sue applicazioni più semplici. Per e. personale s'intende un e. di dimensioni tali da poter essere sistemato su (o vicino a) una scrivania, a disposizione di una sola persona e di costo modesto (da uno a qualche milione di lire), in modo da poter essere usato in modo anche assai saltuario o comunque poco intensivo. Nelle sue realizzazioni correnti è formato da un microelaboratore (v. App. IV, i, p. 650) con uno schermo video, una tastiera, una o più unità di memoria ausiliaria a dischetto magnetico (fisso e asportabile) e generalmente anche una stampante e un dispositivo (mouse) che, mosso su un piano, consente di controllare il contemporaneo moto di una freccia (o comunque di un indicatore) nel quadro che appare sullo schermo video.
Molto spesso un e. personale è utilizzato come e. di testi (word processor), cioè come sistema con cui non solo si possono comporre e stampare testi come se fosse una macchina per scrivere, ma si possono inoltre apportare modifiche (anche ripetitive), trasposizioni, ecc., limitate a una parola o estese a molte righe. La diffusione di economiche stampanti laser che, usando la tecnologia delle comuni macchine fotocopiatrici xerografiche, permettono di produrre testi e disegni di ottima qualità, ha diffuso l'utilizzo degli e. personali non soltanto nei lavori di segreteria, ma anche nella composizione tipografica.
Quando un e. personale viene dotato di un corredo programmativo che permette, oltre all'elaborazione di testi, anche la loro archiviazione e il loro reperimento automatico, allora si comincia ad avere uno strumento indispensabile non solo per il lavoro di ufficio, ma anche per il lavoro giornalistico, per l'analisi letteraria di testi, per l'esecuzione di calcoli, di simulazioni, di statistiche, ecc., almeno a un basso livello. Accanto a ciò va ricordata la diffusione di microelaboratori che entrano negli e. personali non professionali, cioè di capacità minime, per uso domestico, per video giochi, ecc.
Tralasciando questi ultimi, va sottolineato che gli e. personali sono ormai basati su microelaboratori che hanno caratteristiche molto simili a quelle degli e. usati nei sistemi più grandi, e perciò nel seguito daremo sinteticamente un'analisi del tipo di architettura che ormai distingue i moderni e. del tipo detto di von Neumann, per passare poi a descrivere le architetture che non corrispondono a tale tipo.
Lo sviluppo delle architetture. - Innanzitutto diremo che per architettura di un e. s'intende la sua descrizione fatta ai fini del suo uso, e perciò di chi lo programma, prescindendo dalla sua realizzazione fisica. Essa perciò dà la struttura concettuale e il comportamento funzionale dell'e. stesso. Un'analisi di questo tipo è interessante sia perché dà un risultato invariante rispetto alla tecnologia corrente, che progredisce in modo assai rapido, sia perché permette di vedere come l'evoluzione dell'architettura dei microelaboratori, dalla metà degli anni Settanta alla metà degli anni Ottanta, abbia ricalcato l'evoluzione degli e. dai primi anni Cinquanta alla metà degli anni Sessanta.
L'architettura del tipo detto di von Neumann è quella classica con una memoria di lavoro (o memoria primaria) composta da registri (contraddistinti da indirizzi), una unità operativa (o unità aritmetica e logica), una unità di governo, unità periferiche (di memoria secondaria o dedicate alle operazioni d'ingresso e di uscita di operandi e di risultati), oltre che da organi di collegamento (bus) fra tali unità funzionali (v. App. IV, i, p. 650). L'insieme dell'unità (od organo) di governo e dell'unità aritmetica e logica è detta generalmente unità centrale.
Le elaborazioni di un'architettura alla von Neumann sono eseguite in base a un programma, composto di istruzioni che fanno riferimento, in genere, non agli operandi, ma agli indirizzi dei registri che li contengono, e questo rende i programmi parametrici. Per evitare di scrivere molte istruzioni si cerca di avere programmi ciclici e modulari, cioè decomposti in moduli riusabili, che prendono il nome di sottoprogrammi.
Infine va rilevato che l'architettura di von Neumann è universale, nel senso che, essendo tutti gli operandi codificati in un codice binario, basta che l'unità aritmetica e logica possa compiere alcune semplici operazioni proprie dell'algebra a due valori, perché qualunque tipo di operazione fra operandi qualsiasi (purché codificabili in modo finito) risulti possibile se si dispone di una memoria di capacità adeguata.
L'architettura di von Neumann, da lui (e da altri) proposta nel 1945, corrisponde a quella dei primi e. realizzati alla fine degli anni Quaranta e nella prima metà degli anni Cinquanta e in larga misura anche ai primi semplici microelaboratori della metà degli anni Settanta. Tuttavia lo sviluppo delle tecniche di programmazione, dei linguaggi programmativi e delle relative tecniche di traduzione in linguaggi macchina direttamente eseguibili da un e., lo sviluppo dei sistemi operativi e dell'uso di e. in contesti che interagiscono continuamente con essi (per es., controllo di processi industriali), hanno provocato l'aggiunta di varie funzionalità alla primitiva, semplice architettura.
Ovvia la convenienza di poter memorizzare od operare con operandi rappresentati sia nella notazione in virgola fissa (cioè con la virgola binaria in posizione fissa rispetto a numeri espressi con un numero costante di cifre) che in quella in virgola mobile (cioè con una notazione analoga a quella del tipo 2,326 × 106). Inoltre è stata introdotta la possibilità di operare su numeri sia in virgola mobile che in virgola fissa con apposite istruzioni aritmetiche, e questo con un'espansione dell'unità aritmetica o con l'aggiunta di un'unità aritmetica ad hoc. Ulteriore aggiunta è stata quella di poter operare su interi in rappresentazione sia binaria che decimale. La possibilità di fare riferimento a operandi con numero variabile di caratteri, specie per le operazioni relative alle unità periferiche, è ormai adottata generalmente.
Tutto ciò ha comportato la necessità di avere istruzioni che specificavano non solo un indirizzo di un registro contenente un operando costituito da un byte (cioè da 8 bit o cifre binarie), ma anche il numero di byte a cui si riferisce l'istruzione stessa. Corrispondentemente si sono ampliate le funzioni degli organi che governano l'accesso alla memoria.
Dal punto di vista tecnico-economico è continuato sia il raddoppio biennale del rapporto prestazioni/costi, sia l'ampliamento del mercato controllato da aziende giapponesi produttrici di componenti elettronici e in particolare di memorie.
Si è detto poco sopra dell'opportunità di dividere i programmi in moduli. Questo è utile per suddividere il problema da risolvere in parti, e il programma relativo in moduli, che assolvono funzioni definite più o meno facilmente e più o meno chiaramente, così da facilitare sia il compito di capire il problema e d'individuarne le soluzioni, sia il lavoro di redazione dei programmi.
I moduli di programma sono anche convenienti perché possono essere riusati più volte nello stesso programma o in altri programmi quando, per es., calcolino funzioni matematiche di frequente impiego, oppure quando assolvano compiti particolari come, per es., la stampa di un testo registrato nella memoria. La riusabilità di questi moduli (o sottoprogrammi) in vari contesti richiede una facile rilocabilità dei medesimi, cioè la possibilità di cambiare facilmente la zona di memoria in cui i programmi stessi sono scritti o in cui sono registrati operandi e risultati.
Questo ha fatto sì che il semplice formato delle istruzioni di macchina (cioè delle istruzioni eseguibili immediatamente, senza traduzione) degli e. a struttura più semplice, sia passato dalla forma "parte operazione − indicazione eventuale di accumulatori − parte indirizzo (una o più) relativa alla memoria di lavoro", alla forma "parte operazione − indicazione eventuale di registri aritmetici − indicazione di registri e di modi di indirizzamento − parte indirizzo − eventuale indicazione della lunghezza degli operandi".
Fra i modi d'indirizzamento più diffusi, ricorderemo l'indirizzamento relativo, in cui la parte indirizzo di un'istruzione dà non l'indirizzo del registro di memoria in cui si trova l'operando, ma l'indirizzo in cui si trova l'indirizzo dell'operando. Questo sistema è simile a quello delle caselle postali.
Altro modo d'indirizzamento assai diffuso è l'indirizzamento con indice, in cui la parte indirizzo di un'istruzione viene sommata al contenuto di un registro, detto registro indice (specificato nell'istruzione stessa), per dare l'indirizzo effettivo dell'operando. Questo consente di accedere facilmente a indirizzi consecutivi di memoria con una stessa istruzione, purché si modifichi il contenuto del registro indice che essa specifica. Inoltre consente di modificare gli indirizzi effettivi a cui si riferiscono le istruzioni di un modulo, se esse fanno riferimento a uno stesso registro indice.
Altri tipi d'indirizzamento, riportabili o meno a variazioni dei tipi ora descritti, esistono, ma per ragioni di spazio non vengono qui descritti.
Per passare dall'esecuzione di un programma a quella di un sottoprogramma c'è bisogno di istruzioni di salto che registrino l'indirizzo da cui si è saltati. Così, quando il sottoprogramma è terminato, si può riprendere l'esecuzione del programma che lo ha chiamato in causa. Per questo è utile avere registri a catasta o a pila (stack) in cui è utile ''accatastare'' l'uno sull'altro gli indirizzi per il ritorno al programma che ha chiamato un modulo, il quale poi avrà potuto chiamare un altro modulo, e così via. Questi registri a catasta sono utili anche per il passaggio di operandi e di risultati fra programmi chiamanti e programmi chiamati, e per compiere varie altre operazioni, fra le quali alcune per la traduzione fra linguaggi programmativi diversi. L'operazione di chiamata in azione di un modulo di programma (o sottoprogramma) richiede perciò che nel repertorio di istruzioni di un e. ci siano una o più istruzioni apposite, oltre a organi ad hoc, che possono essere usati anche per altre funzioni.
Non sempre, come vedremo, moduli o programmi diversi cooperano e si compongono nel modo sopra descritto, in cui un programma (o modulo A) chiama un sottoprogramma B (che assume in questo caso il nome di sottoprogramma chiuso) e, quando questo ha terminato, si torna all'esecuzione di A nel punto in cui era stato chiamato B. Questo, a sua volta, può avere nel proprio ambito un'istruzione di chiamata di un altro sottoprogramma C, che a sua volta può contenere la chiamata di D, e così via per un numero finito di volte (v. App. IV, i, p. 652). Perciò nel caso dei sottoprogrammi chiusi possiamo dire che l'esecuzione del programma chiamato è inserita nell'esecuzione del programma chiamante, il suo testo essendo presente una sola volta. Invece c'è un altro tipo di sottoprogramma, detto sottoprogramma aperto, il cui testo viene inserito in quello del programma chiamante in ogni punto in cui viene richiesta la sua esecuzione. Questo tipo di sottoprogramma non richiede, però, istruzioni particolari.
Altro tipo di programmi (o di moduli) cooperanti è quello delle cosiddette coroutine (la parola routine essendo sinonimo di sottoprogramma), le quali sono dei moduli che si chiamano in azione l'uno con l'altro senza attendere di essere terminati e, quando vengono chiamati in azione di nuovo, riprendono dal punto in cui avevano chiamato l'altro, come mostrato in fig. 1.
Dobbiamo però notare che l'intervento di un modulo (o di tutto un programma) non sempre può essere convenientemente predisposto da un'apposita istruzione di un programma in corso di esecuzione. Per es., l'accettazione di una richiesta di attenzione da parte di un terminale collegato a un e. o l'interrogazione di uno o più allarmi possono essere previste da uno speciale programma d'interrogazione la cui esecuzione va periodicamente inserita in quella dei programmi usuali. Tuttavia questo modo di operare non è accettabile se gli eventi da controllare sono diversi, e comunque costringe a un'estenuante pianificazione e previsione dei tempi di entrata in funzione dei programmi d'interrogazione. Perciò si preferisce aggiungere all'unità di governo la capacità di accettare segnali d'interruzione, che possono far interrompere l'esecuzione di un programma, conservando lo stato della computazione in atto (in modo da poterla poi riprendere), e avviare invece un programma relativo al segnale d'interruzione ricevuto che, per es., può provenire da un allarme o comunque da un evento estemporaneo. Così si evita il periodico salto a un programma d'interrogazione, che può essere anche inutile perché non c'è nessuna richiesta o allarme in atto e si hanno invece delle interruzioni solo quando c'è un'effettiva richiesta di attenzione o un effettivo allarme.
Spesso i governi capaci di accettare interruzioni hanno dei dispositivi che permettono d'ignorare (o ''mascherare'') temporaneamente dei segnali d'interruzione o di servirli automaticamente secondo priorità predisposte, nel caso in cui ne arrivino più di uno. L'introduzione dei segnali d'interruzione e della conseguente operazione d'interruzione è fondamentale per un e. che debba interagire con un utente, con dei dispositivi, con degli impianti, ecc., e perciò anche nei microelaboratori è stata introdotta la possibilità di accettare interruzioni sin dal loro avvento.
È però da sottolineare che, quando la cooperazione fra programmi e moduli di programma non è rigidamente predeterminata come nel caso dei sottoprogrammi (chiusi o aperti), allora si possono creare delle interferenze da evitare. Per es., se un programma D trasferisce ripetutamente dati da una memoria secondaria a un'area Z della memoria di lavoro, e un programma S provoca la stampa dei dati successivamente trasferiti dalla memoria secondaria, allora vogliamo che il programma S:
a) provochi la stampa dei dati trasferiti dalla memoria secondaria a quella di lavoro prima che il programma D trasferisca nell'area Z dei nuovi dati che cancellino i precedenti prima che questi siano stampati;
b) non stampi di nuovo il contenuto dell'area Z prima che il programma D non vi abbia trasferito nuovi dati al posto di quelli già stampati.
Allo scopo di avere quanto sopra, e cioè di evitare che sia D che S operino contemporaneamente sull'area Z, si può usare un semaforo, cioè, per es., una variabile a due valori, la quale è interrogata da ciascuno dei due programmi prima di entrare nella sequenza, detta ''critica'', delle proprie istruzioni che accedono all'area Z di memoria. Se, per es., la variabile che fa da semaforo vale 0, allora il programma che la esamina resta in attesa, altrimenti, se vale 1, prosegue azzerando la variabile semaforica (in modo che l'altro programma resti in attesa se la esamina) ed entrando nella propria zona critica.
Per realizzare tali operazioni di tipo semaforico sono allora necessarie apposite istruzioni di macchina, dette istruzioni semaforiche o di sincronizzazione, che, per es., con un'unica operazione esaminino il contenuto di un registro e, se questo non è 1, ripetano la propria esecuzione, altrimenti passino all'istruzione successiva azzerando il contenuto del registro stesso.
Si noti che, fino a questo punto, abbiamo considerato il caso di più programmi o moduli di programma che si trovano nella memoria di un e. e cooperano mutuamente in un unico lavoro per raggiungere un fine comune. Però non sempre è così. Per es., in un e. di un centro di calcolo scientifico si possono trovare in esecuzione contemporanea più lavori, sia perché in quel centro sono presenti e vengono tenuti aggiornati certi programmi di calcolo di uso generale, sia perché può essere economicamente più conveniente fare svolgere dei lavori su un grande calcolatore. Per molti anni, infatti, il costo di un e. è stato (grosso modo) proporzionale alla radice quadrata del numero di istruzioni che è capace di eseguire nell'unità di tempo (legge di Grosch), e il costo di un'elaborazione è in genere addebitato in base al tempo di utilizzo dell'e. e dei suoi organi, a parità di altre condizioni.
Altra ragione per cui più lavori indipendenti possono essere presenti contemporaneamente su un e. è quella di voler accedere a uno stesso sistema di archivi di dati. D'altra parte la presenza contemporanea di più lavori in uno stesso e. può aumentare l'utilizzo dei suoi organi. Se infatti la capacità e la velocità di questi ultimi sono state scelte in base al maggiore e più impegnativo dei lavori che si prevede di dover svolgere, allora quando viene eseguito un lavoro meno impegnativo vi possono essere degli organi (quali, per es., la memoria di lavoro o l'unità aritmetica e logica) che non sono sfruttati al massimo delle proprie possibilità.
Perché l'esecuzione contemporanea di lavori indipendenti sia fattibile occorre, però, che i vari organi di un e. (memoria di lavoro, unità di governo e unità aritmetica e logica, memorie secondarie, unità d'ingresso e unità di uscita) possano operare indipendentemente gli uni dagli altri, anche se sotto il controllo dell'unità di governo che ne avvia le operazioni in base al programma di esecuzione. D'altra parte questa mutua indipendenza dei vari organi di un e. può essere conveniente anche per l'esecuzione di un solo lavoro, in quanto può permettere a tali organi di lavorare contemporaneamente, quando naturalmente l'elaborazione lo esiga.
Perciò si possono avere due tipi di architetture che si rifanno al modello di von Neumann. In un primo tipo (adatto per e. con un piccolo numero di unità periferiche e di modeste capacità elaborative), le operazioni dei vari organi periferici avvengono sotto controllo dell'organo di governo, e spesso lo scambio di dati fra memoria e unità periferiche avviene per il tramite dell'unità centrale.
Un secondo tipo, invece, ha una memoria principale con un proprio governo, che può ricevere richieste di accesso dagli altri organi e servire tali richieste secondo varie procedure, in modo che è la memoria a essere l'organo di comunicazione fra unità centrale e unità periferiche e anche fra queste stesse. Questo è il tipo di architettura adottato in genere negli e. con molte unità periferiche e con le maggiori capacità di memorizzazione e di elaborazione. Occorre però aggiungere che tipi intermedi di architetture fra i due indicati possono comunque essere utilmente usati.
Nella fig. 2 è schematizzata un'architettura del secondo tipo sopra descritto, in cui sono indicati i vari organi (bus) d'interconnessione, sia nell'ambito della memoria, che in quello delle unità periferiche, oltre al bus centrale che collega memoria, unità centrale e canali delle unità periferiche.
I canali sono organi che ricevono dall'unità centrale l'istruzione relativa a un'unità periferica UP a essi collegata, dopo di che ne curano l'esecuzione accedendo alla memoria quando necessario, registro per registro, in modo che l'unità centrale può curare l'esecuzione di altre istruzioni. Similmente la memoria potrà essere utilizzata dall'unità centrale o da altri canali, per un accesso alla volta per ciascuno, attraverso il governo accessi GA. La memoria potrà essere anche suddivisa in più banchi M accessibili indipendentemente.
Questo schema semplificato di architettura si può considerare tipico per gli e. maggiori (escludendo i supercalcolatori, o supercomputers) specie se si considera che invece di una sola unità centrale se ne possono avere diverse, arrivando allo schema detto multiprocessore, che però si scosta notevolmente dall'originario schema di von Neumann, e di cui si dirà oltre. Restando allo schema con una sola unità centrale, si può notare che un tale e. è adatto a eseguire più programmi indipendenti contemporaneamente, cioè può operare in multiprogrammazione. Contemporaneamente significa che più programmi (indipendenti fra loro, come detto) risiedono nella memoria principale, e che l'unità centrale esegue (o avvia, nel caso di istruzioni relative alle unità periferiche) una alla volta un'istruzione di uno di tali programmi. La scelta del programma a cui appartiene di volta in volta l'istruzione è fatta dal supervisore, cioè da quella parte del sistema operativo (v. App. IV, i, p. 653) che, in base a eventuali priorità o scadenze di esecuzione assegnate ai vari programmi e in base ai segnali d'interruzione, gestisce l'uso sia dei vari organi (o unità) dell'e. che possono operare indipendentemente, sia dei vari componenti del sistema operativo e del corredo programmativo disponibile sull'e. stesso, secondo criteri di ottimo che sono definiti in base al servizio che si vuole ottenere dal sistema operativo stesso.
Per evitare che il supervisore possa essere disturbato o spodestato della sua funzione di gestore dell'attività dell'e., è necessario introdurre alcune varianti all'architettura e alcune aggiunte al repertorio delle istruzioni. In genere s'introduce per l'unità centrale una coppia di stati: uno stato supervisivo, da utilizzare mentre essa sta eseguendo il supervisore, e uno normale per l'esecuzione degli altri programmi. L'esecuzione di un'interruzione o di istruzioni apposite (che servono appunto per chiamare in azione il supervisore) pone l'unità centrale nello stato supervisivo, da cui si può tornare a quello normale solo con l'esecuzione di un'apposita istruzione. Alcune istruzioni, poi, sono eseguibili solo nello stato supervisivo e perciò sono riservate al solo supervisore. Tali sono le istruzioni relative alle unità periferiche, in modo che al supervisore è riservata la loro gestione, e se un programma normale vuole usarle ne deve fare richiesta al supervisore.
Altre istruzioni riservate al supervisore sono quelle di accesso ai registri relativi alle interruzioni e alla protezione della memoria. S'introducono infatti dei registri di protezione della memoria, che indicano quale zona di memoria può essere usata correntemente nello stato normale. Il tentativo di accedere ad altre zone fa sì che l'accesso non avvenga e si abbia un'interruzione, con conseguente entrata in azione del supervisore, che provvederà alle azioni opportune, quali per es. la stampa di un messaggio di avvertimento e l'espulsione del programma che ha cercato di evadere dalla zona di memoria assegnatagli.
Naturalmente il supervisore, prima di avviare un normale programma, provvede a inserire nei registri di protezione della memoria i dati che indicano la zona assegnata a tale programma. Una speciale istruzione di salto, che mette l'unità centrale nello stato normale, permette di passare dal supervisore ai normali programmi.
Se l'e. ha più unità centrali, una di esse può essere dedicata a eseguire il supervisore oltre ai normali programmi, oppure, più utilmente, tutte le unità possono a turno svolgere tale funzione, che non deve assorbire altro che una piccola frazione della potenza elaborativa disponibile.
Ci occuperemo ora del problema della gestione dei trasferimenti di operandi, risultati, programmi fra la memoria secondaria (attualmente, in genere, formata da dischi magnetici) e quella di lavoro. Questo è un compito piuttosto noioso che si sovrappone all'usuale lavoro di programmazione e che non riguarda gli algoritmi da usare per risolvere il problema, ma è qualcosa relativo al particolare e. in uso.
È ovvia perciò la convenienza di avere un sistema d'indirizzamento e di trasferimento automatico di dati fra memoria di lavoro e secondaria, in modo che il programmatore possa indirizzare (anche a livello di linguaggio macchina) una memoria di capacità pari a quella dei dischi magnetici disponibili e di velocità operativa molto prossima a quella della memoria di lavoro. Un tale sistema assume il nome di memoria virtuale e ha pregi notevoli, se si tiene presente che il rapporto fra le capacità (espresse, per es., in bit) fra memoria secondaria e memoria primaria può essere dell'ordine di 104, mentre il rapporto fra le velocità operative può valutarsi attorno a 10−4, anche se in modo grossolano, date le diverse modalità di accesso nei due tipi di memoria.
Poiché il trasferimento di dati con le memorie a disco è conveniente farlo per blocchi di almeno un centinaio di byte, l'insieme degli indirizzi della memoria virtuale è anche diviso in blocchi. Così, per ogni accesso alla memoria virtuale, il governo della memoria principale controlla se il blocco che contiene tale indirizzo è o no nella memoria principale stessa e, se non vi si trova, richiede al supervisore il suo trasferimento dalla memoria a disco magnetico. L'esperienza mostra che, sia nei grandi e. che nei minori, l'osservanza di qualche semplice accortezza nell'uso della memoria virtuale permette di ottenere che solo per qualche percento degli accessi alla memoria è necessario ricorrere a trasferimenti dalla memoria secondaria. Si sottolinea che una memoria virtuale consente anche di risolvere i problemi di riallocazione di operandi e di programmi di cui si era trattato precedentemente e che memorie virtuali sono presenti non solo negli e. dei grandi impianti, ma anche nei microelaboratori.
Il concetto di memoria virtuale può però estendersi a una gerarchia più ampia e dotata di: una memoria secondaria (a dischi, oggi), una memoria primaria (a semiconduttori, oggi) e una memoria ''nascosta'' (in inglese cache) che è anche a semiconduttori, ma con una tecnologia più veloce, oltre che con un costo maggiore per bit registrato. È però da notare che in questo caso la differenza fra le velocità di accesso fra memoria nascosta e memoria primaria è di un solo ordine di grandezza, e che non è necessario fare trasferimenti per grossi blocchi di dati come nel caso dei dischi. Perciò, anche se restano i concetti della memoria virtuale a due soli livelli, la realizzazione della cache può essere assai diversa e, nel caso di trasferimenti fra memoria principale e memoria nascosta, non ha luogo la chiamata di supervisore ma, per es., si ha l'entrata in azione di un microprogramma dell'unità centrale o del governo della memoria principale.
Ricordiamo sommariamente che l'esecuzione di un'istruzione (o di qualunque operazione complessa) può essere decomposta nell'esecuzione di una sequenza di istruzioni a livello più elementare dette microistruzioni, le quali specificano essenzialmente operazioni di trasferimento fra registri e organi operativi di un e. o di una sua unità. Le microistruzioni corrispondenti all'esecuzione di un'istruzione (o di un'operazione complessa) formano un microprogramma. Così il progetto e la realizzazione di un organo di governo possono essere fatti mediante microprogrammi, basati su microistruzioni che specificano le operazioni elementari in cui può essere decomposta l'esecuzione di un'istruzione del linguaggio di macchina dell'elaboratore.
Accenniamo anche ai governi anticipativi (look-ahead), cioè a governi capaci di registrare, accodandole, più istruzioni, in modo che il reperimento dei loro operandi e l'esecuzione delle operazioni su di esse può essere fatto anticipatamente, tenendo occupati la memoria principale e il massimo numero di organi aritmetici e operativi per il maggior tempo possibile. Ciò implica, naturalmente, che tali organi siano decomposti in parti che possono operare più o meno indipendentemente le une dalle altre.
La tecnica di decomporre l'esecuzione di un'operazione complessa in operazioni elementari da eseguire in sequenza, in modo che più operazioni complesse possano trovarsi in stadi successivi, collocati ''in cascata'', di una sorta di ''linea di montaggio'', in ciascuno stadio della quale si esegue un'operazione elementare, è nota come pipelining e la ''linea di montaggio'' è chiamata appunto pipeline (cascata). Di questa tecnica si parlerà nel seguito a proposito dei supercalcolatori e degli e. ad alto parallelismo.
Accenniamo infine alle unità periferiche degli e., che possiamo dividere in unità di memoria secondaria, in unità d'ingresso e unità di uscita (anche se alcune unità possono svolgere tutte e tre tali funzioni), dicendo anche che il progresso della tecnologia relativa a esse, che spesso è di tipo elettromeccanico, è anche molto rapido, come accade per le tecnologie di tipo elettronico.
La tecnologia dominante per le memorie secondarie è, dall'inizio degli anni Settanta, quella del disco magnetico, diffusasi nella decade successiva anche ai microelaboratori, portatili o meno. Oltre ai dischi rigidi, costituiti da un supporto metallico rigido dato da uno o più dischi sovrapposti e coperti di materiale magnetico, si sono enormemente diffusi i dischetti o dischi flosci (floppy discs) che sono costituiti da un disco ritagliato da un foglio di plastica ricoperto di materiale magnetico e contenuto in una custodia più o meno rigida. I dischetti sono asportabili e perciò possono essere usati sia come memoria secondaria, sia per far entrare, sia per far uscire dati da un elaboratore.
L'esperienza quotidiana ha reso familiari anche: stampanti, tastiere, video, nastri magnetici, lettori ottici dei codici a barre per negozi, supermercati, ecc. Meno noti sono i sensori e gli attuatori usati nel controllo di impianti e di apparati, e i modem, cioè gli apparecchi modulatori-demodulatori necessari per il collegamento a linee di trasmissione di dati.
Sensore è un apparecchio che misura una grandezza fisica; attuatore un organo elettromeccanico che, al comando di un segnale, provoca dei movimenti di parti meccaniche, valvole per fluidi, ecc. I robot hanno sensori di capacità, flessibilità e complessità notevoli, che spesso sono dotati di microprocessori propri. Stessa cosa, però, si può dire per gli attuatori e per gran parte delle unità periferiche di un e. o di un impianto di elaborazione.
Comunque un'unità periferica, che fa parte di un e. rispondente allo schema della fig. 2, è in genere dotata di un proprio governo (detto, appunto, di unità periferica), che la adatta a funzionare con i canali di quel tipo di elaboratore. Questi canali presentano infatti verso le unità periferiche un'interfaccia standard a cui il governo di ciascun tipo di unità deve adeguarsi, per un certo tipo di elaboratore. Le interfacce dei canali (o degli altri organi con funzioni simili) verso le altre unità periferiche tendono a uniformarsi, almeno nell'ambito di una stessa famiglia. Una famiglia di e. è un insieme di tipi di e. con capacità e velocità crescenti e compatibili verso l'alto, cioè tali che i programmi in linguaggio macchina dei tipi con minore capacità e velocità possono essere eseguiti anche da e. maggiori della stessa famiglia.
Elaboratori paralleli. - Gli schemi di architettura di e. che abbiamo considerato contengono già dei gradi di parallelismo; per es., hanno la capacità di operare contemporaneamente su tutti i bit di un operando per eseguire un'operazione aritmetica invece che operare su di essi cifra a cifra. Oppure possono eseguire contemporaneamente fasi diverse di istruzioni successive, come nel caso dei governi anticipativi o come nel caso di un'unità aritmetica con più stadi in cascata (pipeline). Abbiamo anche visto la possibilità di avere un sistema di elaborazione con più unità centrali collegate al bus centrale. Perciò ci si può chiedere quali architetture è possibile concepire con numeri più o meno grandi di unità centrali o di coppie unità centrale-memoria principale, che possono essere considerate ciascuna un e. a sé stante.
Una tassonomia degli e. paralleli, cioè formati con più e. usuali o con più unità centrali, è dovuta a M.J. Flynn e fa riferimento alle sequenze di istruzioni e alle sequenze di operandi che un generico e. parallelo è capace di trattare contemporaneamente. Le architetture più semplici (quelle che in gran parte abbiamo trattato fin qui) corrispondono al tipo SISD (Single Instruction-stream, Single Data-stream) in cui viene eseguita un'istruzione alla volta (di un'eventuale singola sequenza di istruzioni) su un solo operando alla volta (di un'eventuale singola sequenza di operandi).
Altro tipo nella tassonomia di Flynn è il SIMD (Single Instructionstream, Multiple Data-stream) in cui si esegue contemporaneamente una sola istruzione alla volta su più dati per mezzo di più unità di elaborazione, che ricevono l'istruzione da eseguire da un e. centrale, come nell'esempio in fig. 3A.
In questa un processore P0 trasmette una stessa istruzione ai processori P1, P2,...Pn, ciascuno dotato della propria memoria M1, M2,...,Mn. I processori P1,...Pn possono pensarsi come delle unità centrali. Una rete d'interconnessione I collega i vari processori. Altri collegamenti (per es. per le operazioni d'ingresso e di uscita) non sono mostrati per semplicità.
Altro tipo di architettura è il tipo MISD (Multiple Instructionstreams, Single Data-stream) in cui contemporaneamente si eseguono in cascata più (sequenze di) istruzioni su un'unica sequenza di dati. Questo è un esempio tipico di pipelining di cui è trattato prima.
Nella fig. 3B i processori P1, P2,...,Pn elaborano in cascata i dati che provengono dalla memoria M, a cui tornano i risultati che escono da Pn. La memoria M può pensarsi come un'unica memoria, anche se ognuno dei P potrà avere necessità di usufruire di una propria memoria per lavorare. Lo schema indicato è, anche in questo caso, semplificato al massimo.
Ultimo tipo di architettura nella tassonomia che consideriamo è quello MIMD (Multiple Instruction-stream, Multiple Data-stream) in cui si hanno più e. con memoria propria e/o memoria comune condivisa, operanti su varie sequenze di operandi con vari programmi.
Un modo per realizzare questo tipo è quello di collegare più unità centrali (eventualmente dotate anche di memoria propria) al bus centrale dello schema di architettura avanzata alla von Neumann del precedente paragrafo. Però con questo schema non si riesce a collegare più di qualche unità centrale senza provocare ingorghi sul bus centrale o sull'accesso alla memoria, a meno di particolari condizioni del carico di lavoro.
Tuttavia con un numero maggiore di unità centrali (o di processori) si presenta il fatto che, a seconda del problema da risolvere e perciò degli algoritmi da realizzare, occorre prevedere una rete di connessione ad hoc per un'elaborazione efficiente. Perciò per e. paralleli di uso universale occorre prevedere un sistema di connessione variabile dinamicamente, cioè al variare del tipo di elaborazione. Dato il costo e la complessità di un insieme di connessioni indipendenti e permanenti, fra ogni processore e ciascuno degli altri, tale sistema non è accettato (almeno attualmente), e si hanno vari tipi di sistemi più o meno semplici di connessioni.
Queste in genere permettono di collegare direttamente un processore a solo pochi altri, il che può essere efficiente per alcuni tipi di problemi, ma non per altri. Perciò si sono spesso usate reti multistadio, in cui uno stadio della rete permette il collegamento di un processore a pochi altri di un certo insieme, ma attraverso più stadi è possibile collegare un processore a tutti i rimanenti (o quasi).
Per quanto riguarda gli e. paralleli di tipo MIMD occorre osservare che due architetture tipiche sono quella a memoria condivisa e quella a trasmissione di messaggi. Nella prima tutti i processori condividono un'unica memoria di lavoro, che però tende a divenire il collo di bottiglia del sistema per quanti artifici si possano introdurre. Nella seconda architettura ogni processore possiede una propria memoria e interagisce con gli altri mediante scambio di messaggi (consistenti in istruzioni e operandi), e questo pone problemi di velocità quando l'interazione è frequente.
Da questo punto di vista è importante il parametro detto granularità, cioè il rapporto fra il tempo impiegato per le elaborazioni e quello per le comunicazioni. Una grande granularità indica che i processori operano in modo relativamente indipendente, mentre una granularità fine indica il caso opposto.
Non ci addentreremo nella descrizione ulteriore delle architetture degli e. paralleli data la sperimentalità di gran parte di quelli proposti o prodotti, se non per dire che esse sono usate essenzialmente o per i supercalcolatori (v. oltre) o per usi particolari, in cui una particolare architettura parallela si adatta a una particolare classe di problemi, poiché un'architettura parallela efficientemente impiegabile per uso universale non è stata ancora trovata, e forse le architetture massicciamente parallele (cioè composte da migliaia o milioni di processori) saranno usate diffusamente quando si accetterà la loro inefficienza (nel senso odierno) per molte classi di problemi.
Supercalcolatori. - Sono gli e. che usano il parallelismo per raggiungere velocità maggiori di quelle consentite dalla tecnologia corrente per gli e. non paralleli. Gran parte di quelli commercialmente in uso sono specializzati al trattamento di problemi numerici relativi a calcolo su vettori e appartengono in genere al tipo SIMD (o sono costituiti da pochi elaboratori SIMD collegati come MIMD).
Fino a ora, però, il supercalcolatore è stato raggiunto in termini di velocità dagli e. normali (o addirittura da microelaboratori) in 10÷15 anni, con un rapporto di costi compreso fra 1000 e 10.000. Perciò, se si è disposti ad aspettare per il tempo suddetto, si può avere la stessa velocità a un costo molto inferiore. È anche da notare che il progresso tecnologico, in termini sia di elettronica che di meccanica, ha più volte superato limiti teorici considerati invalicabili.
Macchine per basi di dati (data-base machines). − Sono e. (del tipo SIMD o MIMD, in genere) usati, come ausiliari di altri e., per le operazioni su basi di dati (v. informatica, in questa Appendice). Il loro uso e la loro diffusione sono limitati, anche se fin dagli anni Settanta sono stati prodotti e anche venduti vari tipi di questi elaboratori.
Elaboratori per linguaggi funzionali o logici. - Sono e. pensati per interpretare o per tradurre efficientemente linguaggi funzionali (v. informatica, in questa Appendice) oppure linguaggi logici, anche se per quest'ultimo tipo non si è arrivati oltre il livello di prototipo. Fra quelli del primo tipo, gli e. orientati verso il LISP (un particolare linguaggio funzionale) e perciò noti come lisp-machines, hanno avuto diffusione apprezzabile. Piuttosto sommariamente si può dire che spesso essi aggiungono a una macchina di von Neumann caratteristiche architettoniche e istruzioni per un efficiente e veloce uso di sottoprogrammi e di strutture di dati dinamiche dette ''liste''.
Accenniamo infine a qualche altro tipo di architettura di diffusione limitata essenzialmente a prototipi o ad applicazioni assai particolari.
Schiere sistoliche (systolic arrays). − Sono schiere di processori (o di organi aritmetici) disposti su due dimensioni e che comunicano ciascuno con n vicini (n=4 o 6, per es.). L'architettura SIMD, illustrata precedentemente, può essere considerata come una schiera sistolica a una dimensione. Poiché i processori operano sincronicamente, il flusso dei dati attraverso una schiera avviene ritmicamente, e da qui origina il nome, per analogia con il battito cardiaco.
Architetture a flusso di dati (data flow). − Sono architetture che cercano di simulare una situazione in cui per ogni operazione elementare da compiere c'è un elemento di calcolo che riceve gli operandi quando sono disponibili da altri elementi simili e fornisce i risultati ad altri elementi di calcolo. In un certo senso l'idea di base è simile a quella dei calcolatori analogici, però realizzata in modo diverso e più efficiente. Lo sviluppo di queste architetture è però condizionato da considerazioni di efficienza e dallo sviluppo di linguaggi adatti.
Reti neurali. - Sono schiere di elementi che simulano alcuni aspetti del comportamento dei neuroni. In particolare si considera spesso che tali elementi diano in uscita uno di due (o di pochi) possibili valori solo quando la somma pesata degli ingressi supera una certa soglia, il cui valore può eventualmente essere variato per simulare, per es., una sorta di apprendimento. Furono oggetto di molte ricerche fra la seconda metà degli anni Cinquanta e quella degli anni Sessanta, specie nel campo del riconoscimento di figure, ma furono poi trascurate per limitazioni nelle capacità computazionali. Recentemente, però, si è risvegliato un certo interesse in tali reti anche contando su nuovi progressi tecnologici o su applicazioni particolari di algoritmi di ottimizzazione modellabili con il comportamento di reti del genere.
Bibl.: A.S. Tannenbaum, Structured computer organization, Englewood Cliffs (N.J.) 19882; K. Hwang, F.A. Briggs, Computer architecture and parallel processing, Singapore 19922.