2014-10-24 14 views
5

Sto cercando di compilare un codice SIMD che funzioni su MSVC con Clang su Xcode 6. Sfortunatamente ricevo un errore in cui gli operatori di accesso agli array sono stati sovraccaricati in una classe vettoriale personalizzata che non riesco a risolvere. Il modello vettoriale ha specializzazioni per array di lunghezza 4 e 8 che usano intrinseche SIMD, ma l'operatore di accesso all'array per restituire un riferimento a un elemento del vettore (per l'aggiornamento di quell'elemento) mi dà un errore su clang "il riferimento non const non può associare all'elemento vettoriale ".Come accedere agli elementi vettoriali SIMD quando si sovraccaricano gli operatori di accesso agli array?

Full source code

Gli operatori di overload:

#ifdef _MSC_VER 
    float operator[](int idx) const { return v.m256_f32[idx]; } // m256_f32 MSVC only 
    float& operator[](int idx) { return v.m256_f32[idx]; } 
#else 
    float operator[](int idx) const { return v[idx]; } 
    float& operator[](int idx) { return v[idx]; } 
#endif 

L'errore da Clang:

non-const reference cannot bind to vector element 
    float& operator[](int idx) { return v[idx]; } 
             ^~~~~~ 

risposta

5

Penso che avrete probabilmente bisogno di usare un sindacato per questo, es .:

union U { 
    __m256 v; 
    float a[8]; 
}; 

e l'operatore valore sarebbe allora:

float operator[](int idx) const { U u = { v }; return u.a[idx]; } 

L'operatore di riferimento è più complicato però, e l'unico modo che posso vedere per farlo è tramite tipo gioco di parole, quindi con le solite precauzioni:

float& operator[](int idx) { return ((float *)&v)[idx]; } 

Non sono nemmeno sicuro che questo verrà compilato, e potrebbe essere necessario -fno-strict-aliasing.

Per evitare questa cattiveria, si suppone di poter modificare la variabile membro da __m256 v; a U u;.

Spero solo che non stiate facendo questo genere di cose all'interno di qualsiasi loop critico per le prestazioni.

+0

L'intero motivo dell'utilizzo di simd è la prestazione, quindi non si vuole fare nulla che possa rallentarlo drasticamente! – olilarkin

+0

@olilarkin: certo - ma se si accede a singoli elementi di un vettore all'interno di un ciclo critico delle prestazioni, si sta facendo del tutto sbagliato SIMD, in genere questo tipo di operazione dovrebbe avvenire solo dopo un ciclo, dove non è prestazioni- critica. –

+0

scusa ti ho frainteso ... gli elementi non sono accessibili individualmente nella parte relativa alle prestazioni, solo nell'inizializzazione – olilarkin

2

Questo funziona solo per la lettura, quindi non sarà possibile restituire un riferimento a float. Ma questo dovrebbe funziona con valori di runtime:

  • > = SSE4.1 +: usare intrinseche PEXTRD come _mm_extract_ps
  • prima SSE4.1: _mm_cvtsi128_si32 + _mm_srli_si128 di accedere a qualsiasi oggetto a 32 bit (quindi caso con un sindacato