2015-10-03 33 views
6

MSVC 2013 ultimo w/Update 4Risoluzione dei problemi ragione auto vectorize '1200'

Non capire perché sto ottenendo questo errore su questo apparentemente semplice esempio

informazioni C5002: ciclo non vettorializzare a causa di motivi '1200'

che è

1200 loop contiene dipendenze dati di loop-trasportato

non vedo come le iterazioni della l oop potrebbe interferire l'uno con l'altro.

__declspec(align(16)) class PhysicsSystem 
{ 
public: 
    static const int32_t MaxEntities = 65535; 

    __declspec(align(16)) struct VectorizedXYZ 
    { 
     double  mX[ MaxEntities ]; 
     double  mY[ MaxEntities ]; 
     double  mZ[ MaxEntities ]; 

     VectorizedXYZ() 
     { 
      memset(mX, 0, sizeof(mX)); 
      memset(mY, 0, sizeof(mY)); 
      memset(mZ, 0, sizeof(mZ)); 
     } 
    }; 

    void Update(double dt) 
    { 
     for (int32_t i = 0; i < MaxEntities; ++i) <== 1200 
     { 
      mTmp.mX[ i ] = mPos.mX[ i ] + mVel.mX[ i ] * dt; 
      mTmp.mY[ i ] = mPos.mY[ i ] + mVel.mY[ i ] * dt; 
      mTmp.mZ[ i ] = mPos.mZ[ i ] + mVel.mZ[ i ] * dt; 
     } 
    } 

private:  
    VectorizedXYZ mTmp; 
    VectorizedXYZ mPos; 
    VectorizedXYZ mVel; 
}; 

Edit: A giudicare dalla http://blogs.msdn.com/b/nativeconcurrency/archive/2012/05/08/auto-vectorizer-in-visual-studio-11-rules-for-loop-body.aspx questo sembrerebbe essere un esempio di "Esempio 1 - imbarazzante parallelo", ma si comporta come pensa gli array non sono sicure da aliasing, che è sconcertante per me.

Edit2: Sarebbe bello se qualcuno potesse condividere i motivi per cui la vettorializzazione automatica non riesce in un apparentemente semplice esempio così, ma dopo armeggiare con esso per un po ', ho optato invece di prendere le redini me

void PhysicsSystem::Update(Real dt) 
{ 
    const __m128d mdt = { dt, dt }; 

    // advance by 2 since we can do 2 at a time at double precision in __m128d 
    for (size_t i = 0; i < MaxEntities; i += 2) 
    { 
     __m128d posX = _mm_load_pd(&mPos.mX[ i ]); 
     __m128d posY = _mm_load_pd(&mPos.mY[ i ]); 
     __m128d posZ = _mm_load_pd(&mPos.mZ[ i ]); 

     __m128d velX = _mm_load_pd(&mVel.mX[ i ]); 
     __m128d velY = _mm_load_pd(&mVel.mY[ i ]); 
     __m128d velZ = _mm_load_pd(&mVel.mZ[ i ]); 

     __m128d velFrameX = _mm_mul_pd(velX, mdt); 
     __m128d velFrameY = _mm_mul_pd(velY, mdt); 
     __m128d velFrameZ = _mm_mul_pd(velZ, mdt); 

     _mm_store_pd(&mPos.mX[ i ], _mm_add_pd(posX, velFrameX)); 
     _mm_store_pd(&mPos.mY[ i ], _mm_add_pd(posX, velFrameY)); 
     _mm_store_pd(&mPos.mZ[ i ], _mm_add_pd(posX, velFrameZ)); 
    } 
} 
+0

Solo 2 osservazioni: 1/poiché il metodo di aggiornamento è in linea, quando ho provato a compilare questo, non è successo nulla che mi abbia perplesso per un po '; e 2/ora che l'ho annullato, la versione 15.0.3 del compilatore Intel si limita a vettorializzare senza alcun problema. – Gilles

+0

Grazie. E interessante. MSVC 2015 non gli piace né – jswigart

+0

Ti suggerirei sicuramente di esaminare la vettorizzazione portatile (nota anche con il comando #pragma omp simd di OpenMP 4.0). Supponendo che tu abbia un compilatore che lo supporta (icc 15+ fa, credo), allora entrambi renderanno la tua vita molto più semplice e ti daranno anche il controllo su ciò che è e non è vettorizzato. Al contrario di solo "dare suggerimenti" al compilatore su ciò che dovrebbe essere auto-vettorializzato. – NoseKnowsAll

risposta

0

Non sono sicuro se il compilatore lo supporta, ma per far rispettare un certo corretta vettorizzazione, è possibile farlo in modo portabile:

void PhysicsSystem::Update(double dt) { 
    double *tx=mTmp.mX, *ty=mTmp.mY, *tz=mTmp.mZ; 
    double *px=mPos.mX, *py=mPos.mY, *pz=mPos.mZ; 
    double *vx=mVel.mX, *vy=mVel.mY, *vz=mVel.mZ; 
    #pragma omp simd aligned(tx, ty, tz, px, py, pz, vx, vy, vz) 
    for (int i = 0; i < MaxEntities; ++i) { 
     tx[ i ] = px[ i ] + vx[ i ] * dt; 
     ty[ i ] = py[ i ] + vy[ i ] * dt; 
     tz[ i ] = pz[ i ] + vz[ i ] * dt; 
    } 
} 

è necessario quindi attivare il supporto OpenMP per la direttiva da prendere in considerazione.

+0

Che diamine. Se faccio tutto questo tranne la riga di pragma, allora funziona. – jswigart

+0

Mi aspettavo che funzionasse anche senza il pragma, ma non potevo controllare dato che non ho il tuo compilatore .... Il fatto è, immagino, che il compilatore ipotizzi qualche possibile aliasing degli array membri all'interno di 'VectorizedXYZ' strutture. Tornando ai semplici puntatori, si interrompono i collegamenti tra i membri ... – Gilles

+0

Probabilmente si utilizzano 3 loop separati senza il trucco del puntatore funzionerebbe pure – Gilles

Problemi correlati