2010-12-12 4 views
12

Le passage de types alignés ou de structures avec des types alignés par valeur ne fonctionne pas avec certaines implémentations. Cela casse les conteneurs STL, car certaines des méthodes (telles que resize) prennent leurs arguments en valeur.Types alignés et transmission d'arguments par valeur

Je fais des tests avec Visual Studio 2008 et je ne sais pas exactement quand et comment la valeur de transmission échoue. Ma principale préoccupation est la fonction foo. Cela semble fonctionner, mais pourrait-il être le résultat d'une inline ou d'une autre coïncidence? Que faire si je change sa signature à void foo (const __m128 &)?

Votre contribution est grandement appréciée. Je vous remercie.

struct A 
{ 
    __m128 x; 
    int n; 
}; 

void foo(__m128); 
void bar(A); 

void f1() 
{ 
    // won't compile 
    // std::vector<A> vec1(3); 

    // compiles, but fails at runtime when elements are accessed 
    std::vector<__m128> vec2(3); 

    // this seems to work. WHY??? 
    std::vector<__m128, some_16_byte_aligned_allocator<__m128> > vec3(3); 

    __m128 x; 
    A a; 

    // passed by value, is it OK? 
    foo(x); 

    // won't compile 
    //bar(a); 
} 

EDIT. STL échoue même avec l'allocateur aligné, parce que le problème de passer par la valeur reste.

trouvé ce lien pass __m128 by value

+0

Quelles sont les erreurs/avertissements de compilation que vous obtenez? Je suppose quelque chose comme "paramètre formel ... ne sera pas aligné"? – celion

+0

C'est ce que je reçois. erreur C2719: 'unnamed-parameter': paramètre formel avec __declspec (align ('16 ')) ne sera pas aligné – watson1180

+0

En x64, les arguments de fonction prennent en charge l'alignement de 16 octets, ce problème disparaît. Je sais que cela ne résout pas votre problème immédiat, mais bon, c'est marginalement mieux que rien. ;) – jalf

Répondre

2

Je pense que le seul moyen sûr de le faire en général est de passer par référence. Certaines plates-formes (par exemple Xbox 360) prennent en charge le passage d'arguments vectoriels dans des registres, mais je ne pense pas que cela soit possible sur x86.

Pour le cas std::vector, vous devez vous assurer que la mémoire allouée est alignée sur 16 octets; sinon, vous aurez des plantages lorsque vous essaierez d'effectuer la plupart des opérations sur des vecteurs non alignés.

Si vous prenez en charge plusieurs plates-formes, planifiez en toute sécurité d'utiliser un typedef par exemple.

typedef const MyVector& MyVectorParameter; 

Vous pouvez ensuite modifier le typedef sur les plates-formes prenant en charge la valeur de transfert de vecteur.

+0

Remplacement de l'aide de l'allocateur avec std :: vector <__m128>, mais std :: vector ne compile toujours pas. – watson1180

+0

Avez-vous vérifié 'sizeof (A)'? Si ce n'est pas un multiple de 16 octets, alors les éléments suivants du stockage de tableau alloué par le vecteur ne seront pas alignés, même si le début du stockage est aligné. –

+0

Sur ma plate-forme, la taille de A est de 32 octets.Un mauvais alignement provoquerait un crash de l'exécution, mais le vecteur ne compilera pas indépendamment de l'allocateur. – watson1180

1

la fonction souvent utilisée resize() provoque tout l'alignement et peut-être vous pouvez essayer de spécialiser le modèle vectoriel pour __m128?

Questions connexes