2010-12-05 50 views
5

J'essaie d'optimiser mon code en utilisant l'intrinsèque SSE mais je rencontre un problème où je ne connais pas un bon moyen d'extraire les valeurs entières d'un vecteur après avoir fait les opérations intrinsèques SSE pour obtenir ce que je vouloir.Quel est le moyen le plus efficace pour charger et extraire des valeurs entières de 32 bits à partir d'un vecteur SSE 128 bits?

Est-ce que quelqu'un connaît un bon moyen de le faire? Je programme en C et mon compilateur est la version 4.3.2 de gcc.

Merci pour votre aide.

+0

Hmm ... int * pointeur = adresse_fichier; * (pointeur ++) quatre fois'? – khachik

+0

Y a-t-il une raison pour laquelle vous ne pouvez pas effectuer toutes vos opérations dans les registres SSE, puis les renvoyer en mémoire lorsque vous avez terminé? –

+0

J'ai essayé mais j'ai continué à obtenir des erreurs de compilation que je ne pouvais pas comprendre ... – Kaigi

Répondre

7

Cela dépend de ce que vous pouvez supposer du niveau minimum de support SSE que vous avez.

En remontant jusqu'à SSE2, vous avez _mm_extract_epi16 (PEXTRW) qui peut être utilisé pour extraire n'importe quel élément de 16 bits d'un vecteur de 128 bits. Vous devrez appeler cela deux fois pour obtenir les deux moitiés d'un élément 32 bits.

Dans les versions plus récentes de SSE (SSE4.1 et versions ultérieures), vous avez _mm_extract_epi32 (PEXTRD) qui peut extraire un élément 32 bits en une instruction.

Alternativement, si ce n'est pas dans une boucle critique de performance, vous pouvez simplement utiliser une union, par ex.

typedef union 
{ 
    __m128i v; 
    int32_t a[4]; 
} U32; 
+1

Salut Paul, merci pour votre réponse. Où avez-vous trouvé ces fonctions (mm_extract_epi16/32)? Je ne les vois pas dans la documentation de gcc. Y compris -mmmx -msse -msse2 et -msse3 ne semble pas me laisser l'utiliser et le compilateur dit qu'il y a une déclaration de fonction implicite. – Kaigi

+2

@Kaigi: '_mm_extract_epi16' est dans emmintrin.h,' _mm_extract_epi32' est dans smmintrin.h. Vous aurez besoin d'une version raisonnablement à jour de gcc pour ce dernier. –

5
_mm_extract_epi32 

L'extrait est en effet intrinsics la meilleure option, mais si vous avez besoin pour soutenir SSE2, je recommande ceci:

inline int get_x(const __m128i& vec){return _mm_cvtsi128_si32 (vec);} 
inline int get_y(const __m128i& vec){return _mm_cvtsi128_si32 (_mm_shuffle_epi32(vec,0x55));} 
inline int get_z(const __m128i& vec){return _mm_cvtsi128_si32 (_mm_shuffle_epi32(vec,0xAA));} 
inline int get_w(const __m128i& vec){return _mm_cvtsi128_si32 (_mm_shuffle_epi32(vec,0xFF));} 

J'ai trouvé que si vous reinterpret_cast/union de la vecteur à toute représentation int [4] le compilateur a tendance à vider les choses en mémoire (ce qui peut ne pas être si mauvais) et le lit comme un int, même si je n'ai pas regardé l'assemblage pour voir si les dernières versions du les compilateurs génèrent un meilleur code.