Je tente de ré-écrire un Raytracer à l'aide d'extensions Streaming SIMD. Mon Raytracer d'origine a utilisé l'assemblage intégré et les instructions forts> Mouvements forts> pour charger les données dans les registres XMM. J'ai lu que le compilateur intrinsique n'est pas significativement plus lent que l'assemblage en ligne (je suppose que je peux même gagner de la vitesse en évitant les accès à la mémoire non alignée), et beaucoup plus portable, je tente donc de migrer mon code SSE pour utiliser la intrinsèque de XMMintrin.h . La classe principale affectée est vectorielle, qui ressemble à ceci comme ceci:
#include "xmmintrin.h" union vector { __m128 simd; float raw[4]; //some constructors //a bunch of functions and operators } __attribute__ ((aligned (16)));
5 Réponses :
Si vous avez besoin d'un tableau de N de ces objets, allocation Vecteur RAW [N + 1] CODE> et utilisez
Vector * Constry Array = Reterpret_cast
Mon problème principal est de déclarer des instances locales de ces objets - je n'ai pas réellement besoin d'un tableau d'entre eux.
@Octavianus: Cela peut certainement être utilisé pour N = 1, vous avez juste une plus grande quantité de frais généraux.
Le moyen le plus simple est Si vous ne l'avez pas encore, vous voudrez peut-être vérifier alors vous pouvez construire Votre syndicat: p> Enfin, si cela ne fonctionne pas, vous pouvez toujours créer votre propre petite classe: p> Il allouera un peu plus de stockage que nécessaire, mais de cette manière l'alignement est garanti. P> avec chance, le compilateur peut être capable d'optimiser le truc d'alignement du pointeur s'il détecte L'alignement est nécessaire correctement. p> p> std :: aligné_storage code>, qui prend un alignement en tant que second paramètre.
Cela semble attrayant, mais où puis-je trouver std :: aligné_storage? Google a été violemment inutile; Il suggère des types_Traits mais y compris cela ne me permet pas de compiler avec elle. Est aligné_storage si nouveau que g ++ 4.4.3 ne le supporte pas?
@Octavianus: possible, je n'ai pas g ++ 4.4.3 à portée de main. Peut-être devriez-vous essayer d'utiliser std :: tr1 :: aligned_storage code> à la place (dans
J'utilise ce truc de l'Union tout le temps avec Les autres réponses contiennent de bonnes soluarardages cependant. P> __ m128 code> et fonctionnait avec GCC sur Mac et Visual C ++ sous Windows, il faut donc être un bogue dans le compilateur que vous utilisez. P>
Ce n'est pas un bug de compilateur. De nombreuses machines sont par défaut à 16 octets d'alignement sur la pile, mais certaines machines plus anciennes ne garantissent rien au-dessus de 8 octets.
__M128 garantit un alignement de 16 octets
Oui. Mais si vous le collez dans une structure, il semble de garantir l'alignement de 16 octets par rapport au début de la structure.
@Octavianus: Alors c'est un bug de compilateur. Alignof (Union) Code> doit être> =
Alignof () Code> Son membre le plus aligné.
Normalement, tout ce dont vous avez besoin est:
union vector { __m128 simd; float raw[4]; };
Il y a quelques semaines, j'avais réécrit une mission de traçage de la vieille rayon de mes journées universitaires, à la mettre à jour pour l'exécuter sur 64 bits Linux et à utiliser les instructions SIMD. (L'ancienne version a été incidemment dirigée sous DOS sur un 486, pour vous donner une idée de quand je l'ai fait quand je l'ai fait).
Il y a très bien peut-être de meilleures façons de le faire, mais voici ce que j'ai fait ... P>
typedef float v4f_t __attribute__((vector_size (16))); class Vector { ... union { v4f_t simd; float f[4]; } __attribute__ ((aligned (16))); ... };
Le __M128 TypeDEF est identique à votre typlef pour v4f_t, c'est donc ce que j'ai peur.
@OCTAVIANUS: le __ M128 CODE> TLEDEF comprend également l'attribut
May_alias CODE>, ce qui permet de créer des points sûrs pour créer
__ m128 * code> des pointeurs sur n'importe quel objet arbitraire, même non -
float code>. (c'est-à-dire que c'est comme
char * code> peut alias sur n'importe quoi). Mais ouais,
__ attribut __ ((aligné (16))) code> sur l'Union est redondant; Il a déjà cela à partir du
v4f_t code> ou du membre
__ m128 code>. De plus, la syntaxe de vecteur native GNU C permet d'indexer dans un
__ m128 v code> comme
V [3] code>, de sorte que l'Union est redondante. (Sauf pour y accéder avec un
float * code>; la chose stricte d'aliasing ne va pas dans les deux sens. Ou pour MSVC Compat.)
Si vous avez une version récente de g ++ qui prend en charge
std :: aligned_storage code>, vous pouvez obtenir un stockage aligné de manière portable et fonctionnera également sur d'autres compilateurs aussi.
Et si vous contournez le syndicat et utilisez simplement le DIRECT __M128? Est-ce que cela change quelque chose?
Contourner entièrement l'Union en fait beaucoup plus douloureux d'accéder aux membres individuels. J'ai également une classe de vecteur Vectorpacket qui obtient plus d'avantages de la SSE que des vecteurs standard, mais comme exemple, mon analyse comparative indique qu'il est plus rapide que je puisse ajouter les membres d'un seul produit de points en série au lieu de mélanger à plusieurs reprises le registre à Ajouter tout en restant dans mon bloc SSE. Je ne connais pas
std :: aligné_storage code>; Cela dit, ma machine a g ++ 4.4.3, mais il y a une deuxième machine que j'espérais pouvoir pouvoir l'exécuter sur ce qui est verrouillé à 3.4.6.
logiciel.intel.com/en-us/forums/showThread. PHP? T = 63876 Notez-vous qu'elles couchent des types de M128. Vous pouvez également lancer M128 au tableau.
@Tanycorn: Non,
(flotteur *) my_m128 code> est pas i> sûr. La propriété May-alias-quoi que ce soit des types de vecteur Intel ne va à une seule manière, juste comment vous pouvez accéder à n'importe quoi avec
Char * code>, mais il n'est pas garanti d'accès à un
Char [] Code > avec un
int * code>. (C'est sûr dans MSVC, qui est comme
GCC -Fno-strict-aliasing code>, mais dans d'autres compilateurs, vous devez utiliser des syndicats ou la diffusion intrinsèque pour accéder aux éléments de vecteurs.) Voir Print une variable __m128i pour un exemple.