C++ 我是否必须对齐数据才能将此函数矢量化?

C++ 我是否必须对齐数据才能将此函数矢量化?,c++,parallel-processing,vectorization,simd,C++,Parallel Processing,Vectorization,Simd,我有此函数,Intel Advisor强烈建议将其矢量化: void SIFTDescriptor::samplePatch(float *vec) { for (int r = 0; r < par.patchSize; ++r) { const int br0 = par.spatialBins * bin0[r]; const float wr0 = w0[r]; const int br1 = par.spatialBins * bin1[r];

我有此函数,Intel Advisor强烈建议将其矢量化:

void SIFTDescriptor::samplePatch(float *vec)
{
   for (int r = 0; r < par.patchSize; ++r)
   {
      const int br0 = par.spatialBins * bin0[r]; const float wr0 = w0[r];
      const int br1 = par.spatialBins * bin1[r]; const float wr1 = w1[r];
      for (int c = 0; c < par.patchSize; ++c)
      {
         const float val = mask.at<float>(r,c) * grad.at<float>(r,c);

         const int bc0 = bin0[c];
         const float wc0 = w0[c]*val;
         const int bc1 = bin1[c];
         const float wc1 = w1[c]*val;

         // ori from atan2 is in range <-pi,pi> so add 2*pi to be surely above zero
         const float o = float(par.orientationBins)*(ori.at<float>(r,c) + 2*M_PI)/(2*M_PI);

         int   bo0 = (int)o;
         const float wo1 =  o - bo0;
         bo0 %= par.orientationBins;

         int   bo1 = (bo0+1) % par.orientationBins;
         const float wo0 = 1.0f - wo1;

         // add to corresponding 8 vec...
         if (wr0*wc0>0) {
             vec[br0+bc0+bo0] += wr0*wc0 * wo0;
             vec[br0+bc0+bo1] += wr0*wc0 * wo1;
         }
         if (wr0*wc1>0) {
             vec[br0+bc1+bo0] += wr0*wc1 * wo0;
             vec[br0+bc1+bo1] += wr0*wc1 * wo1;
         }
         if (wr1*wc0>0) {
             vec[br1+bc0+bo0] += wr1*wc0 * wo0;
             vec[br1+bc0+bo1] += wr1*wc0 * wo1;
         }
         if (wr1*wc0>0) {
             vec[br1+bc1+bo0] += wr1*wc0 * wo0;
             vec[br1+bc1+bo1] += wr1*wc0 * wo1;
         }
      }
   }
}
但是,“英特尔顾问”告诉我,中有两种先读后写的依赖项:

 vec[br0+bc0+bo0] += wr0*wc0 * wo0;
以及:

现在,我是simd的初学者,根据我的理解,我必须编写SSE/AVX2/AVX-512指令来解决这个依赖关系。例如,我发现了一个问题,在哪里解释了如何在数组单元格中保存累积和。这有点不同,因为我想将累积结果的结果保存在数组的元素中(
vec[something]
,而不是像
result
这样的标量变量)

然而,在第二个问题的答案中,解释了为了使用代码,我们需要对齐的数据。由于
vec
是指向
cv::Mat
对象的指针,因此我并不认为数据是对齐的

在回答这个问题时,有人争辩说,是否需要对齐的数据来解决我的问题。换句话说,我担心我陷入了XY问题,我正集中精力在(可能)实际不需要的地方对齐数据(特别是因为我是simd初学者,我害怕过度思考)


注意:我使用的是一台与AVX2兼容的机器,我计划随后转移到一台AVX-512机器。

看起来您对内部c-loop有一个非常严格的交叉迭代依赖关系。这是一个基本的算法特征(特别是因为bo0是c的一个变量和不可预测的函数),因此对齐数据无助于解决基本问题。纯形式的简单simd简化也不起作用。作为第一个简单的尝试,我可能会做的是在外部r环上做矢量化。尝试将#pragma simd放在第一个for循环语句(r-loop)之前。正式地说,在这样做之前,您需要检查r-loop(而不是c-loop)的Advisor依赖关系。我知道向量大小是128。那么,如果我创建8个不同的向量(每个累加向量+=)并在最后求和,会怎么样?这将解决依赖关系,对吗?请注意,两个for循环的范围都是41(所以1681次迭代),看起来内部c循环的交叉迭代依赖性非常强。这是一个基本的算法特征(特别是因为bo0是c的一个变量和不可预测的函数),因此对齐数据无助于解决基本问题。纯形式的简单simd简化也不起作用。作为第一个简单的尝试,我可能会做的是在外部r环上做矢量化。尝试将#pragma simd放在第一个for循环语句(r-loop)之前。正式地说,在这样做之前,您需要检查r-loop(而不是c-loop)的Advisor依赖关系。我知道向量大小是128。那么,如果我创建8个不同的向量(每个累加向量+=)并在最后求和,会怎么样?这将解决依赖关系,对吗?请注意,两个for循环的范围都是41(所以1681次迭代)
 vec[br0+bc0+bo0] += wr0*wc0 * wo0;
 vec[br1+bc0+bo0] += wr1*wc0 * wo0;