2015-10-03 22 views
6

MSVC 2013 Ostateczny w/Aktualizacja 4problemów auto vectorize powodem „1200”

Nie rozumiejąc dlaczego ja dostaję ten błąd na tej pozornie prostym przykładzie

informacji C5002: pętla nie wektorowy powodu rozumu „1200”

który jest

1200 Loop zawiera pętla przenoszony Zależności danych

nie widzę, w jaki sposób iteracji L oop może interferować ze sobą.

__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: Sądząc http://blogs.msdn.com/b/nativeconcurrency/archive/2012/05/08/auto-vectorizer-in-visual-studio-11-rules-for-loop-body.aspx ten wydaje się być przykładem „Przykład 1 - żenująco równoległych”, ale działa jak ona myśli, że tablice są niebezpieczne z aliasingu, który jest dla mnie zaskakujący.

Edit2: Byłoby miło, gdyby ktoś mógłby podzielić się powody, dla których auto wektoryzacja nie działa na takiej pozornie prosty przykład, ale po majstrować przy nim przez pewien czas, zdecydowałem zamiast wziąć panowania sobie

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

Tylko 2 uwagi: 1/ponieważ metoda aktualizacji jest wbudowana, kiedy próbowałem ją skompilować, nic się nie działo, co mnie zastanawiało przez jakiś czas; i 2/teraz, gdy to odkreśliłem, wersja kompilatora Intel 15.0.3 po prostu wektoryzuje się bez żadnego problemu. – Gilles

+0

Dzięki. I interesujące. MSVC 2015 też tego nie lubi – jswigart

+0

Z pewnością sugerowałbym, żebyś szukał przenośnej wektoryzacji (również za pomocą '#pragma omp simd') OpenMP 4.0. Zakładając, że dysponujesz kompilatorem, który go obsługuje (icc 15+, wierzę), wtedy zarówno ułatwi ci to życie, jak i zapewni ci kontrolę nad tym, co jest i nie jest wektoryzowane. W przeciwieństwie do "sugerowania" kompilatorowi, co powinno być automatycznie wektoryzowane. – NoseKnowsAll

Odpowiedz

0

Nie jestem pewien, czy kompilator wspiera, ale trochę za egzekwowanie prawidłowego wektoryzacji można przenośnie zrobić:

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

trzeba następnie włączyć wsparcie dla OpenMP dyrektywy mają być brane pod uwagę.

+0

Co do cholery. Jeśli robię to wszystko poza linią pragma, to działa. – jswigart

+0

Spodziewałem się, że działa nawet bez pragmy, ale nie mógł sprawdzić, ponieważ nie mam twojego kompilatora ... Chodzi o to, myślę, że kompilator zakłada pewne możliwe aliasingowanie tablic członkowskich wewnątrz 'VectorizedXYZ' Struktury. Wracając do prostych wskazówek, przerywamy połączenia między członkami ... – Gilles

+0

Prawdopodobnie używając 3 oddzielnych pętli bez sztuczki wskaźnikowej też by działało. – Gilles

Powiązane problemy