Molte volte ci siamo trovati a parlare di architetture hardware, usando terminologie come RISC, CISC e così via. Cerchiamo quindi di entrare nel dettaglio per approfondire, e avere ben chiaro in che modo funzionino queste due tipologie di architettura, arrivando anche a capire quali siano i pro e i contro dell’una e dell’altra.
Quando parliamo di CPU, ci riferiamo alla Central Processing Unit. Siamo abituati a considerare la CPU come una “black box” che si occupa dell’esecuzione delle operazioni a velocità elevatissime. Cosa troviamo all’interno, se decidiamo di aprire la scatola? La risposta a questa domanda è molto semplice: un “set di istruzioni“. Questo set di istruzioni può essere di due tipi: Reduced Instruction Set Computing e Complex Instruction Set Computing.
Il set di istruzioni è, di fatto, il libro di grammatica e conversazione che vi serve per poter comunicare con il processore. Attraverso il “linguaggio macchina” infatti, sarete in grado di scrivere programmi e impartire istruzioni alla CPU.
RISC
L’architettura RISC è semplice e lineare, permettendo al microprocessore di esegure il set di istruzioni in tempi molto rapidi e inferiori ai tempi dell’architettura CISC. Il primo concetto che occorre comprendere è che “Set di istruzioni ridotto” non vuol dire “incompleto“. Semplicemente, il set a disposizione non presenta tecniche di indirizzamento particolareggiate o raramente utilizzate; se da un lato la velocità è il punto forte, di contro si ha lo svantaggio che, avendo a disposizione solo istruzioni semplici, la scrittura di un codice è più lunga e pertanto occupa più spazio in memoria. La maggior parte dei comandi viene completata in un ciclo macchina.
CISC
L’architettura CISC è formata da un set di istruzioni in grado di eseguire operazioni molto più complesse rispetto all’architettura RISC. E’ infatti possibile utilizzare una sola istruzione per leggere un dato in memoria, modificarlo e salvarlo nuovamente, cosa impensabile con un set di istruzioni ridotto. Sebbene questo tipo di architettura non abbia la velocità di quella RISC, ha il vantaggio di poter realizzare programmi più compatti che occupano un minor spazio in memoria. I programmi in questione sono però più “pesanti“, e richiedono molto tempo per l’esecuzione. Un singolo set di istruzioni è eseguito in più passaggi; ogni set di istruzioni ha oltre 300 istruzioni separate. Le istruzioni vengono completate in 2-10 cicli macchina.
Un po’ di storia
Per meglio comprendere le ragioni di queste due scuole di pensiero, è utile soffermarsi un momento sulle motivazioni che hanno portato i progettisti a percorrere queste due strade.
Agli albori dell’industria informatica, quelli che al giorno d’oggi chiamiamo “compilatori”, non esistevano (ma teneteli a mente!). I programmatori erano soliti scrivere in linguaggio macchina o in linguaggio assembly. Questa necessità di scrivere in linguaggio macchina rendeva davvero ostico l’avvicinamento alla programmazione, pertanto si decise di introdurre istruzioni molto complesse all’interno del set di istruzioni dei processori, in modo tale da poter “simulare” le funzioni ad alto livello dei linguaggi di programmazione.
Questa complessità delle istruzioni rispondeva alla necessità di dover assolutamente risparmiare memoria, poichè all’epoca (a differenza di oggi), la memoria era costosissima e non ci si poteva di certo permettere di aumentarla alla leggera e ogni qual volta occorresse. I processori erano concepiti per avere codifiche delle stringhe di bit a lunghezza variabile, in modo tale da poter definire le istruzioni e massimizzarne la densità. Stiamo parlando di un’epoca in cui un hard disk da 5Mb (sì, avete capito giusto, 5 Megabyte) pesava una tonnellata e costava migliaia di dollari.
Vi sembra tutto molto strano vero? In effetti lo è. Vi basti pensare che le CPU di quegli anni erano dotate di pochi registri perchè costava tantissimo implementare bit all’interno di un processore e una quantità ingente di registri avrebbe aumentato a dismisura il numero dei transistor.
L’unica soluzione possibile e percorribile, era quella di realizzare processori in grado di eseguire operazioni con diverse tipologie di indirizzamento, grazie alla cosiddetta “ortogonalità delle istruzioni“, utilizzando quindi memorie e registri come ingressi e uscite.
Vi ricordate che vi avevo detto di tenere a mente la questione dei compilatori? Ecco, è il 1957 quando il team Fortran guidato da John Backus, un informatico e matematico dell’IBM, realizza uno dei primi linguaggi di programmazione, il “FORTRAN” per l’appunto, acronimo di “FORmula TRANslation”. IBM infatti aveva compreso la difficoltà data dal linguaggio macchina e dal linguaggio Assembly, pertanto aveva iniziato delle ricerche per creare un linguaggio di programmazione meno ostico e più vicino al linguaggio naturale.
Con la nascita del COBOL (COmmon Business Oriented Language), l’epoca dei compilatori ebbe ufficialmente inizio.
La rapidissima diffusione dei compilatori portò un mutamento irreversibile nella concezione dei processori e nelle loro applicazioni. Studi approfonditi rivelarono che, a causa dell’utilizzo ormai consolidato e diffuso di quest’ultimi, la maggior parte dei metodi di indirizzamento complesso aveva smesso di essere utilizzata. All’orizzonte si prefigurava già un problema che avrebbe fatto venire più di un mal di testa ai progettisti: il rapporto tra CPU e Memoria.
Sebbene la velocità delle CPU e delle Memorie fosse simile in quel periodo, era ormai risaputo che la velocità dei processori sarebbe aumentata molto rapidamente, mentre quella delle memorie sarebbe rimasta molto indietro. Questo avrebbe vanificato ogni progresso, poichè i continui accessi di un processore veloce ad una memoria più lenta, avrebbero generato un evidente calo di prestazioni.
Oltre ai problemi inerenti all’hardware e al suo sfruttamento, un’analisi dei programmi abitualmente utilizzati all’epoca evidenziò che CPU così veloci non avessero ragion d’essere, se raffrontate ai programmi che avrebbero dovuto far girare. Andrew Stuart Tanenbaum (se non sapete chi sia, chiedete a Linus Torvalds) fu uno dei primi a evidenziare questo problema, offrendo anche la soluzione mediante la quale il 98% delle costanti di un programma potesse essere memorizzato nei bit non utilizzati del set di istruzioni del processore, piuttosto che nella memoria.
L’eliminazione di istruzioni complesse o poco usate, diede vita ad un set di istruzioni più semplice e rapido da far girare. Questa riduzione delle istruzioni, portò alla creazione del Reduced Instruction Set Computing, in contrapposizione al Complex Instruction Set Computing.
Quale è meglio?
Eccoci arrivati alla fatidica domanda. La risposta potrebbe sorprendere. Iniziamo intanto dicendo che entrambe le architetture sono sopravvissute a decenni di sviluppo. Intel (x86) e AMD prediligono l’architettura CISC, mentre Apple ha percorso la strada della RISC, sebbene negli ultimi anni anche Apple abbia deciso di passare a processori Intel Core (per poi tornare alle origini nel 2020). Allo stato attuale delle cose, possiamo dire che le barriere tra le due architetture, di fatto non esistono più. Quando le due tipologie di architettura iniziarono a “darsi battaglia” erano infatti gli anni ’80 e i problemi da affrontare erano grosso modo due: l’area del chip e la complessità progettuale dei processori.
All’epoca il mercato era dominato dai PC Desktop e dai Server, adesso il mondo della tecnologia e di conseguenza dell’informatica, è cambiato completamente: con l’avvento di tablet, smartphone e sempre più dispositivi portatili, l’aspetto fondamentale è diventato quello del consumo energetico e della relativa ottimizzazione. Uno studio del 2015, compiuto dall’Università del Wisconsin denominato “ISA Wars: Understanding the Relevance of ISA being CISC or RISC“, ha evidenziato quanto non ci sia alcuna differenza rilevante tra le differenti Instruction Set Architecture (insieme di istruzioni). Laddove un’ISA è carente rispetto ad un’altra, la microelettronica presente all’interno del processore ne compensa le mancanze.
Infine, occorre ricordare che in’ISA meno complessa, come nei RISC, è suscettibile di maggiore miniaturizzazione (consentendo ulteriori step della Legge di Moore) ove la tecnologia CISC è invece giunta ad un limite fisico. Anche a livello di calcolo distribuito in’ISA RISC (consumando meno) risulta favotrita a parità di consumi.