iphone performance arm thumb

Rendimiento ARM vs Thumb en iPhone 3GS, código de punto no flotante



performance (3)

Me preguntaba si alguien tenía algún número importante en el rendimiento del código ARM vs Thumb en el iPhone 3GS. Específicamente para el código de punto no flotante (VFP o NEON): soy consciente de los problemas con el rendimiento del punto flotante en el modo Pulgar.

¿Hay un punto en el que el tamaño de código adicional de las instrucciones de ARM más grandes se convierta en un peligro para el rendimiento? En otras palabras, si mi código ejecutable es relativamente pequeño en comparación con la memoria disponible, ¿hay alguna diferencia de rendimiento medida para activar el modo Pulgar?

La razón por la que pregunto es que si bien puedo habilitar ARM para los archivos fuente específicos de NEON en Xcode usando la opción "-marm", esto rompe la construcción del simulador porque GCC está construyendo x86. Me preguntaba si debería desactivar "compilar como pulgar" y terminar con eso.



El código del pulgar esencialmente siempre será más lento que el ARM equivalente. El único caso en el que el código Thumb puede ser una gran ganancia de rendimiento es si marca la diferencia entre el ajuste de su código en la memoria en chip o en el caché.

Es difícil dar números exactos sobre las diferencias de rendimiento, ya que depende totalmente de lo que realmente hace su código.

Puede establecer marcas de compilación por arquitectura en XCode, lo que evitaría romper la construcción del simulador. Consulte la documentación de configuración de compilación XCode.


No sé sobre el iPhone, pero una afirmación general de que el pulgar es más lento que el ARM no es correcta en absoluto. Dada la memoria de estado de espera de 32 bits de ancho cero, el pulgar será un poco más lento, números como 5% o 10%. Ahora, si es thumb2 que es una historia diferente, se dice que thumb2 puede correr más rápido, no sé lo que el iPhone tiene, supongo, es que no es thumb2.
Si no se está quedando sin memoria de 32 bits de estado de espera cero, sus resultados variarán. Una cosa grande es la memoria de 32 bits de ancho. Si está ejecutando un bus de 16 bits de ancho como la familia GameBoy Advance, y hay algunos estados de espera en esa memoria o ROM, entonces Thumb puede fácilmente ejecutar ARM para el rendimiento, aunque se necesitan más instrucciones para realizar la misma tarea.

¡Prueba tu código! No es difícil inventar una prueba que proporcione los resultados que le interesan o no. Es tan fácil mostrar el pulgar con el dedo que se va y el pulgar. A quién le importa qué son los dhrystones, lo importante es la velocidad con la que se ejecuta SU código HOY.

Lo que he encontrado a lo largo de los años al probar el rendimiento del código para ARM es que su código y su compilador son el factor más importante. Entonces, el pulgar es un poco más lento en teoría porque usa un poco más de instrucciones para realizar la misma tarea. ¿Pero sabías que tu compilador favorito podría ser horrible y simplemente cambiando los compiladores podrías correr varias veces más rápido (gcc cae en esa categoría)? O usar el mismo compilador y mezclar las opciones de optimización. De cualquier manera, puede evitar la diferencia entre el brazo y el pulgar si es inteligente al usar las herramientas. Probablemente lo sepa, pero le sorprendería saber cuántas personas piensan que la única forma en que saben cómo compilar el código es la única y la única forma de obtener un mejor rendimiento es lanzar más memoria u otro hardware al problema.

Si estás en el iPhone, ¿escucho que esa gente está usando LLVM? Me gusta el concepto llvm de muchas maneras y estoy ansioso por usarlo como mi controlador diario cuando madura, pero descubrí que producía un código que era un 10-20% (o mucho más) más lento para la tarea en particular que estaba realizando. Estaba en modo brazo, no probé el modo pulgar y tenía un caché l1 y l2 activado. Si lo hubiera probado sin los cachés para comparar realmente el pulgar con el brazo, probablemente lo vería un poco más lento, pero si lo piensa (lo cual no me interesaba en ese momento) puede almacenar en caché el doble de código de pulgar que el código de brazo que PODRÍA implicar que, a pesar de que hay un poco más de código en general para la tarea, el almacenamiento en caché de una cantidad significativamente mayor y la reducción del tiempo promedio de recuperación puede ser notablemente más rápido. Puede que tenga que intentar eso.

Si está utilizando llvm, tiene el otro problema de varios lugares para realizar optimizaciones. Al pasar de C a bytecode puede optimizar, luego puede optimizar el bytecode, luego puede combinar todo su bytecode y optimizarlo como un todo, luego, al pasar del byte code al ensamblador, puede optimizar. Si solo tuviera 3 archivos de origen y asumiera que solo había dos niveles de optimización por oportunidad, aquellos que no se optimizan o optimizan, con gcc tendría 8 combinaciones para probar, con llvm el número de experimentos es casi un orden de magnitud mayor . Más de lo que realmente puedes correr, cientos a miles. Para la prueba que estaba ejecutando, NO estaba optimizando el paso de C a bytecode, luego NO optimizaba el bytecode por separado, sino que lo optimizaba después de fusionar los archivos de bytecode en uno grande (ger). El hecho de tener llc optimizado en el camino para armar produjo los mejores resultados.

Línea de fondo ... prueba, prueba, prueba.

EDITAR:

He estado usando la palabra bytecode, creo que el término correcto es bitcode en el mundo LLVM. El código en los archivos .bc es lo que quiero decir ...

Si va de C a ARM utilizando LLVM, hay un código de bits (bc) en el medio. Hay opciones de línea de comandos para optimizar en el paso de C a bc. Una vez bc puede optimizar por archivo, bc a bc. Si elige, puede combinar dos o más archivos de bc en archivos de bc más grandes, o simplemente convertir todos los archivos en un solo archivo de bc grande. Entonces cada uno de estos archivos combinados también puede ser optimizado.

Mi teoría, que solo tiene un par de casos de prueba detrás de esto, es que si no realiza ninguna optimización hasta que tenga todo el programa / proyecto en un gran archivo de BC, el optimizador tiene la cantidad máxima si la información con la que desea hacer su trabajo Así que eso significa ir de C a bc sin optimización. Luego fusiona todos los archivos bc en un gran archivo bc. Una vez que tenga todo en un solo archivo de bc grande, deje que el optimizador realice su paso de optimización, maximizando la información y, con suerte, la calidad de la optimización. Luego, vaya del archivo bc optimizado al ensamblador ARM. La configuración predeterminada para llc es con la optimización activada, usted quiere permitir esa optimización ya que es el único paso que sabe cómo optimizar para el objetivo. Las optimizaciones de bc a bc son genéricas y no específicas de destino (AFAIK).

Todavía tienes que probar, probar, probar. Continúe y experimente con optimizaciones entre los pasos, vea si hace que su programa se ejecute más rápido o más lento.