Estoy tratando de optimizar este código c usando el desenrollado de bucle de 4 vías

Lo que estoy tratando de hacer es tomar este código C y optimizarlo usando una técnica llamada desenrollamiento de bucle, pero en este caso quiero usar desenrollado de bucle de cuatro vías Ahora, entiendo la técnica y entiendo el concepto, simplemente no sé cómo aplicarlo a este código. ¿Tengo que añadir algunas variables extra? ¿Debo tener algún código después de cada bucle o solo al final de todos los bucles? Este código es un código de bloque de 8×8 que trata de tomar píxeles y girarlo 90 grados en sentido antihorario. Cualquier ayuda sería apreciada grandemente. Gracias.

/* * rotate8 - rotate with 8x8 blocking */ char rotate8_descr[] = "rotate8: rotate with 8x8 blocking"; void rotate8(int dim, pixel *src, pixel *dst) { int i, j, ii, jj; for(ii = 0; ii < dim; ii += 8) for(jj = 0; jj < dim; jj += 8) for (i = ii; i < ii + 8; i++) for (j = jj; j < jj + 8; j++) dst[RIDX(dim-1-j, i, dim)] = src[RIDX(i, j, dim)]; } 

Puede reemplazar el bucle interno con 8 líneas explícitas de código

  dst[RIDX(dim-1-jj, i, dim)] = src[RIDX(i, jj, dim)]; dst[RIDX(dim-1-(jj+1), i, dim)] = src[RIDX(i, (jj+1), dim)]; ... dst[RIDX(dim-1-(jj+7), i, dim)] = src[RIDX(i, (jj+7), dim)]; 

de modo que está reemplazando la variable de bucle escribiendo explícitamente una línea para cada valor que toma.

Ahora puede repetir que para los 8 valores del siguiente bucle, tendrá 8 x 8 líneas de código, y así sucesivamente.

Como cualquier otra cosa que no sea un ejercicio de comprensión, esto me parece bastante inútil, los comstackdores hacen este tipo de cosas de manera muy eficiente, optimizarán donde tenga sentido. El enrollado manual rara vez produce un código óptimo.

Quería decir perfil, pero luego lo hice yo mismo. La parte sorprendente es que el bucle interno se realiza más rápido con exactamente su diseño; desenrollarlo a mano es realmente más lento.

Sin embargo, la captura real es la macro RIDX. Cambiar el diseño de la memoria y cambiar los bucles externos tiene un impacto significativo .

Aquí está mi versión más rápida con sangría para mostrar dónde difiere de su versión. Se asume que la macro RIDX es como se define.

 #define RIDX(x,y,d) (x+(y)*(d)) typedef unsigned char pixel; void rotate8(int dim, pixel *src, pixel *dst) { int i, j, ii, jj; for(jj = 0; jj < dim; jj += 8) for(ii = 0; ii < dim; ii += 8) for (i = ii; i < ii + 8; i++) for (j = jj; j < jj + 8; j++) dst[RIDX(dim-1-j, i, dim)] = src[RIDX(i, j, dim)]; } 

... lección aprendida: siempre perfil 🙂

 gcc -funrull-loops

No debe desenrollar los bucles usted mismo a menos que GCC no pueda hacerlo (ver el ensamblaje) y ha probado, mediante un generador de perfiles, que tiene que acelerar esta parte del código.

Ese código de ejemplo que tiene parece un candidato perfecto para el desenrollado automático de bucles.

Algunas otras banderas útiles:

 -O3 // activa muchas optimizaciones (casi todas)
 -ftree-vectorize -msse2 // vectoriza automáticamente algunos bucles

http://www.relisoft.com/book/lang/pointer/2ptrarr.html

Si su comstackdor no puede optimizar la versión del algoritmo que se puede leer y mantener en humanos, y usted tiene que doblar como comstackdor humano, ¡compre un nuevo comstackdor! Nadie puede permitirse más comstackdores humanos. Entonces, ten piedad de ti mismo y de tus compañeros progtwigdores, quienes tendrán que mirar tu código.