di  -  mercoledì 28 ottobre 2009

Nel precedente articolo abbiamo introdotto la modalità Thumb, soluzione adottata da ARM con la versione 4 della sua architettura per venir incontro alle necessità di maggior compattezza del codice, tipico del settore embedded.

Col passare del tempo e complice il dilagare di dispositivi portatili che sono diventati sempre più degli oggetti factotum (in particolare con la possibilità di far girare quelli che prima erano dei “giochini”, poi divenuti sempre più complessi) si è affacciata la necessità di eseguire applicazioni Java.

Impegnata in prima linea coi dispositivi mobile (se sono stati venduti più di 10 miliardi di microprocessori di questa famiglia è anche grazie all’esplosione di questo settore), ARM s’è trovata, quindi, di fronte al problema di come realizzare delle JVM (Java Virtual Machine) che girassero in maniera più efficiente sulle sue CPU, e ha tirato fuori dal cilindro Jazelle

Avendo già sperimentato con successo la possibilità di eseguire opcode di ISA diverse da quella nativa (con Thumb, appunto), ha pensato bene di introdurre un’altra modalità di esecuzione che prendesse a modello l’ISA “virtuale” delle JVM, che eseguono codice Java sotto forma di bytecode.

Jazelle arriva nel 2000 con la versione 5 dell’architettura ARM, ma non viene automaticamente inclusa in tutte le CPU v5: si tratta di ben (!) 12mila transistor (ricordiamo che il solo core, quindi senza estensioni e cache varie, si aggira sui 35mila transistor) che possono anche non interessare i partner, per cui l’estensione è e rimane opzionale (a differenza di Thumb, il cui supporto è divenuto poi obbligatorio per tutti i microprocessori di questa famiglia).

L’ISA eseguita dalla JVM è, però, estremamente diversa dall’architettura ARM, da Thumb, e in generale da qualunque altra ISA general purpose già sviluppata. Non sarebbe, pertanto, pensabile che ARM si fosse imbarcata nell’opera di eseguirla completamente in hardware.

La strada percorsa è, infatti, ben diversa. Si tratta di mettere a disposizione un ambiente di esecuzione che faciliti l’esecuzione dei bytecode Java. Non a caso nel titolo dell’articolo parlavo di “accelerazione”, perché è proprio questo ciò che è stato deciso di realizzare dalla casa madre.

In questa modalità il funzionamento del processore cambia radicalmente sia nell’esecuzione delle istruzioni che nell’uso dei registri, i quali subiscono una specializzazione:

  • da R0 a R3 vengono utilizzati per conservare i 4 elementi in cima allo stack Java (le JVM sono delle virtual machine di tipo “stack“)
  • R4 memorizza il puntatore a this (cioè all’oggetto corrente su cui sta lavorando)
  • R5 punta all’handler per la gestione delle istruzioni non eseguite direttamente / nativamente
  • R6 rappresenta lo stack utilizzato dalla JVM (per memorizzare risultati intermedi e valori di ritorno dalle chiamate a funzione)
  • R7 contiene l’indirizzo base delle variabili globali
  • R8 punta alle costanti utilizzate dal codice in esecuzione
  • da R9 a R11 sono a disposizione della virtual machine
  • R12 è liberamente utilizzabile
  • R13, come per la modalità Thumb, conserva il puntatore allo stack (non Java: è lo stack proprio dell’applicazione in esecuzione; in questo caso la JVM)
  • R14, come R12, ma viene usato anche per contenere l’indirizzo di ritorno da una chiamata a funzione (similmente alle modalità ARM e Thumb: è il registro di “Link“)
  • R15, infine, punta al bytecode da eseguire (è il PC, in sostanza)

Per capire meglio il funzionamento di Jazelle, si rende necessaria una spiegazione di massima sul workflow che porta all’esecuzione di bytecode (senza però entrare nel dettaglio del funzionamento di un virtual machine, che esula dallo scopo dell’articolo).

R15, come abbiamo visto, rappresenta il Program Counter della JVM, per cui viene utilizzato per leggere il bytecode da eseguire. In realtà l’ARM preleva una word, cioè 4 byte alla volta, e di questi provvede a scartare quelli inutili (quelli che, eventualmente, precedono il byte che interessa eseguire) e mantenere internamente tutti gli altri (quindi, oltre al byte da eseguire, anche gli eventuali successivi).

Operando in questo modo esegue una sorta di caching che riduce fino a 4 volte il numero di accessi alla memoria per il fetch delle istruzioni e dei loro dati. Questo perché l’ISA delle JVM prevede degli opcode a lunghezza variabile, dove il primo byte rappresenta il “codice identificativo” del bytecode da eseguire, a cui possono seguire altri byte utili all’istruzione.

Una volta prelevato il bytecode e gli eventuali dati che gli servono, Jazelle ha due possibilità: eseguirlo direttamente, oppure richiamare l’handler puntato da R5 a cui demandarne l’interpretazione e la successiva esecuzione.

Jazelle, infatti, non è in grado di eseguire in hardware tutte le quasi 240 istruzioni dell’ISA della JVM, ma soltanto 140 circa di esse vengono lette ed eseguite immediatamente. Le quasi 100 rimanenti richiedono la solita emulazione software prevista da una normale JVM (non dotata di JIT).

Lasciare quasi 100 istruzioni su 240 non emulate potrebbe far decadere considerevolmente le prestazioni, ma in realtà si tratta di bytecode raramente utilizzati. ARM stima, infatti, che meno del 5% del tempo d’esecuzione venga impiegato per farle girare, mentre quasi tutto il tempo la JVM esegue le 140 che sono, pertanto, le più comuni e sulle quali ha giustamente concentrato i suoi sforzi.

Un approccio ibrido, dunque, ma che si rivela azzeccato per svariati motivi:

  • richiede una quantità relativamente piccola di transistor per l’implementazione (altre interamente in hardware sono anche di un ordine di grandezza più costose, in questi termini)
  • il consumo viene ridotto considerevolmente
  • le prestazioni sono molto più elevate rispetto a un interprete interamente software
  • non si occupa spazio in più (a differenza delle JVM con JIT, che sono anche particolarmente esose in quanto devono memorizzare i blocchi di codice transcodificati)

Come al solito ARM si è dimostrata particolarmente attenta alle esigenze dei partner e del mercato, aggiungendo una preziosa freccia al suo arco che, anch’essa, ha contribuito sicuramente alle diffusione di quest’architettura facendola preferire ad altre.

Anche se c’è da dire che successivamente è tornata sui suoi passi, e le ultime incarnazioni della sua architettura non usano più Jazelle, ma s’è inventata una nuova soluzione (ThumbEE). Questa, però, è un’altra storia…

24 Commenti »

I commenti inseriti dai lettori di AppuntiDigitali non sono oggetto di moderazione preventiva, ma solo di eventuale filtro antispam. Qualora si ravvisi un contenuto non consono (offensivo o diffamatorio) si prega di contattare l'amministrazione di Appunti Digitali all'indirizzo info@appuntidigitali.it, specificando quale sia il commento in oggetto.

  • # 1
    Nicola
     scrive: 

    ma esistono in giro “concretizzazioni”(qualche produttore ha integrato Jazelle)? perchè su macchine poco prestanti, le differenze tra un programma Java interamente interpretato ed uno eseguito(tramite jit) sono abissali. Sarei curioso di vedere l’efficacia di questa soluzione.

  • # 2
    zephyr83
     scrive: 

    @ Nicola

    Se nn sbaglio Jazelle viene sfruttato sui cellulari per applicazioni J2ME

  • # 3
    pleg
     scrive: 

    @ Cesare

    Dov’e’ che prendi i numeri di transistor delle CPU ARM? E di preciso a quale parte ti riferisci (solo datapath?)

    Sono curioso, perche’ mi sembrano numeri veramente minuscoli, vorrei sapere cos’e’ che riescono a farci stare in cosi’ poco spazio.

    (Per dare un’idea, 6 mesi fa come progetto di fine corso io e un mio amico abbiamo progettato un decodificatore di un codice d’errore LDPC, e abbiamo cacato fuori un chip da 10 milioni di transistor… 2 persone, in 6 settimane… 35mila transistor ce li saremmo potuti perdere e nemmeno ce ne saremmo accorti :)

  • # 4
    Cesare Di Mauro (Autore del post)
     scrive: 

    @Nicola: come diceva giustamente zephyr83, in genere sono usati nei cellulari.

    @pleg: qui http://en.wikipedia.org/wiki/ARM_architecture#History trovi delle informazioni, che sono attendibili perché le ho già lette tempo fa in qualche white paper. A queste c’è da aggiungere l’ARM1, che utilizzava 25mila transistor; me lo ricordo bene dai tempi di MCMicroComputer.

    I numeri sono piccoli perché non ci sono cache, PMMU, TLB, ecc., la pipeline è molto semplice (a 3 stadi, singola istruzione, e in-order): si tratta, quindi, giusto di ciò che serve per eseguire il fetch, la decodifica (molto semplice) e l’esecuzione.

    Quello del ridotto numero di transistor è stato sempre un punto di forza di quest’architettura.

    P.S. Beato tu che hai la possibilità di progettare e realizzare nuovi processori. :)

  • # 5
    Nicola
     scrive: 

    grazie per le risposte

    “Jazelle arriva nel 2000 con la versione 5 dell’architettura ARM, ma non viene automaticamente inclusa in tutte le CPU v5: si tratta di ben (!) 12mila transistor (ricordiamo che il solo core, quindi senza estensioni e cache varie, si aggira sui 35mila transistor) che possono anche non interessare i partner, per cui l’estensione è e rimane opzionale (a differenza di Thumb, il cui supporto è divenuto poi obbligatorio per tutti i microprocessori di questa famiglia)”

    il mio dubbio(non conoscendo a fondo l’architettura ARM) deriva da questo paragrafo. Non essendo obbligatorio l’inserimento,non tutti i core ARM dovrebbero essere dotati di tale feature, mentre (quasi) tutti i terminali in circolazione supportano la J2ME. Mi ha incuriosito, proverò a cercare qualcosa in giro.

  • # 6
    zephyr83
     scrive: 

    @Nicola

    Infatti nn tutti i terminali hanno le stesse prestazioni in java, anzi!!!! Solitamente i migliori sn i sonyericsson (hanno un’ottima JVM) e spesso anche cn hardware inferiore ottengono risultati superiori anche a terminali più blasonati.
    Qui trovi un programmino che testa la cpu (adesso le prestazioni 3D) e c’è un ricchissimo database
    http://www.dpsoftware.org/ dove trovi le informazioni sulle api utilizzate delle varie JVM
    ovviamente segnalo anche jbenckmark si trovano anche le informazioni sulle cpu (nn sembre attendibili)
    http://www.jbenchmark.com/

  • # 7
    Cesare Di Mauro (Autore del post)
     scrive: 

    @Nicola. Sì, non è obbligatorio, e infatti soltanto i partner che hanno l’esigenza di utilizzare questa tecnologia la licenziano da ARM.

    Tutti i core ARM che integrano Jazelle sono contraddistinti dalla lettere J aggiunta al loro identificativo. Ad esempio ARM7EJ-S.

    @zephyr83: il primo benchmark lascialo perdere perché è inattendibile, in quanto per la “misura” della CPU si basa unicamente sul calcolo della sequenza di Fibonacci.

    Il secondo link, invece, non funziona.

  • # 8
    pleg
     scrive: 

    @ Cesare

    Ok ma quelli sono ARM1 e 2 :)

    Quest’estate ho fatto delle simulazioni su un ARM11, e ho avuto l’impressione che fossimo nell’ordine delle milionate di transistor… stima megagrezza perche’ non mi ricordo l’area del layout :( mi ricordo solo che era una caghetta di mosca in un chip da mezzo miliardo di MOS :)

  • # 9
    Cesare Di Mauro (Autore del post)
     scrive: 

    ROFL. Mi fai morire!!! :D

    Bisogna vedere cosa integrava quell’ARM11: aveva cache? PMMU? Estensione VFP? ecc. ecc. Quando parlo di core mi riferisco al processore “nudo e crudo”.

    Prendiamo, ad esempio, uno degli ultimi nati, il Cortex-M0. Deriva dall’architettura ARM v6 e integra soltanto l’ISA Thumb2 e nient’altro (quindi no cache, PMMU, estensioni varie).
    Ecco qui http://www.arm.com/products/CPUs/ARM-Cortex-M0.html la pagina di presentazione dell’ARM.

    Come puoi leggere in fondo, ARM dichiara di utilizzare circa 12mila gate che, da quel che leggo, sono all’incirca equivalenti a 50mila transistor (non sono pratico di microelettronica: mi dirai tu se la stima è reale o meno).

    P.S. Thumb2 come ISA non è equivalente a quella ARM, ma ne integra quasi tutte le funzionalità (ne parlerò meglio in un prossimo articolo :D). Quindi diciamo che ha una complessità comparabile. ;)

  • # 10
    Nicola
     scrive: 

    grazie a entrambi delle delucidazioni.

    aspetto con ansia il prossimo articolo, conosco poco ARM, ci ho lavorato su solo “indirettamente”(tramite JME, appunto).

  • # 11
    zephyr83
     scrive: 

    @Cesare Di Mauro

    A me il secondo link funziona, cmq basta cercare jbenchmark su google e si trova subito (cmq ripeto, ci ho cliccato e mi ha aperto la pagina).
    Per il primo avresti anche ragione ma noti subito chi ha una buona JVM e chi no! inoltre ci sn anche le informazioni sulle api usate dalle varie JVM

  • # 12
    Cesare Di Mauro (Autore del post)
     scrive: 

    Non mi piacciono i benchmark che testano le API. Visto che mi occupo di architetture, prediligo quelli che eseguono puramente calcoli con la CPU.

    Da questo punto di vista il primo calcola solo Fibonacci. Il secondo, invece, è di gran lunga più variegato e oltre a testare delle API fa anche dei calcoli.

    Quindi lo trovo di gran lunga più attendibile (anche se mi piacerebbe che fossero inclusi altri test su altri algoritmi).

    @Nicola: su ARM ho ancora un po’ di cose da dire. :D

  • # 13
    zephyr83
     scrive: 

    Infatti nn testa le api, da informazioni sulle api usate, per farsi un’idea della JVM. Se nn sbaglio si dovrebbe arrivare a capire se si sfrutta jazelle o meno. C’è anche il test 3D cmq.
    Il secondo link da anche informazioni sul tipo di cpu (anche se nn è sempre attendibile).
    Cmq è difficile fare test del genere visto che è tutto fortemente legato alla JVM e basta poco per ottenere risultati molto differenti a parità di hardware.
    Cmq il test di pfc bench si può paragonare sl super pi dei computer, serve sempre per farsi un’idea (soprattutto dopo un aggiornamento del telefono per vedere se è migliorato qualcosa)

  • # 14
    pleg
     scrive: 

    @ Cesare

    Accipicchia… non sono piu’ abituato a numeri cosi’ piccoli :) cmq e’ vero, oggi la memoria e’ quella che consuma la maggior parte dei trasistor: una cache di 8kB gia’ prende parecchi piu’ MOS di quel core :)

    Cmq, per il gate count, si’ e’ corretto. Di solito con “gate” si indica una NAND (credo per motivi storici), quindi 4 MOS: 12k gate -> 48k MOS.
    Non so bene perche’, ma di solito si indica il gate count e non il transistor count.

  • # 15
    Cesare Di Mauro (Autore del post)
     scrive: 

    @zephyr83: quando parlavo di test delle API mi riferivo all’uso di API dedicate, come queste (preso dal link che hai fornito):

    GPU Graphics Benchmark
    Low level, one spotlight.
    Low level, two spotlights, textured.
    Simple mesh, directional light.
    Simple mesh, UV-Mapping, Catmull-Clark.
    Perspective correction, ambient light.
    Complex mesh, dynamic ligthing.
    Complex mesh, multitexturing.
    Particles simulation, dynamic lighting.

    che non testano la bontà del processore nell’eseguire bytecode, ma la più che altro la bontà dell’implementazione del runtime della JVM.

    Ecco perché non mi piacciono questo tipo di benchmark, ma preferisco una serie variegata di test (nel senso che vengono implementati algoritmi diversi e fra i più disparati) che ricadono interamente sulla CPU.

    SuperPI, al pari di FPC, è un unico benchmark sintetico che non può assolutamente dire nulla sul comportamento generale della CPU. Io su PC lo usavo esclusivamente per testare la stabilità del sistema quando mi dilettavo con gli overclock.

    @pleg: grazie per la conferma. Pensavo anch’io che fosse qualcosa legato alle porte NAND o NOR, ma non essendo pratico ho preferito non espormi.

    Credo che si utilizzino i gate come “misura” perché da un po’ di anni sono comuni gli FPGA per vari progetti, e mi sembra che si parli sempre del numero di gate che mettono a disposizione.

  • # 16
    pleg
     scrive: 

    @ Cesare

    Si’ spesso per le FPGA si specificano le gate equivalenti, ma sono in genere misure fuffe, cioe’ non molto collegate alla dimensione del tuo design. Per un ASIC, prendi il numero di gate, moltiplica per 4 e hai il numero di MOS; moltiplica per l’area della NAND a 2 ingressi di dimensione minima della tua libreria, e hai uan stima ragionevole della dimensione del layout. Ma per una FPGA questo non vale, perche’ i blocchi base non sono normali gate. Potresti avere due strutture che in ASIC vengono quasi uguali, e in FPGA vengono anche 10 volte diverse… il che naturalmente incide moltissimo su *come* scrivi il tuo codice, a seconda che debba essere sintetizzato su FPGA o in ASIC.

  • # 17
    Cesare Di Mauro (Autore del post)
     scrive: 

    Il mio codice lo scriverei così: http://www.myhdl.org/doku.php :D

    A parte gli scherzi, non ho alcuna esperienza e francamente non conosco le implicazioni relative all’utilizzo di ASIC e FPGA (anche se ti confesso che un sogno che conservo nel cassetto è quello di realizzare una CPU erede della famiglia 68000; ma è al di là della mia portata).

  • # 18
    pleg
     scrive: 

    Ha ha il python in ASIC :))
    Anche se chissa’ magari la cosa prima o poi diventera’ normale :) prima verilog e VHDL, poi system-C… magari tra un po’ sintetizzeremo direttamente il C++ in gate di libreria :))

    E’ sempre stato anche un po’ un mio sogno farmi una CPU mia (assolutamente inutile… ma figo :)
    In realta’ non e’ nemmeno chissa’ che, su opencores ci sono un bel po’ di progetti del genere… e per una CPU superbase probabilmente ti bastano uno o due migliaia di righe di verilog.

  • # 19
    Nicola
     scrive: 

    io per calcolare le prestazioni di una data architettura sono per l’approccio “terra terra”: testare l’applicazione che andrà ad eseguire. Calcolare le prestazioni pure di un determinato processore serve solo a dare un’idea indicativa delle sue potenzialità, poichè gli scenari di utilizzo sono talmente disparati che sarebbe impossibile sintetizzarli tutti. Con questo non voglio dire che i benchmark(qualsiasi sia l’approccio) sono inutili, ma io li ho presi sempre con le pinze..

  • # 20
    Cesare Di Mauro (Autore del post)
     scrive: 

    @pleg: gli darò un’occhiata, grazie. :)

    Anche se la scrittura di codice verilog non m’ispira proprio (e poi mi manca proprio il background).

    @Nicola: è scontato che i confronti si fanno sull’architettura reale.

    Personalmente guardo con interesse ai microbenchmark che testano particolari situazioni perché mi piace vedere come si comporta l’architettura della CPU per cercare di capire le sue potenzialità.

  • # 21
    Nicola
     scrive: 

    esatto cesare, mi sono dimenticato di precisare: sono gli unici che si avvicinano a situazioni “realmente” riproducibili nelle varie applicazioni in uso su una particolare architettura. Diciamo che sono un ottimo preludio alla “prova su strada”.

  • # 22
    Cortex-A8: una nuova via per ARM - Appunti Digitali
     scrive: 

    […] cambiamento sensibile è dovuto alla sostanziale rimozione della vecchia modalità Jazelle. In realtà viene mantenuta per retrocompatibilità, ma nessun bytecode viene accelerato in […]

  • # 23
    sidew
     scrive: 

    Mi viene in mente le famose cpu picoJava, che eseguivano direttamente il bytecode java…

    http://en.wikipedia.org/wiki/PicoJava

  • # 24
    Cesare Di Mauro (Autore del post)
     scrive: 

    Sì, anni fa si favoleggiava pure del processore MACJ di Java, ma non se ne seppe più nulla.

Scrivi un commento!

Aggiungi il commento, oppure trackback dal tuo sito.

I commenti inseriti dai lettori di AppuntiDigitali non sono oggetto di moderazione preventiva, ma solo di eventuale filtro antispam. Qualora si ravvisi un contenuto non consono (offensivo o diffamatorio) si prega di contattare l'amministrazione di Appunti Digitali all'indirizzo info@appuntidigitali.it, specificando quale sia il commento in oggetto.