如何让Visual C ++矢量化这个循环(错误代码1200)?

时间:2013-04-18 20:59:16

标签: c++ vectorization simd

我正在尝试让VC ++ 2012自动矢量化一个看起来有点像这样的循环(实际上有一些有趣的计算正在进行中,但是为了尽可能地提出问题,它们被省略了)

parameters:
int period;
unsigned char* out_array;
unsigned char* in_array1;
unsigned char* in_array2;
unsigned char* in_array3;

for (int x = 0; x < width; ++x)
{
   int index = period * (x / 2);

   out_array[0] = in_array1[x];
   out_array[1] = in_array2[index];
   out_array[2] = in_array3[index];
   out_array += 4;
}

我认为阻碍矢量化的唯一因素是out_array += 4,所以我做了一个内部的“展开”循环,希望至少有一个可以被矢量化:

for (int x = 0; x < width; ++x)
{
   for (int xx = 0; xx < 4; ++xx)
   {
       int index = period * ((xx + x) / 2);

       unsigned char* pout_array = out_array + (4 * xx);
       pout_array[0] = in_array1[xx + x];
       pout_array[1] = in_array2[index];
       pout_array[2] = in_array3[index];
   }
   out_array += 16;
}

但是当我使用/Qvect-report:2运行编译器时,它告诉我内部循环因为错误代码1200而无法进行矢量化。错误代码1200指出:

  

循环包含阻止循环的数据依赖性   矢量。循环的不同迭代会干扰每个循环   其他这样,矢量化循环会产生错误的答案,并且   自动矢量化器无法证明自己没有这样的数据   依赖性。

我不明白这一点。显然,这个循环的每次迭代都是独立的。如何让Visual Studio对其进行矢量化?

1 个答案:

答案 0 :(得分:2)

它无法对其进行矢量化的主要原因是,如编写的那样,编译器无法消除out_array [n]不是in_arrayX [m]的可能性,因此必须坚持顺序排序。

您可以使用“__restrict”或“restrict”关键字为编译器解决此问题,该关键字是对编译器的承诺,您只能以确保out_array与其他三个指针中的任何一个不同的方式调用它。您可能还希望使用“const”修饰符来慷慨地协助编译器:

void func(const int period,
    unsigned char* __restrict out_array,
    const unsigned char* in_array1,
    const unsigned char* in_array2,
    const unsigned char* in_array3)
{
   ...
   //mark 'width' as 'const' if possible:
   const int width = ...;
   for (int x = 0; x < width; ++x)
   {
       const int index = period * (x / 2);

       out_array[(x* 4) + 0] = in_array1[x];
       out_array[(x* 4) + 1] = in_array2[index];
       out_array[(x* 4) + 2] = in_array3[index];
   }
}