2

我有以下 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。

4

1 回答 1

4

不同之处在于内存访问。

当 时id = 1,以下数组加载成为单元素向量广播。

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

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

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

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

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

AVX2 将支持这种“聚集/分散”指令。


要解决编辑问题:

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

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

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

于 2012-10-30T10:16:36.203 回答