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));
}
}
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
Dzięki. I interesujące. MSVC 2015 też tego nie lubi – jswigart
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