Pregunta

mi proyecto de procesamiento de imágenes trabaja con imágenes en escala de grises. Tengo plataforma de procesador ARM Cortex-A8. Quiero hacer uso de las luces de neón.

tengo una imagen en escala de grises (considere el siguiente ejemplo) y en mi alogorithm, tengo que añadir sólo las columnas.

¿Cómo puedo cargar cuatro valores de 8 bits de píxeles en paralelo, que son uint8_t , como cuatro uint32_t en uno de los 128 registros poco NEON? Lo intrínseca tengo que utilizar para hacer esto?

Me refiero a:

text alt

Me debe cargarlos como 32 bits, porque si se fijan bien, el momento en que hago 255 + 255 es 512, que no se llevará a cabo en un registro de 8 bits.

por ejemplo.

255 255 255 255 ......... (640 pixels)
255 255 255 255
255 255 255 255
255 255 255 255
.
.
.
.
.
(480 pixels) 
¿Fue útil?

Solución

Yo le recomendará que pasar un poco de tiempo entender cómo funciona SIMD en ARM. Vistazo a:

Tome un vistazo a:

  1. http: //blogs.arm.com/software-enablement/161-coding-for-neon-part-1-load-and-stores/
  2. http: //blogs.arm.com/software-enablement/196-coding-for-neon-part-2-dealing-with-leftovers/
  3. http: // blogs.arm.com/software-enablement/241-coding-for-neon-part-3-matrix-multiplication/
  4. http://blogs.arm.com/software-enablement/277-coding-for-neon-part-4-shifting-left-and-right/

para empezar. A continuación, puede aplicar su código ensamblador en línea usando SIMD o intrínsecos ARM recomendados por Domen correspondiente.

Otros consejos

Depende de su compilador y (posible falta de) las extensiones.

Ie. para GCC, esto podría ser un punto de partida: http: //gcc.gnu .org / onlinedocs / gcc / ARM-NEON-Intrinsics.html

Si necesita sumar hasta 480 valores de 8 bits, entonces sería técnicamente necesitan 17 bits de almacenamiento intermedio. Sin embargo, si realiza las adiciones en dos etapas, es decir, la parte superior 240 filas entonces inferiores 240 filas, puede hacerlo en 16 bits cada uno. A continuación, puede añadir los resultados de las dos mitades para obtener la respuesta final.

En realidad, hay una instrucción de neón, que es adecuado para su algoritmo llamado vaddw. Se añade un vector DWORD a un vector QWord, con los últimos elementos que contienen que son dos veces tan ancho como la primera. En su caso, vaddw.u8 se puede utilizar para agregar 8 píxeles a 8 acumuladores de 16 bits. Entonces, vaddw.u16 se puede utilizar para agregar las dos series de 8 acumuladores de 16 bits en un grupo de 8 unidades de 32 bits -. Tenga en cuenta que debe utilizar la instrucción dos veces para obtener dos mitades

Si es necesario, también puede convertir los valores de nuevo a 16 bits o 8 bits utilizando vmovn o vqmovn.

No es la instrucción que puede cargar su valor de 8 bits 4 en 4 de 32 bits registrar.

debe cargar ellos y luego usar un vshl dos veces. porque no se puede utilizar de neón 32 registros que tendrá que trabajar en 8 píxeles (y no 4)

Se puede utilizar solamente 16bits registrar. debe ser lo suficientemente ...

Cargar los 4 bytes utilizando una instrucción de carga de un solo carril (vld1 <register>[<lane>], [<address]) en una q-registro, a continuación, utilizar dos instrucciones de movimiento de largo (vmovl) promover ellos primero a 16 y luego a 32 bits. El resultado debería ser algo así como (en la sintaxis de GNU)

vld1 d0[0], [<address>] @Now d0 = (*<addr>, *<addr+1>, *<addr+2>, *<addr+3>, <junk>, ... <junk> )
vmovl.u8 q0, d0 @Now q1 = (d0, d1) = ((uint16_t)*<addr>, ... (uint16_t)*<addr+3>, <junk>, ... <junk>)
vmovl.u16 q0, d2 @Now d0 = ((uint32_t)*<addr>, ... (uint32_t)*<addr+3>), d1 = (<junk>, ... <junk>)

Si usted puede garantizar que <address> es de 4 bytes alineados, entonces [<address>: 32] escritura en lugar de la instrucción de carga, para salvar a un ciclo o dos. Si lo hace, y la dirección no está alineado, obtendrá un fallo, sin embargo.

Um, me acabo de dar cuenta que desea utilizar funciones intrínsecas, no de montaje, por lo que aquí es lo mismo con los intrínsecos.

uint32x4_t v8; // Will actually hold 4 uint8_t
v8 = vld1_lane_u32(ptr, v8, 0);
const uint16x4_t v16 = vget_low_u16(vmovl_u8(vreinterpret_u8_u32(v8)));
const uint32x4_t v32 = vmovl_u16(v16);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top