【问题标题】:Inner if statement kills vectorization内部 if 语句杀死向量化
【发布时间】:2012-10-30 10:02:04
【问题描述】:

我有以下 for 循环。当我打开类型数组时,代码不会矢量化。当我将类型固定为“1”时,gcc 会执行一个 primitize 矢量化矢量化。有没有人有任何建议来触发某种矢量化?

#define type(M,N) type[(M)*sizeX + (N)]
for (int i = 0; i < sizeY - 1; i++)
{
    for (int j = 0; j < sizeX - 1; j++)
    {
       const int id = type(i, j);
       //const int id = 1; //vectorizes
       const float A = this->A[id];
       const float B = this->B[id];
       a(i, j) = A * a(i, j) + B * (b(i, j) - b(i + 1, j))*(p[i]);
    }
 }

gcc 4.7.1 的近似误差

45: not vectorized: not suitable for gather A_26 = *D.14145_25;

编辑 1

所有数组都存储为指针,并使用 restrict 关键字定义为某个类的成员。

编辑 2

如果 'type' 很小,我能做些什么吗?

编辑 3

小意味着8。

【问题讨论】:

  • type 是在类中使用 restrict 关键字定义的整数数组(与所有数组一样)
  • 你像调用函数一样调用type()。你能给出那个函数的定义吗?
  • a()b() 怎么样?相同的宏?
  • 是的...重要的一点是,当类型条件负载矢量化消失。
  • @Mysticial:在他的代码的第一行。

标签: c++ gcc compiler-optimization vectorization


【解决方案1】:

区别在于内存访问。

id = 1时,后面的数组加载成为单元素向量广播。

 const float A = this->A[id];
 const float B = this->B[id];

但是当id = type[(i)*sizeX + (k)]时,内存访问是跨步的(不连续的)。

SSE 和 AVX 中的向量加载和存储只能在:

  1. 连续的内存块。
  2. 或者从单个元素广播到整个向量。

它们无法处理跨步内存访问,您从内存的不同部分加载每个向量元素。

AVX2 将支持此类“聚集/分散”指令。


解决编辑问题:

如果type(i, j) 中的i 不是零,则内存访问仍然是跨步的。所以很难矢量化。 (我说“困难”而不是“不可能”,因为编译时间确定的步幅非常小——尽管效率会降低。)

您在这里遇到的核心问题是您正在向下迭代矩阵的行。如果没有收集/分散支持,这不仅无法矢量化,而且对缓存也不利。

我不确定您要完成什么任务,但您可能需要考虑不同的数据布局以获得最佳性能。

【讨论】:

  • re:不同的数据布局 - 您可以使用大小为 (M*N) 的一维数组并使用 mod 和 div 操作对其进行操作,而不是 MxN“矩阵”,本质上是创建基础对于一个可以很好优化的 duff 设备
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-26
  • 2011-09-02
  • 1970-01-01
  • 2017-10-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多