2016-10-14 1 views
4

Comme le titre lit, si un registre SIMD 256 bits est:Existe-t-il un moyen efficace d'obtenir le premier élément non nul dans un registre SIMD en utilisant les intrinsèques SIMD?

0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |

Comment puis-je obtenir efficacement l'index du premier élément non nul (à savoir l'indice 2 du premier 1)? Le moyen le plus simple est de conserver en mémoire et de vérifier un par un, mais cela peut coûter très cher. Y a-t-il des idées mignonnes pour le faire?

Répondre

7
  • PCMPEQB/W/D/Q contre un registre des zéros pour obtenir un vecteur d'éléments qui sont tout-1 pour les éléments zéro et tout à zéro pour les éléments nuls.
  • PMOVMSKB pour activer le vecteur de tous les-uns ou tous nuls dans un nombre entier masque binaire
  • inverti que (opérateur C ~, asm instruction NOT) pour obtenir 1s dans le bitmap pour les éléments qui étaient non nulle
  • TZCNT ou BSF cet entier pour trouver le premier bit défini. Méfiez-vous du comportement de BSF si son entrée est entièrement nulle.

S'il n'y a qu'une seule possible valeur non nulle, PCMPEQ contre un vecteur de ce que vous n'avez pas besoin d'inverser ultérieurement. Si c'est le cas, pensez à stocker vos données dans un bitmap en premier lieu, pour réduire votre empreinte de cache par un facteur de 8. Ensuite, vous avez juste TZCNT 64 bits morceaux du tableau.


Oops, vient de remarquer l'étiquette intrinsèques. Le manuel de référence de l'instruction asm répertorie les intrinsèques C pertinents au bas de chaque entrée, et vous pouvez rechercher le finder intrinsèques d'Intel par asm mnemonic. (Voir le tag tag pour les liens).

+0

Merci @Peter. Je pense que vous voulez dire 'LZCNT' au lieu de' TZCNT'. En fait, les intructions ASM sont meilleures, et merci pour l'information intrinsèque de toute façon. Comme vous l'avez mentionné, il n'y a qu'une seule valeur non nulle possible, mais une idée sur la façon de mettre en œuvre au niveau de l'assemblage le problème de 'cache footprint'? – MarZzz

+0

@MarZzz: Le bit haut de l'élément 0 (premier argument à '_mm_set_epi8', dernier argument à' _mm_setr_epi8') va dans le LSB du masque entier. TZCNT/BSF regarde d'abord le bit le plus bas, donc en utilisant les balayages de l'adresse basse à l'adresse haute (si le vecteur a été chargé depuis la mémoire). Si vous voulez numériser dans l'autre sens, utilisez LZCNT ou BSR (qui donnent des résultats différents). –

+0

@MarZzz: Qu'est-ce qui n'est pas évident à propos de l'implémentation d'un bitmap dans asm? Pour ce cas d'utilisation, 'tzcnt rax, [my_bitmap + rsi]' ou autre pour voir s'il y a des hits dans les 64 bits commençant à 8 * rsi (puisque la mémoire est toujours adressée par octet, sauf si vous utilisez le BT/BTR/BTS, mais pas parce qu'ils sont super-lents avec des opérandes de mémoire, voir http://agner.org/optimize/) –