有没有人看到下面的循环代码有什么明显的东西,我没有看到为什么 VS2012 的 C++ 编译器不能自动矢量化它?
编译器给我的只是info C5002: loop not vectorized due to reason '1200'
当我使用/Qvec-report:2
命令行开关时。
原因 1200 在 MSDN 中记录为:
循环包含阻止矢量化的循环携带的数据依赖性。循环的不同迭代相互干扰,因此对循环进行矢量化会产生错误的答案,并且自动矢量化器无法向自己证明不存在这种数据依赖性。
我知道(或者我很确定)没有任何循环携带的数据依赖关系,但我不确定是什么阻止了编译器实现这一点。
这些source
和dest
指针永远不会重叠或别名相同的内存,我试图通过__restrict
.
pitch
总是一个正整数值,类似于4096
,取决于屏幕分辨率,因为这是一个 8bpp->32bpp 渲染/转换函数,逐列操作。
byte * __restrict source;
DWORD * __restrict dest;
int pitch;
for (int i = 0; i < count; ++i) {
dest[(i*2*pitch)+0] = (source[(i*8)+0]);
dest[(i*2*pitch)+1] = (source[(i*8)+1]);
dest[(i*2*pitch)+2] = (source[(i*8)+2]);
dest[(i*2*pitch)+3] = (source[(i*8)+3]);
dest[((i*2+1)*pitch)+0] = (source[(i*8)+4]);
dest[((i*2+1)*pitch)+1] = (source[(i*8)+5]);
dest[((i*2+1)*pitch)+2] = (source[(i*8)+6]);
dest[((i*2+1)*pitch)+3] = (source[(i*8)+7]);
}
每个周围的括号source[]
都是函数调用的残余,我在这里省略了,因为没有函数调用,循环仍然不会以最简单的形式自动矢量化。
编辑:
我已将循环简化为最简单的形式:
for (int i = 0; i < 200; ++i) {
dest[(i*2*4096)+0] = (source[(i*8)+0]);
}
这仍然会产生相同的 1200 原因代码。
编辑(2):
这个具有本地分配和相同指针类型的最小测试用例仍然无法自动矢量化。我只是在这一点上感到困惑。
const byte * __restrict source;
byte * __restrict dest;
source = (const byte * __restrict ) new byte[1600];
dest = (byte * __restrict ) new byte[1600];
for (int i = 0; i < 200; ++i) {
dest[(i*2*4096)+0] = (source[(i*8)+0]);
}