我有相同循环的以下两个版本:
// version 1
for(int x = 0; x < size_x; ++x)
{
for(int y = 0; y < size_y; ++y)
{
data[y*size_x + x] = value;
}
}
// version 2
for(int y = 0; y < size_y; ++y)
{
for(int x = 0; x < size_x; ++x)
{
data[y*size_x + x] = value;
}
}
我使用两个编译器编译上述代码:
Intel(17.0.1):我使用以下代码编译代码:icc -qopenmp -O3 -qopt-report main.cpp
。两者都成功地进行了矢量化。
GCC(5.1):我使用:g++ -fopenmp -ftree-vectorize -fopt-info-vec -O3 main.cpp
编译代码。只有版本2被矢量化。
以下是我的问题:
Loopnest Interchanged: ( 1 2 ) --> ( 2 1 )
和PERMUTED LOOP WAS VECTORIZED
;在第二版中,我得到了这个:LOOP WAS VECTORIZED
。那么看起来英特尔编译器会重新排列循环的顺序以便对其进行矢量化?我明白这是对的吗? 编辑1:
感谢MarcGlisse,我通过创建代码的简化示例进一步调查,并意识到我的data
大小和GCC上的编译标志的不同组合将实现不同的矢量化。此时我更加困惑,我认为最好先创建一个新帖子,以便首先了解GCC向量化的工作原理。如果有人好奇,您可以查看下面的代码并尝试size_x
和size_y
的值1,2,3,4,5,6,7。还可以使用MarcGlisse的编译标志尝试一次,一次不使用。不同的组合可能会给出不同的矢量化结果。
void foo1(int size_x, int size_y, float value, float* data)
{
for(int x = 0; x < size_x; ++x)
{
for(int y = 0; y < size_y; ++y)
{
data[y*size_x + x] = value;
}
}
}
void foo2(int size_x, int size_y, float value, float* data)
{
for(int y = 0; y < size_y; ++y)
{
for(int x = 0; x < size_x; ++x)
{
data[y*size_x + x] = value;
}
}
}
int main(int argc, char** argv)
{
int size_x = 7;
int size_y = 7;
int size = size_x*size_y;
float* data1 = new float[size];
float* data2 = new float[size];
foo1(size_x, size_y, 1, data1);
foo2(size_x, size_y, 1, data2);
delete [] data1;
delete [] data2;
return 0;
}