Due cose Amiga ha portato alle masse, facendone al contempo i propri cavalli di battaglia: il multitasking e i coprocessori dedicati. Molti ricorderanno ancora la mascella a terra (per non dire altro) guardando le finestre e gli schermi (Copper docet) sul Workbench che facevano girare applicazioni diverse simultaneamente, sfoggiando anche grafica elaborata in tempo reale (e qui… Blitter docet!).
Infatti l’Amiga, non mi stancherò mai di ripeterlo, è stato un eccellente connubio fra sistema operativo (AmigaOS) e hardware dedicato, nato da menti geniali che hanno saputo pensare tanto ai programmatori quanto all’utenza finale.
La presenza di coprocessori dedicati per svolgere alcuni compiti, sgravando di conseguenza la CPU, permette, a mio avviso, di parlare già di ASMP (multiprocessing asimmetrico), sebbene generalmente il termine sia utilizzato in sistemi in cui i processori appartengono alla stessa famiglia o sono molto simili.
Se per “processore” intendiamo, come in letteratura, un “elemento che processa”, cioè che elabora delle informazioni, esegue delle operazioni o delle azioni, ecc., non dovrebbero esservi dubbi sul fatto che l’uso dell’etichetta ASMP sia perfettamente legittimo.
Nel precedente articolo riguardo agli scenari futuri dell’Amiga non ho mai parlato esplicitamente né di SMP né di ASMP per non appesantirlo troppo, e per affrontare l’argomento (che si trascina da tempo, e se ne parla infatti sia per il progetto Natami, che per AROS e altri s.o. AmigaOS-like o derivati) dedicandogli ben più di qualche riga.
Soprattutto non voglio separarlo nettamente fra SMP e ASMP, ma suddividere ulteriormente quest’ultimo in appositi scenari più “specializzati” e non mutuamente esclusivi, quanto piuttosto sovrapponibili (quindi alcuni, o anche tutti, possono coesistere).
Partendo proprio dai coprocessori presenti nel chipset, abbiamo già visto che l’intenzione era quella di migliorarli, aggiungendone anche altri dedicati a precisi scopi, come ad esempio il 3D, il cui supporto nativo (visto che comunque grazie a Blitter e/o CPU era possibile simularlo) era assente.
Quando parlo di coprocessori in quest’ambito, mi riferisco sempre a processori dedicati dotati di funzionalità “fisse” (fixed function, in gergo), pertanto con scarsa o nulla programmabilità. Per rendere meglio l’idea, potremmo considerare tale un chip che si occupa esclusivamente di fungere da modem, oppure un altro che miscela più canali sonori per generare l’output finale (magari con effetti predefiniti selezionabili), un’unità di de/compressione di suoni compressi, ecc.
Un’altra forma di ASMP, ma più sofisticata e appetibile per uno sviluppatore, riguarda l’aggiunta di processori programmabili, come il DSP 3210 di AT&T che Dave Haynie aveva integrato nel prototipo Amiga 3000+ di cui abbiamo parlato in un altro articolo.
Si tratta di una soluzione sicuramente molto più costosa rispetto a un processore dedicato a un ben preciso scopo, ma che mette a disposizione una flessibilità e potenza di calcolo enorme. Il 3210 permetteva, tra l’altro, di essere collegato ad altri DSP della stessa famiglia, e di eseguire in parallelo un s.o. dedicato con task / processi annessi.
Trattandosi di caratteristiche del tutto nuove, eventuali incompatibilità sono completamente assenti: non si può, infatti, programmare male un processore che prima era assolutamente inesistente, giusto per fare un confronto coi problemi causati dall’aggiornamento della sezione video del chipset AGA.
L’adozione di DSP altamente programmabili apre, però, altre questioni. Prima di tutto sceglierne uno o una famiglia (supponendo che i vari membri della medesima siano fra loro compatibili, o almeno retrocompatibili per i modelli più nuovi rispetto ai predecessori) significa anche legarvisi mani e piedi, come si suol dire, in quanto lo sviluppo di applicazioni che ne faranno uso aggiungerà un (pesante) vincolo alle future evoluzioni delle macchine.
Per essere chiari, non si potrebbe poi passare a un nuovo DSP della Texas Instruments, per quanto “mostruoso” potesse essere, se venisse a mancare la retrocompabilità con l’esistente (cosa ovvia in questi casi, andando a pescare da vendor diversi).
Altra cosa molto importante, l’adozione di coprocessori con architetture diverse da quella della CPU principale giocoforza introduce l’obbligo di doverne studiare un’altra, appunto. E se non si tratta di smazzarsi i manuali di riferimento della casa madre per programmarvi in assembly, in ogni caso serve conoscerne le caratteristiche di targa, e come compilare e far eseguire le applicazioni realizzate ad hoc.
Una soluzione scontata è quella di dotare un sistema di ASMP di processori della stessa famiglia, o addirittura esattamente gli stessi, della CPU. L’architettura unica ha indubbi vantaggi, perché consente di riciclare le stesse, o almeno una buona parte, delle conoscenze acquisite col microprocessore “dominante”.
Si tratta di un approccio che è stato scelto di recente per Natami, che inizialmente prevedeva di affiancare all’N050 (CPU di derivazione Motorola 68000 ovviamente) un coprocessore basato su un RISC (molto semplice) appositamente progettato per prendersi carico di massicci calcoli in virgola mobile o interi.
Un processore basato sullo stesso, identico, N050, a cui verranno aggiunte delle capacità di calcolo vettoriale per valori interi e in virgola mobile (approccio SIMD), è una soluzione a mio avviso (e per il lavoro che faccio) di gran lunga preferibile rispetto a un nuovo RISC che avrebbe costretto i coder a ripartire da zero per sfruttarlo.
Ciò non toglie che le due soluzioni abbiano dei costi decisamente diversi, in quanto il core N050 richiede molta più logica / transistor rispetto a quello RISC, trattandosi di un processore nettamente più complesso (e che tra l’altro raggiunge velocità di clock più ridotte). Ma evidentemente i progettisti hanno ritenuto complessivamente “migliore” il progetto basato su N050.
La naturale conseguenza è chiedersi come mai gli stessi processori si dovrebbero utilizzare come coprocessori, e non affiancarli invece a quello principale, dividendosi quindi equamente (se possibile) tutti i compiti (modello SMP, appunto).
D’altra parte, e come abbiamo citato all’inizio, Amiga nasce come sistema multitasking, per cui riuscire ad assegnare i vari task a più processori potrebbe portare a notevoli vantaggi prestazionali in situazioni di forte carico.
Purtroppo per AmigaOS quello che potrebbe sembrare l’uovo di Colombo in realtà pone problemi di difficile soluzione, a causa dell’enorme macigno che fa capo alla retrocompabilità con le applicazioni già scritte (male).
Sulla carta questo s.o. espone l’API Forbid() per disabilitare il multitasking (e Permit() per riabilitarlo), oltre a decine di altre API per gestire semafori et similia, da usare nei casi più critici in cui si vuol esser sicuri di essere gli unici a manipolare certe strutture delicate (come anche quelle dello stesso s.o.).
Queste API vanno a modificare un preciso parametro di ExecBase (la struttura base del kernel, Exec), TDNestCnt (task disable nesting count), che serve a tenere il conto delle varie chiamate effettuate a quest’API (o alla duale), fino all’azzeramento che comporta la riabilitazione del multitasking.
Quest’API si sarebbe potuta patchare opportunamente, in modo da utilizzare delle istruzioni atomiche verso la memoria per garantirsi l’acquisizione o meno della risorsa senza incorrere nei famigerati casi di race condition che si potrebbero verificare.
Purtroppo tanti programmatori hanno pensato bene di risparmiare qualche ciclo di clock, evitando di richiamare l’API, e manipolando direttamente questo campo con tutte le implicazioni che possiamo immaginare dovute dall’infausta operazione.
Il risultato è che per Natami molto probabilmente la soluzione arriverà da un meccanismo di locking & sequenzializzazione di questa specifica locazione di memoria, in modo da regolarne rigorosamente l’accesso. Questo sarà possibile grazie al fatto che Natami è sostanzialmente un SoC, per cui avendo tutto integrato (anche il chipset) può permettersi il lusso di tenere sotto controllo tutto.
Lo stesso ragionamento non si può fare con un sistema SMP classico, cioè dotato di CPU che risiedono in socket diversi (o comunque isolate, se sono contenute nello stesso package), poiché senza un robusto meccanismo di arbitraggio di TDNestCnt i problemi rimangono dietro l’angolo.
Oltretutto l’SMP pone anche quello del bilanciamento del carico sui processori esistenti, in modo da massimizzarne lo sfruttamento. Aggiungiamo, infine, che serve pure stabilire se una CPU debba fare da master, in modo da prendersi carico soltanto lei della gestione del multitasking e/o degli interrupt di sistema, e dell’accesso all’hardware.
Tutti problemi di non banale soluzione di cui un’evoluzione dell’Amiga, sia essa intesa come hardware e/o come AmigaOS, deve tenere assolutamente conto. Da questo punto di vista l’ASMP è certamente più comodo, in quanto o non si pone il problema (gli interrupt li gestisce il core principale, ad esempio), oppure è la CPU che mette i coprocessori in condizione di lavorare in maniera “sicura”, assegnando loro specifici compiti con precise risorse a disposizione.
Fortunatamente non tutte le soluzioni sono mutuamente esclusive e, anzi, persino modelli ibridi SMP / ASMP potrebbero benissimo esistere e convivere senza “pestarsi i piedi”, migliorando le prestazioni del sistema.
Lato mio aggiungo soltanto un paio di cose. Personalmente trovo l’ASMP una soluzione migliore dati i problemi che sussistono con le attuali versioni di AmigaOS. ASMP implementato sfruttando la stessa CPU (o “affine”) della macchina, chiaramente.
La seconda, e chiudo, è che immagino un sistema ASMP dotato di un arbitro che si occupa, oltre alla gestione del bus di connessione coi vari core ASMP, anche di schedulare opportunamente i lavori (job) che gli arrivano, sfruttando una coda per depositarli in ordine di priorità e/o di arrivo, e facendo uso di una funzione di callback per avvisare eventualmente il task “mandante” della fine del job.
In questo modo i programmatori non devono nemmeno sbattere la testa contro i muri per cercare di suddividere preventivamente il lavoro da fare sulla base del numero di processori esistenti, ma è l’arbitro / schedulatore a occuparsi di ricevere dei job più piccoli, da passare ai processori man mano che si liberano, ottimizzando il tutto (sempre nei limiti del possibile).
Non nascondo il fatto che sono rimasto particolarmente affascinato dall’architettura di Larrabee, grazie alla commistione fra un’ISA ben nota (x86) e una potente nonché elegante unità SIMD di nuova generazione.
In ogni caso la scelta fra SMP e ASMP, o magari di soluzioni ibride, per Amiga e/o AmigaOS (e derivati) sarebbe stata soltanto rimandata, perché è fuor di dubbio che il futuro sarà dominato da soluzioni multicore, poiché scalare in frequenza s’è rivelata un’impresa alquanto ardua e difficile da attuare.
Forse non sarebbe male prendere in seria considerazione l’idea di dare un taglio alla retrocompatibilità, mettendoci l’anima in pace se un’applicazione scritta male non funzionerà più (o, peggio, creerà problemi) in un sistema SMP…