排除故障自动矢量化原因'1200'

jsw*_*art 6 c++ sse vectorization visual-studio

更新4的MSVC 2013 Ultimate

不明白为什么我在这个看似简单的例子中得到这个错误

info 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;
};
Run Code Online (Sandbox Code Playgroud)

编辑:通过http://blogs.msdn.com/b/nativeconcurrency/archive/2012/05/08/auto-vectorizer-in-visual-studio-11-rules-for-loop-body.aspx判断这看起来似乎作为"示例1 - 令人尴尬的并行"的一个例子,但它的行为就像它认为数组是不安全的别名,这让我感到困惑.

编辑2:如果有人可以在这样一个看似简单的例子中分享自动矢量化失败的原因,那会很好,但是在修补它一段时间后,我选择自己采取统治

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 ) );
    }
}
Run Code Online (Sandbox Code Playgroud)

Gil*_*les 1

不确定您的编译器是否支持它,但为了强制执行一些适当的矢量化,您可以便携式地执行此操作:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您需要启用 OpenMP 支持才能考虑该指令。