Comment stocker dans des valeurs non jointives emplacements mémoire avec SSE Intrinsics?

StackOverflow https://stackoverflow.com/questions/3969832

  •  09-10-2019
  •  | 
  •  

Question

Je suis très nouveau pour SSE et ont optimisé une section de code à l'aide intrinsics. Je suis satisfait de l'opération elle-même, mais je suis à la recherche d'une meilleure façon d'écrire le résultat. Les résultats se retrouvent dans trois variables _m128i.

Ce que je suis en train de faire est octets spécifiques de stocker des valeurs de résultat à des emplacements de mémoire non contiguës. Je fais actuellement ceci:

__m128i values0,values1,values2;

/*Do stuff and store the results in values0, values1, and values2*/

y[0]        = (BYTE)_mm_extract_epi16(values0,0);
cb[2]=cb[3] = (BYTE)_mm_extract_epi16(values0,2);
y[3]        = (BYTE)_mm_extract_epi16(values0,4);
cr[4]=cr[5] = (BYTE)_mm_extract_epi16(values0,6);

cb[0]=cb[1] = (BYTE)_mm_extract_epi16(values1,0);
y[1]        = (BYTE)_mm_extract_epi16(values1,2);
cr[2]=cr[3] = (BYTE)_mm_extract_epi16(values1,4);
y[4]        = (BYTE)_mm_extract_epi16(values1,6);

cr[0]=cr[1] = (BYTE)_mm_extract_epi16(values2,0);
y[2]        = (BYTE)_mm_extract_epi16(values2,2);
cb[4]=cb[5] = (BYTE)_mm_extract_epi16(values2,4);
y[5]        = (BYTE)_mm_extract_epi16(values2,6);

Lorsque les tableaux y, cb et cr sont octet (unsigned char). Cela me semble mal à, pour des raisons que je ne peux pas définir. Quelqu'un at-il des suggestions pour une meilleure façon?

Merci!

Était-ce utile?

La solution

Vous ne pouvez pas fondamentalement - SSE ne dispose pas d'un magasin de dispersion, et il est une sorte de tous conçus autour de l'idée de faire un travail sur vectorisé flux de données contiguës. En fait, la plupart des travaux impliqués dans faire quelque chose SIMD réarranger vos données afin qu'il soit contigu et vectorisable. Donc, la meilleure chose à faire est de réorganiser vos structures de données afin que vous puissiez les écrire 16 octets à la fois. Ne pas oublier que vous pouvez réorganiser les composants dans votre vecteur SIMD avant de les engager à la mémoire.

A défaut, l'op PEXTRW (_mm_extract_epi16 de intrinsèque) est à peu près la seule façon de tirer un court d'un registre SSE et stocker dans un registre entier. L'autre approche disponible pour vous est d'utiliser le déballer et mélanger ops (_mm_shuffle_ps etc.) aux données Pivoter dans le bas mot du registre, puis MOVSS / _mm_store_ss() pour stocker cette faible mot à une mémoire à la fois.

Vous constaterez probablement que l'utilisation d'une union ou données entre les registres à usage SSE et général, fournira des performances très médiocre en raison d'un détail subtil de mise en œuvre du processeur appelé load - a frappé - magasin décrochage . Au fond, il n'y a aucun moyen direct pour transférer des données entre les types de registres; le processeur doit d'abord écrire les données SSE à la mémoire, et ensuite lu à nouveau dans le GPR. Dans de nombreux cas, cela signifie qu'il doit caler l'opération de chargement et attendez que le magasin avant efface toutes les instructions supplémentaires peuvent être exécutés.

Autres conseils

Je ne sais pas SSE spécifiquement, mais en général le point de l'ensemble des unités vectorisées est qu'ils peuvent fonctionner très rapidement fourni un alignement particulier des données et le formatage. Il est donc à vous de fournir et extraire les données dans le format et l'alignement.

SSE ne pas la scatter / gather fonctionnalités dont vous avez besoin, même si cela est probablement à venir dans les prochaines architectures SIMD.

Comme cela a déjà été suggéré, vous pouvez utiliser un syndicat, par exemple:.

typedef union
{
    __m128i v;
    uint8_t a8[16];
    uint16_t a16[8];
    uint32_t a32[4];
} U128;

Idéalement, ce genre de manipulation se produit uniquement en dehors des boucles critiques, car il est très inefficace par rapport aux opérations SIMD simples sur les éléments de données contiguës.

Vous pouvez essayer d'utiliser pour extraire les octets de l'Union.

union
{
    float value;
    unsigned char ch[8];
};

et puis attribuer les octets selon les besoins
Jouez avec union idée, peut-être remplacer le ch unsigned char [8] avec une struct anonyme?
Peut-être que vous pouvez obtenir d'autres idées de

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top