2010-09-09 12 views
5

mi proyecto de procesamiento de imágenes funciona con imágenes en escala de grises. Tengo la plataforma de procesador ARM Cortex-A8. Quiero hacer uso del NEON.Carga 8bit uint8_t como uint32_t?

Tengo una imagen en escala de grises (considere el siguiente ejemplo) y en mi alogorithm, tengo que agregar solo las columnas.

¿Cómo puedo cargar cuatro píxeles de 8 bits en paralelo valores, que son uint8_t, como cuatro uint32_t en uno de los registros de 128 bits NEON? ¿Qué intrínseco debo usar para hacer esto?

quiero decir:

alt text

debo cargarlos como 32 bits, porque si se fijan bien, el momento en que haga 255 + 255 es 512, que no puede ser detenido en una de 8 bits registro.

p. Ej.

255 255 255 255 ......... (640 pixels) 
255 255 255 255 
255 255 255 255 
255 255 255 255 
. 
. 
. 
. 
. 
(480 pixels) 
+2

255 + 255 = 510. – kennytm

Respuesta

11

Recomendaré que dedique un poco de tiempo a entender cómo funciona SIMD en ARM. Mira:

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 que pueda empezar. A continuación, puede implementar su código SIMD utilizando el ensamblador en línea o los intrínsecos de ARM correspondientes recomendados por domen.

3

Si necesita sumar hasta 480 valores de 8 bits, técnicamente necesitará 17 bits de almacenamiento intermedio. Sin embargo, si realiza las adiciones en dos etapas, es decir, en las 240 filas superiores y luego en las 240 filas inferiores, puede hacerlo en 16 bits cada una. Luego puede agregar los resultados de las dos mitades para obtener la respuesta final.

En realidad, hay una instrucción NEON adecuada para su algoritmo llamada vaddw. Agregará un vector de dword a un vector qword, y este último contendrá elementos que son dos veces más anchos que el primero. En su caso, vaddw.u8 se puede usar para agregar 8 píxeles a 8 acumuladores de 16 bits. Entonces, vaddw.u16 se puede usar para agregar los dos conjuntos de 8 acumuladores de 16 bits en un conjunto de 8 de 32 bits. Tenga en cuenta que debe usar las instrucciones dos veces para obtener ambas mitades.

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

2

No hay instrucciones que puedan cargar su valor de 4 8bit en 4 registros de 32 bits.

debe cargarlos y luego usar un vshl dos veces. porque neon no puede usar 32 registros, tendrá que trabajar en 8 píxeles (y no en 4)

Puede usar solo el registro de 16bits. debería ser suficiente ...

0

Cargue los 4 bytes usando una instrucción de carga de carril único (vld1 <register>[<lane>], [<address]) en un registro q, luego use dos instrucciones de movimiento (vmovl) para promocionarlos primero a 16 y luego a 32 bit. El resultado debería ser algo así como (en GNU sintaxis)

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, a continuación, escribir [<address>: 32] lugar en la instrucción de carga, a ahorrar un ciclo o dos. Si haces eso y la dirección no está alineada, obtendrás una falla, sin embargo.

Um, me acabo de dar cuenta de que quieres utilizar elementos intrínsecos, no ensamblados, así que aquí está lo mismo con los elementos 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); 
Cuestiones relacionadas