Nei sistemi embedded la crescente diffusione dei processori multicore comporta oggi una notevole complicazione della programmazione. Queste applicazioni, infatti, sono spesso caratterizzate dal riutilizzo di software preesistente (“legacy”) e open source nato per processori a singolo core, software che deve quindi essere “parallelizzato” e ripartito tra i vari core che compongono il nuovo processore. Per di più le piattaforme hardware utilizzate nelle applicazioni embedded sono spesso eterogenee, composte cioè di core diversi tra loro, acceleratori hardware e altre risorse. La valutazione delle diverse opzioni e la correzione degli inevitabili errori rendono quindi il “multicore porting” un processo molto lento. Oggi uno strumento realizzato dall’olandese Vector Fabrics si propone di aumentare drasticamente la produttività dei programmatori impegnati nel multicore porting dei programmi scritti in linguaggio C, inizialmente con riferimento a due piattaforme target molto diffuse: Arm Cortex A9 e x86. Il prodotto, denominato vfEmbedded, costituisce un’evoluzione del preesistente vfAnalyst, di cui Selezione di Elettronica si è già occupata lo scorso anno. Anche il nuovo tool, come il precedente, viene offerto tramite web con la formula “software-as-a-service” sulla base di una tariffa mensile.
La parallelizzazione del codice
Poiché vfEmbedded comprende al proprio interno il preesistente vfAnalyst, è utile ricordare brevemente le caratteristiche di quest’ultimo prodotto. Nell’ambito della nuova soluzione le funzioni di vfAnalyst sono utilizzate per svolgere la prima fase del processo, cioè la parallelizzazione del codice sequenziale. L’ostacolo fondamentale sulla strada della parallelizzazione è costituito dalle interdipendenze tra parti diverse dello stesso programma, in altri termini dal fatto che spesso il lavoro svolto da una certa parte del codice si basa su dati prodotti da un’altra parte del medesimo codice. L’esistenza di una relazione di questo tipo rende impossibile, evidentemente, svolgere in parallelo le due parti del programma, poiché occorre completare una delle due prima di poter passare all’altra. Creare una versione “parallela” di un programma “seriale” richiede quindi la chiara individuazione di tutte le interdipendenze (che spesso non sono affatto evidenti), la rimozione di quelle che sono eliminabili e quindi lo sviluppo di soluzioni che consentano di aggirare – per quanto possibile – le interdipendenze che devono necessariamente rimanere. Queste ultime devono però essere conservate integralmente anche nel codice parallelo, che altrimenti risulterebbe funzionalmente diverso dal codice originale. Lo strumento di Vector Fabrics analizza il codice C per individuare i vari tipi di interdipendenze: non solo quelle riguardanti l’attesa dei risultati di un calcolo, ma anche quelle legate all’uso dei “puntatori”, tipici del linguaggio C, e ai “loop” (anelli di operazioni ripetitive). Per quanto riguarda i puntatori, va sottolineato che queste interdipendenze devono essere analizzate in modo dinamico, ossia nel corso del funzionamento reale del programma; in questo caso, quindi, l’analisi del codice richiede una sorta di collaudo, che deve garantire una totale “copertura” delle possibili condizioni di funzionamento reale. Nel caso dei loop, inoltre, Vector Fabrics ha introdotto il concetto di “dependency distance”, una grandezza vettoriale che misura la distanza tra il momento in cui il programma produce un certo dato e quello in cui dovrà riutilizzarlo. Una volta individuate e classificate in modo automatico le interdipendenze, il sistema le presenta al programmatore tramite una rappresentazione tridimensionale (una prospettiva) composta di rettangoli che raffigurano i loop e le funzioni; le caratteristiche grafiche di questi elementi consentono di rappresentare visivamente l’annidamento (nesting) degli elementi del programma.
Suddivisione e mappatura
Le nuove funzioni introdotte da vfEmbedded riguardano specificamente il processo di ripartizione e “mappatura” del codice sulle risorse hardware disponibili. La fase di ripartizione identifica le sezioni del codice che possono essere eseguite in parallelo sui singoli core, anche diversi tra loro. La fase di mappatura consente quindi allo sviluppatore di decidere quale parte del software assegnare a ciascun core. Gli acceleratori e le altre risorse hardware facenti parte dell’architettura possono essere modellizzate fornendo allo strumento informazioni che ne descrivono le prestazioni. Le diverse porzioni del codice possono quindi essere mappate sull’hardware per una stima più precisa delle prestazioni. Va chiarito che, data una certa architettura hardware, è l’utilizzatore a decidere come esplorare lo spazio delle possibili ripartizioni del software, cioè a scegliere quali e quante sono le opzioni da testare; in altri termini lo strumento rende più veloce la valutazione iterativa delle opzioni, ma non è finalizzato a trovare automaticamente l’opzione migliore.
Dopo il completamento delle decisioni riguardanti la suddivisione e la mappatura, vfEmbedded fornisce all’utilizzatore una serie di istruzioni passo-passo (indicate con il termine “recipe”, cioè ricetta), che consentono di implementare la soluzione prescelta senza introdurre errori. Secondo Vector Fabrics, il risparmio di tempo ottenuto accelerando il processo di ripartizione/mappatura ed evitando gli errori consente di completare il multicore porting nel giro di alcuni giorni, anziché alcuni mesi. Lo strumento permette di ottimizzare l’implementazione di algoritmi e codec complessi sulla piattaforma hardware data, ma può essere utilizzato anche per confrontare tra loro più architetture diverse.
L’interfaccia utente
Un aspetto caratterizzante di vfEmbedded è l’interfaccia utente, progettata per semplificare e velocizzare l’impiego del prodotto. La descrizione del target viene effettuata in modalità “drag and drop”, semplicemente trascinando con il mouse i simboli grafici che rappresentano le diverse risorse hardware. La modalità “drag and drop” viene utilizzata anche per collocare le diverse porzioni del codice sui vari core. L’interfaccia grafica dello strumento comprende anche una finestra che illustra il livello di utilizzazione dei diversi core, evidenziando in modo immediato l’eventuale sottoutilizzazione delle risorse hardware. Sulla base di questa informazione, il progettista può decidere di valutare una piattaforma meno potente, per ridurre i costi complessivi del sistema. Come si è detto, vfEmbedded è uno strumento “cloud-based” ed è quindi accessibile solo tramite web sulla base di una tariffazione “a consumo”: attualmente l’abbonamento mensile costa 450 euro. È comunque possibile provare il prodotto gratuitamente. Sono previste future versioni di vfEmbedded rivolte a un maggior numero di processori target.