2015-10-03 23 views
6

MSVC 2013更新4/W究極トラブルシューティング自動ベクトル化の理由「1200」

私はこの一見単純な例で

情報C5002このエラーを取得していますなぜ理解していない:ループの理由によりベクトル化されません「1200」

1200ループが含まれているループ運搬のデータ依存

私は見ていないです

どのようリットルの繰り返しお互いに干渉する可能性があります。

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

編集:http://blogs.msdn.com/b/nativeconcurrency/archive/2012/05/08/auto-vectorizer-in-visual-studio-11-rules-for-loop-body.aspxこれによって判断は「例1 - あきれるほどパラレル」の例のように見えるだろうが、それは配列が私に不可解さエイリアシング、より安全でないと考えるようにそれが動作します。

EDIT2:誰かが自動ベクトル化は、このような一見単​​純な例では失敗した理由を共有することができれば、それはいいだろうが、いくつかの時間のためにそれをいじった後、私は治世を自分で取る代わりに

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

ちょうど2つの発言:1 /私はこれをコンパイルしようとしたときに、更新メソッドがインラインであるので、私はしばらくの間困惑して何も起こっていませんでした。 2 /私はインライン展開していないので、インテルコンパイラのバージョン15.0.3は問題なくベクトル化されます。 – Gilles

+0

ありがとうございます。そして面白い。 MSVC 2015はそれを好きではありません – jswigart

+0

私は確かにポータブルベクトル化(OpenMP 4.0の '#pragma omp simd'を使って)を見てみることをお勧めします。あなたがそれをサポートするコンパイラを持っていると仮定すると(icc 15+はそう信じます)、それはあなたの人生をもっと簡単にし、ベクトル化されているものとされていないものを制御します。単に自動ベクトル化されるべきものについてコンパイラに「提案する」こととは対照的です。 – NoseKnowsAll

答えて

0

ないコンパイラがそれをサポートしていますが、いくつかの適切なベクトル化を強制するために、あなたは移植性のことを行うことができるかどうかを確認します。

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

あなたが考慮に入れるべきディレクティブのOpenMPサポートを有効にする、その後必要があります。

+0

何が一体。もし私がプラグマライン以外のすべてをしたら、それは動作します。 – jswigart

+0

私はプラグマがなくても動作することを期待していましたが、コンパイラを持っていないのでチェックできませんでした....コンパイラが 'VectorizedXYZ'内部のメンバ配列のエイリアシングを想定しています構造。単純なポインタに戻って、メンバー間のリンクを壊す... – Gilles

+0

おそらくポインタトリックなしで3つの別々のループを使用すると – Gilles

関連する問題