2015-10-03 8 views
6

MSVC 2013 Ultimative w/Update 4Fehlerbehebung Auto vectorize Grund ‚1200‘

nicht verstehen, warum ich auf diesem scheinbar einfachen Beispiel diesen Fehler bin immer

Info C5002: Schleife nicht auf Grund ‚1200‘ vektorisiert durch

welches

1200 Schleife enthält schlaufen getragenen Daten abhängigkeit

sehe ich nicht, wie die Iterationen der l oop könnte sich gegenseitig stören.

__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: Gemessen an http://blogs.msdn.com/b/nativeconcurrency/archive/2012/05/08/auto-vectorizer-in-visual-studio-11-rules-for-loop-body.aspx Dies scheint ein Beispiel für „Beispiel 1 - Peinlich Parallel“ zu sein, aber es wirkt wie es die Arrays sind unsicher von Aliasing denkt, die mir rätselhaft.

Edit2: Es wäre schön, wenn jemand die Gründe teilen könnte, warum die automatische Vektorisierung auf eine solche scheinbar einfachen Beispiel ausfällt, aber mit ihm für einige Zeit nach bastelt, ich stattdessen entschied mich die Zügel zu nehmen

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

Nur 2 Anmerkungen: 1/Da die Update-Methode inline ist, als ich versuchte, dies zu kompilieren, passierte nichts, was mich eine Weile verwirrte; und 2/jetzt, dass ich es nicht-inlined, Intel-Compiler-Version 15.0.3 einfach nur ohne Probleme vektorisiert. – Gilles

+0

Danke. Und interessant. MSVC 2015 mag es auch nicht – jswigart

+0

Ich würde sicherlich vorschlagen, dass Sie in portable Vektorisierung suchen (aka mit OpenMP 4.0-'#pragma omp simd'). Angenommen, Sie haben einen Compiler, der dies unterstützt (icc 15+, glaube ich), dann wird es Ihnen sowohl das Leben erleichtern als auch Ihnen die Kontrolle darüber geben, was vektorisiert ist und was nicht. Im Gegensatz dazu, dem Compiler nur Vorschläge zu machen, was automatisch vektorisiert werden sollte. – NoseKnowsAll

Antwort

0

nicht sicher, ob Ihr Compiler unterstützt, aber einige richtige Vektorisierung für die Durchsetzung, können Sie portably das tun:

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

Sie müssen dann die OpenMP-Unterstützung für die Richtlinie berücksichtigt werden, ermöglichen.

+0

Was zum Teufel. Wenn ich das alles außer der Pragma-Linie mache, funktioniert es. – jswigart

+0

Ich habe erwartet, dass es auch ohne das Pragma funktioniert, aber konnte nicht überprüfen, da ich Ihren Compiler nicht habe .... Die Sache ist, ich nehme an, dass der Compiler ein mögliches Aliasing von Member-Arrays innerhalb der 'VectorizedXYZ' annimmt Strukturen. Durch Zurückgehen zu einfachen Zeigern, brechen Sie die Verbindungen zwischen den Mitgliedern ... – Gilles

+0

Wahrscheinlich würde das Verwenden von 3 separaten Schleifen ohne den Zeiger Trick auch funktionieren – Gilles