Desarrollo y optimización de aplicaciones para Android* en la plataforma Intel® Atom™

Resumen

Este documento introduce métodos detallados para el desarrollo y migración de una aplicación Android en la plataforma Intel Atom, y describe los métodos más conocidos para desarrollar aplicaciones mediante el Kit para desarrollo nativo para Android (NDK) y para optimizar el rendimiento. Los desarrolladores para Android pueden utilizar este documento como una referencia para crear aplicaciones de alta calidad para la arquitectura Intel.

1. Clasificación de aplicaciones para Android

Las aplicaciones para Android pueden clasificarse en dos tipos, tal como se muestra en la Ilustración 1.

  • Las aplicaciones Dalvik que incluyen código Java* y utilizan solo la API del SDK oficial para Android y los archivos de los recursos necesarios, tales como xml y png, compilados en un archivo APK.
  • Las aplicaciones NDK para Android que incluyen el código Java y los archivos de recursos, así como el código de recursos C/C++ y, algunas veces, el código ensamblador. Todo el código nativo se compila en una biblioteca vinculada dinámica (un archivo .so) y, posteriormente, Java la llama en el programa principal mediante un mecanismo de JNI.


Ilustración 1: Dos tipos de aplicaciones para Android

2. Kit de desarrollo nativo para Android

2.1 Introducción

El Kit de desarrollo nativo para Android (NDK) es una herramienta que complementa al SDK de Android. El NDK es una herramienta poderosa para el desarrollo de aplicaciones para Android debido a que:

  • Crea porciones cruciales para el rendimiento de sus aplicaciones en código nativo. Cuando se utiliza el código Java, el código fuente basado en Java necesita ser interpretado en un idioma informático mediante un equipo virtual. En cambio, el código nativo se compila y optimiza en código binario directamente antes de la ejecución. Con el uso apropiado del código nativo, puede crear código de alto rendimiento en su aplicación, tal como codificado y decodificado de video de hardware, proceso de gráficos y operaciones aritméticas.
  • Reutiliza el código nativo legado. Los códigos C/C++ se compilan en una biblioteca dinámica que el código Java puede llamar con un mecanismo de JNI.

2.2 Descripción general de las herramientas

Durante el período de desarrollo, puede utilizar Intel® Hardware Execution Manager (HAXM) para mejorar el rendimiento del simulador para Android. HAXM es un motor de virtualización con la ayuda de hardware (hipervisor) que utiliza la Tecnología Intel® de virtualización para acelerar la emulación de aplicaciones para Android en un equipo huésped. En combinación con imágenes del emulador para Android x86 que Intel proporciona y el Administrador de Android SDK oficial, HAXM resulta en una experiencia de emulación para Android más rápida en sistemas habilitados para la Tecnología Intel® de virtualización. Para obtener más información sobre HAXM, visite: http://software.intel.com/es-es/articles/intel-hardware-accelerated-execution-manager.

2.3 Instalación de HAXM

Utilice el Administrador de Android SDK para instalar HAXM (recomendable) o, para hacerlo manualmente, descargue el instalador del sitio web de Intel. Si desea actualizarlo automáticamente, instálelo con el administrador del Android SDK, tal como se muestra en la Ilustración 2. [1]


Ilustración 2: Instalar Intel HAXM con el Administrador de Android SDK

También puede descargar un paquete de instalación adecuado desde http://software.intel.com/es-es/android a su plataforma huésped y seguir las instrucciones paso a paso para instalarlo.

2.3.1 Configuración de HAXM

Cuando se ejecuta HAXM, se requiere la imagen del sistema Android x86 que Intel proporciona. Puede descargar la imagen del sistema usando el Administrador de Android SDK o descargarla manualmente del sitio web de la Zona para desarrolladores Intel®.

Después de que las imágenes se instalan satisfactoriamente, las imágenes del emulador de Intel® x86 Android se ejecutan automáticamente utilizando el binario del “emulator-x86” proporcionado con el Android SDK. La Tecnología Intel® de virtualización acelera el emulador Android, lo cual acelera su proceso de desarrollo.

3. Desarrollo y migración de aplicaciones NDK para la Arquitectura de Intel Atom

3.1 Desarrollo de aplicaciones NDK para los dispositivos basados en el procesador Intel Atom

Después de instalar el NDK satisfactoriamente, dedique unos minutos a leer los documentos del directorio <ndk>/docs/, especialmente los denominados OVERVIEW.html y CPU-X86.html, para familiarizarse con el mecanismo del NDK y cómo utilizarlo.

El desarrollo de la aplicación NDK puede dividirse en cinco pasos que se muestran en la Ilustración 3:


Ilustración 3: Proceso del desarrollo de la aplicación NDK

Para ilustrar estos cinco pasos, se utiliza la demostración de hello-jni. Puede encontrar esta demostración en la carpeta NDK Root\samples\hello-jni [5]. La demostración de Hello-jni es una aplicación simple incluida en el NDK que obtiene una cadena de un método nativo en una biblioteca compartida y la utiliza en la interfaz de usuario de la aplicación.

3.1.1. Creación del código nativo

Cree un nuevo proyecto para Android y coloque su código fuente nativo bajo <proyecto>/jni/. El contenido del proyecto se muestra en la Ilustración 4. Esta demostración incluye una simple función en código nativo denominada Java_com_example_hellojni_HelloJni_stringFromJNI(). Tal como se muestra en el código fuente, devuelve una cadena simple de JNI.


Ilustración 4: Creación del código nativo

3.1.2 Creación de MakeFile ‘Android.mk’

Las aplicaciones del NDK se crean para la plataforma ARM de manera predeterminada. Para crear aplicaciones NDK para la plataforma Intel Atom, es necesario agregar APP_ABI := x86 al MakeFile.


Ilustración 5: Creación de MakeFile

3.1.3 Compilación de código nativo

Cree un código nativo al ejecutar la secuencia de comandos 'ndk-build' desde el directorio del proyecto. Se encuentra en el directorio principal de NDK. El resultado aparece en la Ilustración 6.


Ilustración 6: Código nativo compilado

Las herramientas de creación copian automáticamente las bibliotecas compartidas esenciales a la ubicación pertinente en el directorio del proyecto de la aplicación.

3.1.4 Llamada del código nativo de Java

Cuando despliega la biblioteca compartida satisfactoriamente, puede llamar la función desde Java. El código se muestra en la Ilustración 7. Se crea una llamada de la función nativa pública stringFromJNI() en el código Java y esta función carga la biblioteca compartida con System.loadlibrary().


Ilustración 7: Llamada de código nativo desde Java

3.1.5 Depuración con GDB

Si desea depurar la aplicación NDK con GDB, es necesario satisfacer las siguientes condiciones:

  • La aplicación NDK se crea con 'ndk-build'
  • La aplicación NDK se establece en ‘debuggable’ en Android.manifest
  • La aplicación NDK se ejecuta en Android 2.2 (o superior)
  • Un solo destino está en ejecución
  • Hay que agregar el directorio adb a PATH

Utilice el comando ndk-gdb para depurar la aplicación. Puede definir ya sea un punto de interrupción o una depuración paso a paso para realizar un seguimiento del historial de cambios de un valor variable, tal como muestra la Ilustración 8.


Ilustración 8: Depuración de la aplicación NDK con GDB

3.2 Migración de aplicaciones NDK existentes a dispositivos basados en el procesador Intel Atom

En esta sección, se asume que tiene una aplicación Android para la plataforma ARM y necesita migrarla antes de desplegarla en la plataforma Intel Atom.

La migración de las aplicaciones Android a la plataforma Intel Atom es similar al proceso de desarrollo. Los pasos se muestran en la Ilustración 9.


Ilustración 9: Migración de aplicaciones Android a la plataforma Intel Atom

3.2.1 Migración de aplicaciones Dalvik

Las aplicaciones Dalvik pueden ejecutarse directamente en los dispositivos basados en el procesador Intel Atom. La interfaz de usuario necesita ajustarse para el dispositivo de destino. Para un dispositivo de alta resolución, tales como tabletas con una resolución de 1280*800 o superior, la asignación de memoria predeterminada posiblemente no cumpla con los requisitos de la aplicación, lo cual impide que pueda lanzarse. Se recomienda el incremento de la asignación de memoria predeterminada para los dispositivos de alta resolución.

3.2.2 Migración de aplicaciones NDK para Android

La migración de aplicaciones NDK es un poco más complicada que la migración de aplicaciones Dalvik. Todas las aplicaciones NDK se pueden dividir en tres tipos según las siguientes propiedades del código nativo:

  • Consiste en código C/C++ solo que no está relacionado con el hardware
  • Utiliza una biblioteca vinculada dinámica de terceros
  • Incluye código ensamblador que está altamente relacionado con plataformas que no son la arquitectura Intel

Código nativo que consiste en código C/C++ solo que no está relacionado con el hardware

  1. Recompile el código nativo para ejecutar la aplicación satisfactoriamente en la plataforma Intel Atom.
  2. Abra el proyecto de NDK, busque el archivo Android.mk, agregue APP_ABI := armeabi armeabi-v7a x86 en Android.mk y reconstruya el código nativo con ndk-build.
  3. Si no encuentra el archivo Android.mk, utilice el comando ndk-build APP_ABI="armeabi armeabi-v7a x86" para crear el proyecto.
  4. Vuelva a encapsular la aplicación con las plataformas x86 compatibles.

Si el código nativo utiliza una biblioteca vinculada dinámica de terceros, la biblioteca compartida debe volver a compilarse en la versión x86 para la plataforma Intel Atom.

Si el código nativo incluye código ensamblador que esté altamente relacionado con las plataformas que no son de la arquitectura Intel, entonces el código debe volver a escribirse con ensamblador de la arquitectura Intel o C/C++.

4. Métodos más conocidos para desarrollar el código nativo

4.1 Alineación de memoria forzada

Debido a diferencias entre las arquitecturas, plataformas y compiladores, puede que los tamaños de los datos de la estructura de los mismos datos en distintas plataformas sean diferentes. Sin la alineación de memoria forzada, pueden existir errores de carga para tamaños de datos incoherentes. [2]

El siguiente ejemplo describe los tamaños de datos de la misma estructura de datos en distintas plataformas:

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

Esta es una estructura simple con tres variables denominadas mVar1, mVar2 y mVar3.

mVar1 es un int y utilizará 4 bytes
mVar2 es long long int que utilizará 8 bytes
mVar3 también es int, utilizará 4 bytes.

¿Cuántos espacios se necesitan en las plataformas ARM e Intel Atom?

El tamaño de los datos compilados para las plataformas ARM e Intel Atom con un interruptor de compilador predeterminado se muestra en la Ilustración 10. ARM adopta automáticamente doble malign y ocupa 24 bytes, mientras que x86 ocupa 16 bytes.


Ilustración 10: Memoria asignada por marcadores de compilación predeterminados

La variable mVar2 de 8 bytes (64 bits) resulta en un diseño distinto para TestStruct debido a que ARM requiere una alineación de 8 bytes para variables de 64 bits igual que mVar2. En la mayoría de los casos, esto no causa problemas debido a que crear para x86 vs. ARM requiere una reconstrucción completa.

No obstante, una incoherencia de tamaños podría presentarse si una aplicación serializa clases o estructuras. Por ejemplo, usted crea un archivo en una aplicación de ARM y escribe TestStruct en un archivo. Si posteriormente carga los datos desde ese archivo a una plataforma x86, el tamaño de la clase en la aplicación es diferente en el archivo. Problemas similares de alineación de memorias pueden ocurrir en el tráfico de redes que anticipa un diseño de memoria específico.

La opción “-malign-double” del compilador GCC genera la misma alineación de memoria en x86 y en ARM.


Ilustración 11: Memoria asignada cuando se agregan marcadores -malign-double

4.2 Instrucciones de migración de NEON* a SSE [3]

4.2.1 NEON

La tecnología NEON* de ARM se utiliza principalmente en multimedios tales como aplicaciones de smartphones y HDTV. Según la documentación de ARM, su tecnología basada en el motor SIMD de 128 bits, la cual es una extensión de ARM Cortex*–A Series, ofrece al menos 3 veces más rendimiento que la arquitectura de ARMv5 y al menos 2 veces más que la versión subsiguiente: ARMv6. Para obtener más información sobre la tecnología NEON visite: http://www.arm.com/products/processors/technologies/neon.php.

4.2.2 SSE: El equivalente de Intel

SSE es la Streaming SIMD Extension para la arquitectura Intel (IA). En la actualidad, el procesador Intel Atom es compatible con SSSE3 (Supplemental Streaming SIMD Extensions 3) y las versiones anteriores, pero todavía no es compatible con SSE4.x. SSE es un motor de 128 bits que acepta el encapsulamiento de los datos de puntos flotantes. El modelo de ejecución comenzó con la tecnología MMX y SSx es esencialmente la generación más reciente que reemplaza la necesidad de MMX. Para obtener más información, consulte la sección "Volume 1: Basic Architecture" (Volumen 1: Arquitectura básica) de los Manuales para Desarrolladores de software para las Arquitecturas Intel de 64 y 32 bits. La descripción general de SSE, que se encuentra en la sección 5.5, proporciona las instrucciones para SSE, SSE2, SSE3 y SSSE3. Estas operaciones de datos mueven valores de puntos flotantes basados en precisión y de alto contenido entre los registros de XMM o entre los registros de MMX y la memoria. Los registros de XMM fueron diseñados para usarse como un reemplazo de los registros de MMX.

4.2.3 De NEON a SSE a nivel de ensamblador

Cuando utilice el Manual para desarrolladores de software de la arquitectura Intel como una referencia cruzada para todos los mnemotécnicos SSE(x) individuales, examine también las distintas instrucciones al nivel de ensamblador de SSE ubicadas en: http://neilkemp.us/src/sse_tutorial/sse_tutorial.html. Utilice la tabla de contenido para acceder los ejemplos del código o examine los antecedentes.

De manera similar, el siguiente manual de ARM proporciona información sobre NEON y contiene pequeños fragmentos de código ensamblador en la sección 1.4,”Developing for NEON” (Desarrollo para NEON): http://infocenter.arm.com/help/topic/com.arm.doc.dht0002a/DHT0002A_introducing_neon.pdf.

Diferencias clave al comparar el código ensamblador NEON y SSE:

  • Capacidades Endian. Intel es compatible solo con el ensamblaje de marcadores little-endian, mientras que ARM es compatible con el orden de marcadores endian grandes "big" o pequeños "little" (ARM acepta ambos, es bi-endian). En los ejemplos de código proporcionados, el código ARM es little-endian similar a Intel. Nota: Es posible que existan algunas implicaciones con el compilador de ARM. Por ejemplo, la compilación para ARM utilizando GCC incluye marcadores –mlittle-endian y –mbig-endian. Para obtener más información consulte http://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html.
  • Granularidad. En el caso de los ejemplos de código de ensamblaje simple a los que hacemos referencia, compare las instrucciones de ADDPS para SSE (Intel) con VADD.ix para NEON tales como x = 8 ó 16. Observe que este último valor agrega cierta granularidad a los datos que se administrarán como parte del mnemotécnico al que se hace referencia.

Nota: Estas diferencias no son todas las que existen. Puede ver otras diferencias entre NEON y SSE.

4.2.4 De NEON a SSE a nivel de C/C++

Pueden presentarse muchas dificultades de la API durante la migración del código C/C++ y NEON a SSE. Tenga en mente que asumimos que no se utilizará ensamblador inline, que en su lugar se utilizará el código C/C++ verdadero. Las instrucciones NEON también proveen algunas bibliotecas C nativas. Aunque estas instrucciones son código C, no pueden ejecutarse en la plataforma Intel Atom y deben volver a escribirse.

5. Optimización del rendimiento de la aplicación

5.1 Ajuste de rendimiento

Durante el proceso de codificación, utilice los siguientes métodos para optimizar el rendimiento de su aplicación en la plataforma Intel Atom.

5.1.1 Uso de Inline (en línea) en lugar Frequently Used Short (corto utilizado frecuentemente)

Las funciones Inline son mejores para funciones pequeñas tales como el acceso a miembros de datos privados. Las funciones cortas son sensibles al impacto de las llamadas de funciones. Las funciones más largas demoran menos tiempo, de manera proporcionada, en la secuencia de llamadas/llamadas de regreso y se benefician menos de las funciones en línea. [4]

La función Inline (en línea) ahorra la sobrecarga en:

  • Las llamadas de funciones (inclusive el paso de parámetros y la colocación de la dirección del objeto en la pila)
  • Preservación del marco de la pila de la rutina que llama
  • Nueva configuración de pila y marco
  • Comunicación de valor y retorno
  • Restauración de pila y marco anteriores
  • Retorno

5.1.2 Uso de flotante en lugar de doble

FPU es una unidad de punto flotante que es una parte de un sistema especialmente diseñado para llevar a cabo operaciones en los números de puntos flotantes, tales como: suma, resta, multiplicación, división y raíz cuadrada. Algunos sistemas (especialmente las arquitecturas antiguas y basadas en microcódigo) también pueden realizar varias funciones trascendentales tales como cálculos exponenciales o trigonométricos. Los procesadores actuales realizan estos cálculos con rutinas de bibliotecas de software. En la mayoría de las arquitecturas de computadoras modernas para fines generales, una o más FPU están integradas con la CPU [6].

La plataforma Intel Atom tiene la FPU habilitada. En la mayoría de los casos, el usar puntos flotantes en lugar de dobles acelera el proceso de computación de datos y ahorra el ancho de banda de la memoria en los dispositivos basados en el procesador Intel Atom.

5.1.3 Codificación de multisubprocesos

El codificado de multisubprocesos le permite utilizar la función hyper-threading del procesador Intel Atom para aumentar los resultados y mejorar el rendimiento general. Para obtener más información sobre multisubprocesamiento, consulte: http://www.intel.com/content/www/es/es/architecture-and-technology/hyper-threading/hyper-threading-technology.html.

5.2 Creación de aplicaciones de alto rendimiento con marcadores de compilador

Como usted sabe, el código nativo es creado por GCC en aplicaciones para Android. Pero, ¿sabe cuál es el dispositivo de destino predeterminado de GCC? Es el procesador Pentium® Pro. El código binario de destino se ejecuta mejor en la plataforma Pentium Pro si no agrega ningún marcador durante la compilación del código nativo. La mayoría de las aplicaciones para Android se ejecutan en la plataforma Intel Atom en lugar de Pentium Pro. Se recomienda enfáticamente agregar marcadores específicos según su plataforma de destino. Puede agregar los siguientes marcadores recomendados durante la compilación en la plataforma Intel Atom:

-march=atom
-msse4
-mavx
-maes

Para obtener más información sobre los parámetros del compilador, consulte: http://gcc.gnu.org/onlinedocs/gcc/i386-and-x86-64-Options.html.

6. Conclusión

Este documento describe la manera de desarrollar y optimizar las aplicaciones para Android en las plataformas Intel Atom, así como la manera de desarrollar y migrar aplicaciones del NDK.

Un resumen de los puntos clave es:

  • La mayoría de las aplicaciones para Android pueden ejecutarse directamente en la plataforma Intel Atom. Las aplicaciones de NDK necesitan recompilar el código nativo. Si el código ensamblador se incluye en la aplicación, esta porción del código debe volver a escribirse.
  • Aproveche al máximo las funciones de la arquitectura Intel para mejorar el rendimiento de su aplicación para Android.
  • Agregue interruptores de compilación específicos a la plataforma para que el código de creación GCC sea más efectivo.

Referencia

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

Sobre el autor

Dawei es un ingeniero de aplicaciones dedicado a la habilitación de aplicaciones para móviles, incluyendo el desarrollo y optimización de aplicaciones Android para dispositivos x86, y el desarrollo de aplicaciones con HTML5 para la web. Además, Dawei también tiene amplia experiencia en el diseño de interfaces de usuario y experiencias de usuario de aplicaciones.

Avisos

LA INFORMACIÓN QUE CONTIENE ESTE DOCUMENTO SE PROPORCIONA EN RELACIÓN CON LOS PRODUCTOS INTEL. ESTE DOCUMENTO NO CONCEDE LICENCIA ALGUNA, YA SEA EXPRESA O TÁCITA, POR EXCLUSIÓN U OTRO SUPUESTO, RESPECTO DE DERECHOS DE PROPIEDAD INTELECTUAL. A EXCEPCIÓN DE LO ESTABLECIDO EN LOS TÉRMINOS Y CONDICIONES DE VENTA DE INTEL PARA DICHOS PRODUCTOS, EN NINGÚN CASO INTEL SERÁ RESPONSABLE Y RECHAZA CUALQUIER GARANTÍA EXPLÍCITA O IMPLÍCITA CON RESPECTO A LA VENTAY/O EL USO DE LOS PRODUCTOS INTEL, INCLUIDAS LAS RESPONSABILIDADES O GARANTÍAS RELACIONADAS CON LA APTITUD PARA UN FIN DETERMINADO, LA COMERCIABILIDAD O LA INFRACCIÓN DE CUALQUIER PATENTE, DERECHO DE AUTOR U OTRO DERECHO DE PROPIEDAD INTELECTUAL.

SALVO ACUERDO PREVIO POR ESCRITO REALIZADO POR INTEL, LOS PRODUCTOS INTEL NO SE HAN DISEÑADO PARA NINGUNA APLICACIÓN EN LA QUE UN FALLO DEL PRODUCTO INTEL PUEDA CREAR UNA SITUACIÓN EN LA QUE SE PUEDAN PRODUCIR DAÑOS PERSONALES O LA MUERTE.

Intel puede realizar cambios en las especificaciones y descripciones del producto en cualquier momento, sin previo aviso. Los diseñadores no deben confiar en la ausencia de o en las características de cualquiera de las funciones o instrucciones marcadas como “reservada” o “no definida”. Intel las reserva para una definición futura y no se hará responsable de los conflictos o incompatibilidades que surjan de los futuros cambios realizados en las mismas. Esta información está sujeta a cambio sin previo aviso. No concluya un diseño con esta información.

Los productos descritos en este documento pueden contener defectos de diseño o errores conocidos como erratas que pueden hacer que el producto varíe respecto a las especificaciones publicadas. Las erratas detectadas hasta el momento están disponibles a petición del interesado.

Comunicarse con la oficina de ventas o el distribuidor local de Intel para obtener las especificaciones más recientes antes de hacer un pedido del producto.

Para obtener copias de los documentos que tienen un número de pedido y que se mencionan en este documento o en otros documentos de Intel llame al 1-800-548-4725 o visite: http://www.intel.com/design/literature.htm El software y las cargas de trabajo utilizadas en pruebas de rendimiento pueden ser optimizadas para el rendimiento solo en microprocesadores Intel. Las pruebas de rendimiento, como SYSmark y MobileMark, se miden utilizando sistemas informáticos específicos, componentes, software, operaciones y funciones. Cualquier cambio en cualquiera de estos factores puede causar una variación en los resultados. Debe consultar otra información y pruebas de rendimiento para que le ayuden a realizar una evaluación completa de las compras previstas, incluido el rendimiento de ese producto en combinación con otros.

Cualquier código de origen del software reimpreso en este documento se proporciona según una licencia de software y puede utilizarse o copiarse solamente según los términos de esa licencia.

Intel, Atom, Pentium y el logotipo Intel son marcas comerciales de Intel Corporation en EE. UU. y/u otros países.

Copyright © 2012 Intel Corporation. Todos los derechos reservados.

*Las demás marcas y nombres podrían ser considerados como propiedad de terceros.

**Este ejemplo de código fuente se publica según el Contrato de licencia de muestras de código fuente de Intel

Etiquetas:
Para obtener más información sobre las optimizaciones del compilador, consulte el aviso sobre la optimización.