iphone - programa - cómo escribir códigos de ensamblaje en línea sobre LOOP en Xcode LLVM?
swift tutorial español (2)
Aunque esta respuesta no es directamente una respuesta a su pregunta, es más un consejo general sobre el uso de compiladores ensambladores frente a compiladores modernos.
Por lo general, le costará superar al compilador con respecto a la optimización de su código C. Por supuesto, mediante el uso inteligente de ciertos conocimientos sobre cómo se comportan sus datos, es posible que pueda modificarlo solo unos pocos porcentajes.
Una de las razones para esto es que los compiladores modernos utilizan una serie de técnicas cuando se trata de un código como el que describes, por ejemplo, desenrollar bucles, reordenar las instrucciones para evitar puestos de tuberías y burbujas, etc.
Si realmente quieres hacer que ese algoritmo grite, deberías considerar rediseñar el algoritmo en lugar de C para evitar las peores demoras. Por ejemplo, leer y escribir en la memoria es costoso en comparación con el acceso de registro.
Una forma de lograr esto podría ser hacer que su código cargue 4 bytes a la vez usando un unsigned long
y luego hacer los cálculos sobre esto en los registros antes de escribir estos 4 bytes en la operación de una tienda.
Entonces, para recapitular, haga que su algoritmo trabaje de forma más inteligente, no más difícil.
Estoy estudiando sobre montaje en línea. Quiero escribir una rutina simple en iPhone bajo Xcode 4 LLVM 3.0 Compiler. Tengo éxito en escribir códigos básicos de ensamblaje en línea.
ejemplo:
int sub(int a, int b)
{
int c;
asm ("sub %0, %1, %2" : "=r" (c) : "r" (a), "r" (b));
return c;
}
Lo encontré en stackoverflow.com y funciona muy bien. Pero, no sé cómo escribir código sobre LOOP.
Necesito códigos de ensamblaje como
void brighten(unsigned char* src, unsigned char* dst, int numPixels, int intensity)
{
for(int i=0; i<numPixels; i++)
{
dst[i] = src[i] + intensity;
}
}
Eche un vistazo aquí en la sección de bucle - http://en.wikipedia.org/wiki/ARM_architecture
Básicamente, querrás algo como:
void brighten(unsigned char* src, unsigned char* dst, int numPixels, int intensity) {
asm volatile (
"/t mov r3, #0/n"
"Lloop:/n"
"/t cmp r3, %2/n"
"/t bge Lend/n"
"/t ldrb r4, [%0, r3]/n"
"/t add r4, r4, %3/n"
"/t strb r4, [%1, r3]/n"
"/t add r3, r3, #1/n"
"/t b Lloop/n"
"Lend:/n"
: "=r"(src), "=r"(dst), "=r"(numPixels), "=r"(intensity)
: "0"(src), "1"(dst), "2"(numPixels), "3"(intensity)
: "cc", "r3", "r4");
}
Actualizar:
Y aquí está esa versión NEON:
void brighten_neon(unsigned char* src, unsigned char* dst, int numPixels, int intensity) {
asm volatile (
"/t mov r4, #0/n"
"/t vdup.8 d1, %3/n"
"Lloop2:/n"
"/t cmp r4, %2/n"
"/t bge Lend2/n"
"/t vld1.8 d0, [%0]!/n"
"/t vqadd.s8 d0, d0, d1/n"
"/t vst1.8 d0, [%1]!/n"
"/t add r4, r4, #8/n"
"/t b Lloop2/n"
"Lend2:/n"
: "=r"(src), "=r"(dst), "=r"(numPixels), "=r"(intensity)
: "0"(src), "1"(dst), "2"(numPixels), "3"(intensity)
: "cc", "r4", "d1", "d0");
}
Entonces esta versión NEON hará 8 a la vez. Sin embargo, no verifica que numPixels
sea divisible por 8, por lo que definitivamente querrás hacerlo, ¡de lo contrario las cosas saldrán mal! De todos modos, es solo el comienzo para mostrarte lo que se puede hacer. Observe el mismo número de instrucciones, pero realice acciones en ocho píxeles de datos a la vez. Ah, y también tiene la saturación que supongo que querrías.