2010-12-12 11 views
12

Il passaggio di tipi o strutture allineati con tipi allineati per valore non funziona con alcune implementazioni. Questo rompe i contenitori STL, perché alcuni dei metodi (come ridimensionare) prendono i loro argomenti in base al valore.Tipi allineati e argomenti di passaggio in base al valore

Eseguo alcuni test con Visual Studio 2008 e non del tutto sicuro di quando e in che modo il passaggio per valore non riesce. La mia preoccupazione principale è la funzione pippo. Sembra funzionare bene, ma potrebbe essere il risultato di un inlining o di qualche altra coincidenza? Cosa succede se cambio la sua firma in void foo (const __m128 &)?

Il tuo contributo è molto apprezzato. Grazie.

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); 
} 

MODIFICA. STL non riesce nemmeno con l'allocatore allineato, poiché il problema del valore passato rimane.

trovato questo link pass __m128 by value

+0

Quali sono gli errori/gli avvisi di compilazione che stai ottenendo? Presumo che qualcosa come "parametro formale ... non sia allineato"? – celion

+0

Questo è quello che ottengo. errore C2719: 'parametro senza nome': il parametro formale con __declspec (align ('16 ')) non sarà allineato – watson1180

+0

In x64, gli argomenti delle funzioni supportano l'allineamento di 16 byte, quindi questo problema scompare. So che non risolve il tuo problema immediato, ma hey, è marginalmente meglio di niente. ;) – jalf

risposta

2

Credo che l'unico modo sicuro per fare questo, in generale, è quello di passare per riferimento. Alcune piattaforme (ad esempio Xbox 360) supportano il passaggio degli argomenti vettoriali nei registri, ma non penso che sia possibile su x86.

Per il caso std::vector, è necessario assicurarsi che la memoria allocata sia allineata a 16 byte; altrimenti si verificheranno arresti anomali quando si tenta di eseguire la maggior parte delle operazioni su vettori non allineati.

Se stai supportando più piattaforme, un piano sicuro consiste nell'utilizzare un typedef ad es.

typedef const MyVector& MyVectorParameter; 

È quindi possibile modificare il typedef su piattaforme che supportano il pass-by-value del vettore.

+0

Sostituzione della guida di allocatore con std :: vector <__m128>, ma std :: vector non viene ancora compilato. – watson1180

+0

Hai controllato 'sizeof (A)'? Se non è un multiplo di 16 byte, gli elementi successivi della memoria di array allocata dal vettore non saranno allineati, anche se l'inizio della memoria è allineato. –

+0

Sulla mia piattaforma, la dimensione di A è di 32 byte.Un allineamento errato causerebbe un arresto anomalo del runtime, ma il vettore non verrà compilato indipendentemente dall'allocatore. – watson1180

1

la funzione di ridimensionamento() utilizzata spesso causa tutto l'allineamento e forse è possibile provare a specializzare il modello vettoriale per __m128?