Existe-t-il un moyen d'utiliser AVX/SSE pour prendre un vecteur de flottants, arrondir à l'inférieur et produire un vecteur d'ints ? Toutes les méthodes intrinsèques de floor semblent produire un vecteur final en virgule flottante, ce qui est étrange car l'arrondi produit un entier !
Réponses
Trop de publicités?Une méthode simple consisterait à utiliser ce qui suit ROUNDPS et en appliquant ensuite l'instruction CVTPS2DQ pour convertir le float
à mots entiers doubles signés . Le code ressemblerait à ceci :
; xmm0 is assumed to be packed float input vector
roundps xmm0, xmm0, 3 ; truncate mode, see below as requested in comment on the other answer
cvtps2dq xmm0, xmm0
; xmm0 now contains the (rounded) packed integer vector
Pour les vecteurs AVX ymm, préfixez les instructions par "V" et remplacez les xmm par des ymm.
ROUNDPS fonctionne comme suit
Arrondir les valeurs en virgule flottante de simple précision dans xmm2/m128 et placer le résultat dans xmm1. Le mode d'arrondi est déterminé par imm8.
le mode d'arrondi (l'opérande immédiat/le troisième opérande) peut avoir les valeurs suivantes (tirées du tableau 4-15 - Rounding Modes and Encoding of Rounding Control (RC) Field
des documents actuels d'Intel) :
Rounding Mode RC Field Setting Description
----------------------------------------------------------
Round to nearest (even) 00B Rounded result is the closest to the infinitely precise result. If two values are equally close, the result is nearest (even) the even value (i.e., the integer value with the least-significant bit of zero).
Round down (toward −∞) 01B Rounded result is closest to but no greater than the infinitely precise result.
Round up (toward +∞) 10B Rounded result is closest to but no less than the infinitely precise result.
Round toward 0 (truncate) 11B Rounded result is closest to but no greater in absolute value than the infinitely precise result.
La raison probable pour laquelle le vecteur de retour de l'opération d'arrondi est float
et non int
Il se peut que, de cette manière, les autres opérations puissent toujours être des opérations sur les flottants (sur des valeurs arrondies) et une conversion en int
serait trivial, comme indiqué.
Les éléments intrinsèques correspondants se trouvent dans les documents référencés. Un exemple de transformation du code ci-dessus en éléments intrinsèques (qui dépendent de l'élément Rounding Control (RC) Field
) est :
__m128 dst = _mm_cvtps_epi32( _mm_floor_ps(__m128 src) );
En appliquant simplement une opération de "troncature" au fichier float
du vecteur en les arrondissant à l'entier précédent le plus proche de zéro, une seule instruction/intrinsèque suffirait :
cvttps2dq xmm0, xmm0
ou comme intrinsèque :
__m128i _mm_cvttps_epi32(__m128 a)
Utiliser les instructions de conversion :
int _mm_cvt_ss2si (__m128 a)
Convertit la composante flottante 32 bits de bas niveau de a
en entier et renvoie cet entier. Les trois composantes supérieures de a
sont ignorées.
__m128i _mm_cvtps_epi32 (__m128 a);
Convertit les quatre nombres flottants 32 bits en nombres entiers et renvoie un vecteur de 4 nombres entiers 32 bits.
Ce sont les plus fréquemment utilisés. Il y a variations supplémentaires pour gérer les conversions.
Options d'instruction unique :
- tronquer vers zéro :
__m128i _mm_cvttps_epi32(__m128 a)
- arrondir à la valeur la plus proche :
__m128i _mm_cvtps_epi32(__m128 a)
Deux instructions, utilisant SSE4.1 ROUNDPS
puis cvtps_epi32
- Rond vers
-INF
:__m128 _mm_floor_ps(__m128 s1)
- Rond vers
+INF
:__m128 _mm_ceil_ps(__m128 s1)
N'utilisez que les autres formes tronquées ou les formes les plus proches de roundps
si vous souhaitez conserver les données au format FP.
Pour les nombres positifs, la troncature et le plancher sont identiques. Pour les nombres entiers négatifs, cvtt(-4.9) = -4
mais floor(-4.9) = -5.0
. Voir floorf()
vs. truncf()
.
Si la valeur de la PF est en dehors de l'intervalle INT_MIN
a INT_MAX
gamme, cvttps
y cvtps
vous donnera 0x80000000
(c'est-à-dire INT_MIN
(juste le bit de signe), qu'Intel appelle la valeur "integer indefinite". Il soulèvera également l'exception FP invalid, mais les exceptions FP sont masquées par défaut.