Sviluppo e ottimizzazione di applicazioni Android* sulla piattaforma Intel® Atom™

Sunto

Questo documento descrive metodi dettagliati per sviluppare ed eseguire il porting delle applicazioni Android sulla piattaforma Intel Atom e tratta delle metodologie ottimali per sviluppare applicazioni usando Android Native Development Kit (NDK) e ottimizzare le prestazioni. Consultando questo documento gli sviluppatori Android possono creare applicazioni di qualità elevata per l'architettura Intel.

1. Classificazione delle applicazioni Android

Le applicazioni Android possono essere classificate in due tipi, come mostrato nella Figura 1.

  • Le applicazioni Dalvik che includono il codice Java* e usano solo l'API Android dell'SDK ufficiale e i file di risorse necessari, come i file xml e png, compilati in un file APK.
  • Le applicazioni Android NDK che includono il codice Java e i file di risorse nonché il codice sorgente C/C++ e talvolta il codice assembly. Tutto il codice nativo è compilato in una libreria dinamica (file .so) e quindi chiamato da Java nel programma principale usando un meccanismo JNI.


Figura 1: Due tipi di applicazioni Android

2. Android Native Development Kit

2.1 Introduzione

Android Native Development Kit (NDK) è uno strumento complementare dell'Android SDK. L'NDK è uno strumento potente per lo sviluppo di applicazioni Android perché:

  • Crea in codice nativo le porzioni dell'applicazione che richiedono prestazioni elevate. Quando si usa codice Java, il codice sorgente basato su Java deve essere interpretato in linguaggio macchina usando una macchina virtuale. Il codice nativo invece è compilato e ottimizzato direttamente in un file binario prima dell'esecuzione. Usando correttamente il codice nativo è possibile creare nell'applicazione del codice dalle prestazioni elevate, come la codifica e la decodifica video basate su hardware, l'elaborazione grafica e le operazioni aritmetiche.
  • Riutilizza il codice nativo precedente. I codici C/C++ possono essere compilati in una libreria dinamica che può essere richiamata dal codice Java con un meccanismo JNI.

2.2 Panoramica sugli strumenti

Durante la fase di sviluppo è possibile utilizzare Intel® Hardware Execution Manager (HAXM) per migliorare le prestazioni del simulatore Android. HAXM è un motore di virtualizzazione basato su hardware (hypervisor) che usa la Intel® Virtualization Technology per accelerare l'emulazione delle applicazioni Android su un computer host. Usato in combinazione con le immagini dell'emulatore Android x86 fornite da Intel e con l'Android SDK Manager ufficiale, HAXM permette di ottenere un'emulazione Android più veloce sui sistemi abilitati per la Intel® Virtualization Technology. Per maggiori informazioni su HAXM, visitare: http://software.intel.com/it-it/articles/intel-hardware-accelerated-execution-manager.

2.3 Installazione di HAXM

Installare HAXM usando Android SDK Manager (procedura consigliata) oppure installarlo manualmente scaricando il programma di installazione dal sito Web di Intel. Se si desidera aggiornarlo automaticamente, eseguire l'installazione usando Android SDK Manager come mostrato nella Figura 2. [1]


Figura 2: Installare Intel HAXM usando Android SDK Manager

È possibile anche scaricare sulla piattaforma host il pacchetto di installazione appropriato dal sito Web http://software.intel.com/it-it/android e quindi seguire le istruzioni dettagliate per installarlo.

2.3.1 Impostazione di HAXM

Quando si esegue HAXM è richiesta l'immagine del sistema Android x86 fornita da Intel. Si può scaricare l'immagine del sistema usando Android SDK Manager o scaricarla manualmente dal sito Web di Intel® Developer Zone.

Una volta installate correttamente, le immagini dell'emulatore Intel® x86 Android sono eseguite automaticamente utilizzando il file binario “emulator-x86” fornito con l'SDK di Android. L'emulatore Android è accelerato dalla Intel® Virtualization Technology, velocizzando a sua volta il processo di sviluppo.

3. Sviluppo e porting di applicazioni NDK per l'architettura Intel Atom

3.1 Sviluppo di applicazioni NDK per dispositivi basati sul processore Intel Atom

Dopo aver installato correttamente l'NDK, leggere i documenti contenuti nella directory <ndk>/docs/, in particolare OVERVIEW.html e CPU-X86.html, per capire il funzionamento dell'NDK e il suo utilizzo.

Lo sviluppo delle applicazioni NDK può essere suddiviso in cinque fasi, mostrate nella Figura 3:


Figura 3: Processo di sviluppo delle applicazioni NDK

La demo hello-jni è utilizzata per illustrare queste cinque fasi. La demo si trova nella cartella Root\samples\hello-jni dell'NDK [5]. La demo hello-jni è una semplice applicazione inclusa nell'NDK che ottiene una stringa da un metodo nativo di una libreria condivisa e la usa nell'interfaccia utente dell'applicazione.

3.1.1. Creare codice nativo

Creare un nuovo progetto Android e inserire il codice sorgente nativo in <progetto>/jni/. Il contenuto del progetto è mostrato nella Figura 4. Questa demo include una semplice funzione in codice nativo chiamata Java_com_example_hellojni_HelloJni_stringFromJNI(). Come mostrato nel codice sorgente, restituisce una stringa semplice da JNI.


Figure 4: Creare codice nativo

3.1.2 Creare MakeFile ‘Android.mk’

Per impostazione predefinita le applicazioni NDK sono create per la piattaforma ARM. Per creare applicazioni NDK per la piattaforma Intel Atom è necessario aggiungere APP_ABI := x86 a MakeFile.


Figura 5: Creare MakeFile

3.1.3 Compilare codice nativo

Compilare il codice nativo eseguendo lo script 'ndk-build' dalla directory del progetto. Si trova nella directory di livello superiore dell'NDK. Il risultato è mostrato nella Figura 6.


Figura 6: Codice nativo compilato

Gli strumenti di compilazione copiano automaticamente le librerie condivise scorporate nella posizione corretta all'interno della directory del progetto dell'applicazione.

3.1.4 Chiamare il codice nativo da Java

Quando si distribuisce correttamente la libreria condivisa è possibile chiamare la funzione da Java. Il codice è mostrato nella Figura 7. Una chiamata di funzione nativa pubblica stringFromJNI() viene creata in codice Java e questa funzione carica la libreria condivisa usando System.loadlibrary().


Figura 7: Chiamare il codice nativo da Java

3.1.5 Debug con GDB

Se si desidera eseguire il debug dell'applicazione NDK con GDB, devono essere soddisfatte le seguenti condizioni:

  • L'applicazione NDK è costruita con 'ndk-build'
  • L'applicazione NDK è impostata su ‘debuggable’ in Android.manifest
  • L'applicazione NDK è eseguita in Android 2.2 (o superiore)
  • È in esecuzione una sola destinazione
  • Aggiungere la directory di adb a PATH

Usare il comando ndk-gdb per eseguire il debug dell'applicazione. È possibile impostare un punto di interruzione o un debug dettagliato per tracciare la cronologia delle modifiche del valore di una variabile, come mostrato nella Figura 8.


Figura 8: Debug dell'applicazione NDK con GDB

3.2 Porting di applicazioni NDK esistenti nei dispositivi basati sul processore Intel Atom

In questa sezione si presuppone di avere un'applicazione Android per la piattaforma ARM e che sia necessario eseguirne il porting prima di distribuirla sulla piattaforma Intel Atom.

Il processo di porting delle applicazioni Android verso la piattaforma Intel Atom è simile al processo di sviluppo. I passaggi sono mostrati nella Figura 9.


Figura 9: Porting di applicazioni Android verso la piattaforma Intel Atom

3.2.1 Porting di applicazioni Dalvik

Le applicazioni Dalvik possono essere eseguite direttamente sui dispositivi basati sul processore Intel Atom. L'interfaccia utente deve essere regolata per il dispositivo di destinazione. Per un dispositivo ad alta risoluzione, come ad esempio i tablet con una risoluzione 1280x800 o superiore, l'allocazione predefinita della memoria potrebbe non soddisfare i requisiti delle applicazioni, con conseguente impossibilità di avviare l'applicazione. Per i dispositivi ad alta risoluzione si consiglia di aumentare l'allocazione predefinita della memoria.

3.2.2 Porting di applicazioni Android NDK

Il porting delle applicazioni NDK è un po' più complicato rispetto al porting delle applicazioni Dalvik. Tutte le applicazioni NDK possono essere divise in tre tipologie in base alle seguenti proprietà del codice nativo:

  • Consiste solo di codice C/C++ che non è correlato all'hardware
  • Utilizza una libreria collegata dinamica di terze parti
  • Include il codice assembly che è altamente correlato alle piattaforme non basate su architettura Intel

Codice nativo costituito solo di codice C/C++ che non è correlato al hardware

  1. Per eseguire correttamente l'applicazione sulla piattaforma Intel Atom ricompilare il codice nativo.
  2. Aprire il progetto NDK e cercare il file Android.mk e aggiungere APP_ABI := armeabi armeabi-v7a x86 ad Android.mk, quindi ricompilare il codice nativo con ndk-build.
  3. Se il file Android.mk non viene trovato, utilizzare il comando ndk-build APP_ABI="armeabi armeabi-v7a x86" per compilare il progetto.
  4. Impacchettare nuovamente l'applicazione con le piattaforme x86 supportate.

Se il codice nativo utilizza una libreria collegata dinamica di terze parti, la libreria condivisa deve essere ricompilata nella versione x86 per la piattaforma Intel Atom.

Se il codice nativo include codice assembly che è altamente correlato alle piattaforme non basate su architettura Intel, il codice deve essere riscritto in assembly IA o C/C++.

4. Metodologie ottimali per lo sviluppo di codice nativo

4.1 Allineamento forzato della memoria

A causa delle differenze tra le architetture, le piattaforme e i compilatori, le dimensioni dei dati di una stessa struttura di dati su piattaforme diverse possono essere diverse. Se non si usasse l'allineamento forzato della memoria, le discrepanze nelle dimensioni dei dati potrebbero causare errori di caricamento. [2]

L'esempio seguente mostra le dimensioni dei dati di una stessa struttura di dati su diverse piattaforme:

struct TestStruct {
int mVar1;
long long mVar2;
int mVar3;
 };

Questo è un semplice struct con tre variabili chiamate mVar1, mVar2 e mVar3.

La variabile mVar1 è un intero che usa 4 byte
La variabile mVar2 è un intero di tipo long long che usa 8 byte
La variabile mVar3 è anch'essa un intero che usa 4 byte.

Quanto spazio è necessario sulle piattaforme ARM e Intel Atom?

Le dimensioni dei dati compilati per le piattaforme ARM e Intel Atom con un'opzione predefinita del compilatore sono mostrate nella Figura 10. ARM adotta automaticamente l'opzione "double malign" e occupa 24 byte, mentre x86 occupa 16 byte.


Figura 10: Memoria allocata dai flag di compilazione predefiniti

La variabile mVar2 a 8 byte (64 bit) genera un layout differente per TestStruct perché ARM richiede un allineamento di 8 byte per le variabili a 64 bit come la mVar2. Nella maggior parte dei casi ciò non causa problemi in quanto la compilazione per x86 rispetto ad ARM richiede una ricompilazione completa.

Potrebbe tuttavia verificarsi una discrepanza nelle dimensioni se un'applicazione serializza le classi o le strutture. Ad esempio, si crea un file in un'applicazione ARM che scrive TestStruct in un file. Se in seguito si caricano i dati da tale file su una piattaforma x86, le dimensioni della classe nell'applicazione sono diverse da quelle nel file. Problemi simili di allineamento della memoria possono verificarsi per il traffico di rete che prevede un layout di memoria specifico.

L'opzione “-malign-double” del compilatore GCC genera lo stesso allineamento della memoria in x86 e ARM.


Figura 11: Memoria allocata quando sono aggiunti i flag -malign-double

4.2 Porting delle istruzioni NEON* in SSE [3]

4.2.1 NEON

La tecnologia ARM NEON* è principalmente utilizzata in ambiti multimediali come gli smartphone e le applicazioni HDTV. Secondo quando riportato nella documentazione di ARM, la tecnologia basata sul motore SIMD a 128 bit, che è un'estensione della serie ARM Cortex*-A, offre prestazioni almeno triple rispetto all'architettura ARMv5 ed almeno doppie rispetto all'architettura ARMv6 seguente. Per maggiori informazioni sulla tecnologia NEON visitare: http://www.arm.com/products/processors/technologies/neon.php.

4.2.2 SSE: l'equivalente Intel

SSE è la Streaming SIMD Extension per l'architettura Intel. Il processore Intel Atom attualmente supporta SSSE3 (Supplemental Streaming SIMD Extensions 3) e versioni precedenti, ma non supporta ancora SSE4.x. SSE è un motore a 128 bit che gestisce la compattazione dei dati a virgola mobile. Il modello di esecuzione è iniziato con la tecnologia MMX e SSx è essenzialmente la generazione più recente che non rende più necessario MMX. Per ulteriori informazioni, consultare la sezione "Volume 1: Basic Architecture" dei manuali di sviluppo di software per le architetture Intel 64 e IA-32. La panoramica SSE nella sezione 5.5 offre le istruzioni per SSE, SSE2, SSE3 e SSSE3. Queste operazioni sui dati spostano i valori a virgola mobile di precisione e compattati tra i vari registri XMM o tra i registri XMM e la memoria. I registri XMM sono destinati ad essere utilizzati in sostituzione dei registri MMX.

4.2.3 Da NEON a SSE a livello di assembly

Usare il manuale per gli sviluppatori di software per le architetture Intel come riferimento incrociato per tutti i singoli mnemonici SSE(x) e consultare anche le varie istruzioni SSE a livello di assembly reperibili in: http://neilkemp.us/src/sse_tutorial/sse_tutorial.html. Usando il sommario è possibile accedere agli esempi di codice o esaminare informazioni complementari.

Allo stesso modo, il seguente manuale di ARM fornisce informazioni su NEON e contiene piccoli frammenti di assembly nella sezione 1.4 ”Developing for NEON”: http://infocenter.arm.com/help/topic/com.arm.doc.dht0002a/DHT0002A_introducing_neon.pdf.

Differenze fondamentali quando si confrontano il codice assembly NEON e SSE:

  • Ordine dei byte. Intel supporta solo l'assembly little-endian, mentre ARM supporta l'ordine big-endian o little-endian (ARM è bi-endian). Negli esempi di codice forniti il codice ARM è di tipo little-endian, simile a quello di Intel. Nota: potrebbero comparire alcune caratteristiche del compilatore ARM. Ad esempio, la compilazione per ARM usando GCC include i flag –mlittle-endian e –mbig-endian. Per ulteriori informazioni, fare riferimento a http://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html.
  • Granularità. Nel caso dei semplici esempi di codice assembly citati, confrontare le istruzioni ADDPS per SSE (Intel) con VADD.ix per NEON, come x = 8 o 16. Notare che quest'ultimo caso inserisce una certa granularità nei dati da gestire come parte dello mnemonico di riferimento.

Nota: queste non sono tutte le differenze. Si potrebbero notare altre differenze tra NEON e SSE.

4.2.4 Da NEON a SSE a livello di C/C++

Il porting del codice C/C++ e NEON in SSE può causare numerosi inconvenienti a livello della API. Tenere a mente il presupposto che l'assembly inline non è in uso, ma che è invece utilizzato del codice C/C++ vero e proprio. Anche le istruzioni NEON forniscono alcune librerie C native. Queste istruzioni, sebbene in codice C, non possono essere eseguite dalla piattaforma Intel Atom e devono essere riscritte.

5. Ottimizzazione delle prestazioni delle applicazioni

5.1 Ottimizzazione delle prestazioni

Durante il processo di codifica, usare i seguenti metodi per ottimizzare le prestazioni dell'applicazione sulla piattaforma Intel Atom.

5.1.1 Usare funzioni inline invece di funzioni brevi più frequenti

Le funzioni inline sono meglio utilizzate per funzioni piccole come l'accesso a membri di dati privati. Le funzioni brevi sono sensibili al sovraccarico delle chiamate di funzioni. Le funzioni più lunghe richiedono in proporzione meno tempo per la sequenza di chiamata/ritorno e traggono meno vantaggio dall'inline. [4]

La funzione inline riduce il sovraccarico in queste aree:

  • Chiamate di funzione (incluso il passaggio dei parametri e l'inserimento dell'indirizzo dell'oggetto nello stack)
  • Mantenimento dello stack frame del chiamante
  • Impostazione di un nuovo stack frame
  • Comunicazione del valore restituito
  • Ripristino di uno stack frame precedente
  • Restituzione

5.1.2 Usare Float invece di Double

FPU è un'unità a virgola mobile che fa parte di un sistema progettato specificatamente per eseguire operazioni con numeri a virgola mobile, come addizioni, sottrazioni, moltiplicazioni, divisioni e radici quadrate. Alcuni sistemi, come le architetture meno recenti basate su microcodice, possono anche eseguire varie funzioni trascendenti come il calcolo di funzioni esponenziali e trigonometriche. I processori attuali eseguono questi calcoli con routine di librerie di software. Nelle architetture più recenti dei computer per uso generico, una o più FPU sono integrate nella CPU [6].

La piattaforma Intel Atom ha attivata la FPU. Nella maggior parte dei casi l'uso di Float invece che Double velocizza il processo di elaborazione dei dati e riduce l'utilizzo della larghezza di banda della memoria nei dispositivi basati sul processore Intel Atom.

5.1.3 Codifica multi-thread

La codifica multi-thread consente di usare la funzione di hyper-threading del processore Intel Atom per aumentare il throughput e migliorare le prestazioni complessive. Per ulteriori informazioni sul multi-threading, consultare: http://www.intel.com/content/www/it/it/architecture-and-technology/hyper-threading/hyper-threading-technology.html.

5.2 Creare applicazioni dalle prestazioni elevate con i flag del compilatore

Come sapete, nelle applicazioni Android il codice nativo è compilato da GCC. Ma sapete qual è il dispositivo di destinazione predefinito di GCC? È il processore Pentium® Pro. Il codice binario viene eseguito meglio sulla piattaforma Pentium Pro se non si aggiungono flag durante la compilazione del codice nativo. La maggior parte delle applicazioni Android sono eseguite su piattaforma Intel Atom invece che Pentium Pro. È consigliato aggiungere flag specifici per la piattaforma di destinazione. I flag che è consigliato aggiungere per la compilazione sulla piattaforma Intel Atom sono i seguenti:

-march=atom
-msse4
-mavx
-maes

Per ulteriori informazioni sui parametri del compilatore, consultare: http://gcc.gnu.org/onlinedocs/gcc/i386-and-x86-64-Options.html

6. Conclusioni

Questo documento descrive come sviluppare e ottimizzare le applicazioni Android sulle piattaforme Intel Atom, nonché come sviluppare ed eseguire il porting delle applicazioni NDK.

In sintesi, i punti chiave trattati sono:

  • La maggior parte delle applicazioni Android possono essere eseguite direttamente sulla piattaforma Intel Atom. Per le applicazioni NDK è necessario ricompilare il codice nativo. Se nell'applicazione è incluso codice assembly, questa porzione del codice deve essere riscritta.
  • Utilizzare al meglio le funzioni dell'architettura Intel per migliorare le prestazioni delle applicazioni Android.
  • Aggiungere opzioni di compilazione specifiche della piattaforma per rendere più efficace la compilazione del codice da parte di GCC.

Riferimento

  1. http://software.intel.com/it-it/articles/installation-instructions-for-intel-hardware-accelerated-execution-manager-windows/
  2. http://software.intel.com/it-it/blogs/2011/08/18/understanding-x86-vs-arm-memory-alignment-on-android/
  3. http://software.intel.com/it-it/articles/ndk-android-application-porting-methodologies/
  4. http://msdn.microsoft.com/it-it/library/1w2887zk.aspx
  5. http://developer.android.com/sdk/ndk/index.html
  6. http://it.wikipedia.org/wiki/Unit%C3%A0_di_calcolo_in_virgola_mobile

Informazioni sull'autore

Dawei è un ingegnere informatico che si occupa specificatamente dell'abilitazione delle applicazioni mobili, incluso lo sviluppo di applicazioni Android e la loro ottimizzazione per i dispositivi x86 e lo sviluppo di applicazioni Web HTML5. Dawei ha inoltre una vasta esperienza nella progettazione delle interfacce utente e dell'esperienza utente per le applicazioni mobili.

Avvisi

LE INFORMAZIONI CONTENUTE IN QUESTO DOCUMENTO SONO FORNITE IN ABBINAMENTO AI PRODOTTI INTEL. QUESTO DOCUMENTO NON CONCEDE ALCUNA LICENZA, IMPLICITA O ESPLICITA, MEDIANTE PRECLUSIONE O ALTRO, PER QUANTO RIGUARDA I DIRITTI DI PROPRIETÀ INTELLETTUALE. AD ECCEZIONE DI QUANTO STABILITO DAI TERMINI E DALLE CONDIZIONI DI VENDITA INTEL PER I PRODOTTI IN QUESTIONE, INTEL NON SI ASSUME ALCUNA RESPONSABILITÀ E DISCONOSCE QUALSIASI GARANZIA ESPRESSA O IMPLICITA RELATIVA ALLA VENDITA E/O ALL'UTILIZZO DI PRODOTTI INTEL, INCLUSA LA RESPONSABILITÀ O L'IDONEITÀ AD UNO SCOPO PARTICOLARE, LA COMMERCIABILITÀ O LA VIOLAZIONE DI BREVETTI, COPYRIGHT O ALTRI DIRITTI DI PROPRIETÀ INTELLETTUALE.

SE NON ALTRIMENTI SPECIFICATO PER ISCRITTO DA INTEL, I PRODOTTI INTEL NON SONO PROGETTATI NÉ DESTINATI PER APPLICAZIONI IN CUI UN GUASTO DEL PRODOTTO POTREBBE DARE ADITO A SITUAZIONI IN CUI POSSANO VERIFICARSI LESIONI PERSONALI O MORTALI.

Intel può apportare modifiche alle specifiche e alle descrizioni dei prodotti in qualsiasi momento e senza preavviso. I progettisti non devono fare affidamento sull'assenza o sulle caratteristiche di qualunque funzione o sulle istruzioni contrassegnate come "riservate" o "non definite". Intel si riserva di definirle in futuro e non accetta alcuna responsabilità in caso di conflitti o incompatibilità derivanti da ogni loro modifica futura. Le informazioni sono soggette a modifica senza preavviso. Non finalizzare un progetto con queste informazioni.

I prodotti descritti in questo documento possono contenere errori o difetti di progettazione noti come "errata" che possono determinare l'errato funzionamento del prodotto, a differenza di quanto stabilito nelle relative specifiche pubblicate. Gli "errata" attualmente riconosciuti sono disponibili su richiesta.

Per ottenere le specifiche più recenti e prima di inoltrare l'ordine di prodotti, contattare l'ufficio vendite Intel di zona oppure il distributore di fiducia.

Le copie dei documenti con numero d'ordine citati in questo documento, o altra letteratura Intel, possono essere richieste telefonando al numero (USA) 1-800-548-4725 oppure visitando il sito: http://www.intel.com/design/literature.htm Il software e i carichi di lavoro utilizzati nei test delle prestazioni potrebbero essere stati ottimizzati per le prestazioni solo sui microprocessori Intel. I test delle prestazioni, come SYSmark e MobileMark, sono misurati usando computer, componenti, software, operazioni e funzioni specifici. Qualunque modifica a questi fattori potrebbe causare variazioni nei risultati. Per valutare in modo più completo i prodotti considerati per l'acquisto, si consiglia di consultare altre informazioni e test delle prestazioni, incluse le prestazioni del prodotto quando usato insieme ad altri prodotti.

Il codice sorgente del software riprodotto in questo documento è fornito in base a una licenza software e può essere usato o copiato esclusivamente in conformità con i termini di tale licenza.

Intel, Atom, Pentium e il logo Intel sono marchi di Intel Corporation registrati negli Stati Uniti e/o in altri paesi.

Copyright © 2012 Intel Corporation. Tutti i diritti riservati.

*Altri marchi e denominazioni potrebbero essere proprietà di terzi.

**Questo codice sorgente di esempio è rilasciato in base al Contratto di licenza per il codice sorgente di esempio Intel

Para obter informações mais completas sobre otimizações do compilador, consulte nosso aviso de otimização.
Tags: