1

我试图找到合适的材料,清楚地解释编写 C/C++ 源代码的不同方法,这些源代码可以由英特尔编译器使用数组表示法和基本函数进行矢量化。网上的所有资料都举了一些简单的例子:saxpy、reduction 等。但是缺乏关于如何向量化具有条件分支或包含具有循环依赖的循环的代码的解释。

例如:假设我想使用不同的数组运行顺序代码。矩阵以主要行格式存储。矩阵的列由 compute_seq() 函数计算:

#define N      256
#define STRIDE 256

__attribute__((vector))    
inline void compute_seq(float *sum, float* a) {
  int i;
  *sum = 0.0f;
  for(i=0; i<N; i++) 
    *sum += a[i*STRIDE];
}

int main() {
  // Initialize
  float *A = malloc(N*N*sizeof(float));
  float sums[N];
  // The following line is not going to be valid, but I would like to do somthing like this:
  compute_seq(sums[:],*(A[0:N:1]));
}

任何意见表示赞赏。

4

1 回答 1

1

这是该示例的更正版本。

__attribute__((vector(linear(sum),linear(a))))
inline void compute_seq(float *sum, float* a) {
  int i;
  *sum = 0.0f;
  for(i=0; i<N; i++)
    *sum += a[i*STRIDE];
}

int main() {
  // Initialize
  float *A = malloc(N*N*sizeof(float));
  float sums[N];
  compute_seq(&sums[:],&A[0:N:N]);
}

重要的变化是在呼叫现场。表达式 &sums[:] 创建了一个由 &sums[0], &sums[1], &sums[2], ... &sums[N-1] 组成的数组部分。表达式 &A[0:N:N] 创建一个由 &A[0*N], &A[1*N], &A[2*N], ...&A[(N-1)*N] 组成的数组部分.

我在向量属性中添加了两个线性子句,以告诉编译器生成一个针对参数是算术序列的情况进行优化的克隆,就像在这个例子中一样。对于这个例子,它们(和向量属性)是多余的,因为编译器可以在同一个翻译单元中看到被调用者和调用站点,并为自己找出细节。但如果在另一个翻译单元中定义了 compute_seq,则该属性可能会有所帮助。

数组表示法是一项正在进行的工作。icc 14.0 beta 毫无怨言地为 Intel(R) Xeon Phi(TM) 编译了我的示例。icc 13.0 update 3 报告它无法向量化函数(“取消引用太复杂”)。反常地,关闭矢量属性会关闭报告,可能是因为编译器可以在内联后对其进行矢量化。

在为 Intel(R) Xeon Phi(TM) 编译时,我使用编译器选项“-opt-assume-safe-padding”。它可以提高矢量代码质量。它让编译器假设超出任何访问地址的页面是可以安全触摸的,从而启用某些否则会被禁止的指令序列。

于 2013-08-12T17:17:29.773 回答