【问题标题】:How to optimize the computation of a for loop using SIMD?如何使用 SIMD 优化 for 循环的计算?
【发布时间】:2019-09-27 06:25:02
【问题描述】:

我正在尝试使用 Neon SIMD 在 ODROID XU4 ARM 平台上加速立体匹配算法。为此,我正在使用 openMp 语用。

 void StereoMatch:: sadCol(uint8_t* leftRank,uint8_t* rightRank,const int SAD_WIDTH,const int SAD_WIDTH_STEP, const int imgWidth,int j, int d , uint16_t* cost) 
  {

   uint16_t sum = 0;
   int n = 0;
   int m =0;
      for ( n = 0; n < SAD_WIDTH+1; n++)
      {

     #pragma omp simd
     for(  m = 0; m< SAD_WIDTH_STEP; m = m + imgWidth ) 
         {


        sum += abs(leftRank[j+m+n]-rightRank[j+m+n-d]);

         };
         cost[n] = sum;
         sum = 0;



  };

我对 SIMD 和 openMp 还很陌生,我知道在代码中使用 SIMD pragma 会指示编译器对减法进行矢量化处理,但是当我执行代码时,我发现没有区别。我应该在我的代码中添加什么以对其进行矢量化?

【问题讨论】:

  • 你用什么标志编译?试试-O3 -fopenmp-simd -march=native -mfpu=neon
  • 在您的特定情况下,您还需要将reduction(+:sum)simd pragma 一起使用。
  • 我没有使用 Neon 的实际经验,但 SIMD 通常不适用于跨步内存访问。我会切换循环的顺序,即在内循环中累积到多个cost[n]SAD_WIDTHSAD_WIDTH_STEPimgWidth 的典型值是什么?
  • 这是 Godbolt 上的清理版本:godbolt.org/z/SPQ5_t。您可能需要使用内在函数手动优化它,但您可以尝试使用内部循环的指针; -d 绝对是搞砸事情的好人选。
  • @TakiEddine 我不认为您所经历的加速要归功于 SIMD,而是 OpenMP 完成了通过多个内核分配工作负载的工作。如果编写得当,即使在单核上,它也会比原来的快几十倍。我不会使用多核来完成这样一项带宽有限的琐碎工作。

标签: arm openmp simd neon odroid


【解决方案1】:

正如 cmets 中所说,ARM-Neon 有一条指令可以直接执行您想要的操作,即计算无符号字节的绝对差并将其累加为无符号短整数。

假设SAD_WIDTH+1==8,这是一个非常简单的使用内在函数的实现(基于@nemequ 的简化版本):

void sadCol(uint8_t* leftRank,
            uint8_t* rightRank,
            int j,
            int d ,
            uint16_t* cost) {
    const int SAD_WIDTH = 7;
    const int imgWidth = 320;
    const int SAD_WIDTH_STEP = SAD_WIDTH * imgWidth;

    uint16x8_t cost_8 = {0};
    for(int m = 0; m < SAD_WIDTH_STEP; m = m + imgWidth )  {
        cost_8 = vabal_u8(cost_8, vld1_u8(&leftRank[j+m]), vld1_u8(&rightRank[j+m-d]));
    };
    vst1q_u16(cost, cost_8);
};

vld1_u8 加载 8 个连续字节,vabal_u8 计算绝对差并将其累加到第一个寄存器。最后,vst1q_u16 将寄存器存储到内存中。

您可以轻松制作imgWidthSAD_WIDTH_STEP 函数参数。如果SAD_WIDTH+1 是 8 的不同倍数,您可以为此编写另一个循环。

我手头没有 ARM 平台来测试它,但“它可以编译”:https://godbolt.org/z/vPqiYI(在我看来,程序集看起来不错)。如果您使用-O3 进行优化,gcc 将展开循环。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-02
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    • 2015-09-07
    • 2011-06-15
    • 1970-01-01
    相关资源
    最近更新 更多