Question

mon projet de traitement d'images fonctionne avec des images en niveaux de gris. Je ARM plate-forme de processeur Cortex-A8. Je veux utiliser NEON.

J'ai une image en niveaux de gris (considérer l'exemple ci-dessous) et dans mon alogorithm, je dois ajouter que les colonnes.

Comment charger quatre valeurs de pixels de 8 bits en parallèle, qui sont uint8_t , quatre uint32_t dans l'une des 128 registres NEON bits? Que intrinsèque dois-je utiliser pour ce faire?

Je veux dire:

text alt

Je dois les charger en 32 bits parce que si vous regardez attentivement, le moment que je fais 255 + 255 est 512, qui ne peut être tenue dans un registre 8 bits.

par exemple.

255 255 255 255 ......... (640 pixels)
255 255 255 255
255 255 255 255
255 255 255 255
.
.
.
.
.
(480 pixels) 
Était-ce utile?

La solution

Je recommande que vous passiez un peu de compréhension de la façon dont le temps SIMD fonctionne sur ARM. Regardez:

Jetez un oeil à:

  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/

pour commencer. Vous pouvez ensuite mettre en œuvre votre code SIMD en utilisant assembleur en ligne ou correspondant intrinsics ARM recommandés par Domen.

Autres conseils

dépend de votre compilateur et (éventuel manque de) extensions.

Ie. pour GCC, cela pourrait être un point de départ: http: //gcc.gnu .org / onlinedocs / gcc / ARM NEON-Intrinsics.html

Si vous devez additionner jusqu'à 480 valeurs de 8 bits vous alors techniquement besoin 17 bits de stockage intermédiaire. Toutefois, si vous effectuez les ajouts en deux étapes, à savoir, supérieure à 240 lignes, puis 240 lignes en bas, vous pouvez le faire en 16 bits chacun. Ensuite, vous pouvez ajouter les résultats des deux moitiés pour obtenir la réponse finale.

Il est en fait une instruction NEON qui convient à votre algorithme appelé vaddw. Il ajoutera un vecteur dword à un vecteur QWORD, avec celui-ci contenant des éléments qui sont deux fois plus large que l'ancien. Dans votre cas, vaddw.u8 peut être utilisé pour ajouter 8 pixels à 8 accumulateurs 16 bits. Ensuite, vaddw.u16 peut être utilisé pour ajouter les deux ensembles de 8 accumulateurs 16 bits dans un ensemble de 8 bits les 32 -. Notez que vous devez utiliser l'instruction deux fois pour les deux moitiés

Si nécessaire, vous pouvez également convertir les valeurs à 16 bits ou 8 bits en utilisant vmovn ou vqmovn.

Il n'y a pas d'instruction qui peut charger votre valeur 4 8bit dans 4 32bit registre.

vous devez les charger et utiliser un vshl deux fois. parce que le néon ne peut pas utiliser 32 registres que vous aurez à travailler sur 8 pixels (et non 4)

Vous pouvez utiliser uniquement enregistrer 16bits. il devrait être suffisant ...

Charger les promouvoir première à 16, puis à 32 bits les 4 octets en utilisant une instruction de chargement à voie unique (vld1 <register>[<lane>], [<address]) dans un q-registre, puis d'utiliser deux instructions de déplacement continue (vmovl). Le résultat devrait être quelque chose comme (dans la syntaxe 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 vous ne pouvez garantir que <address> est de 4 octets aligné, puis [<address>: 32] écriture à la place dans l'instruction de charge, pour sauver un cycle ou deux. Si vous le faites et l'adresse désaxement, vous aurez une faute, cependant.

Euh, je viens de réaliser que vous voulez utiliser intrinsics, pas le montage, voici donc la même chose avec intrinsics.

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);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top