Quantcast
Channel: Intel® C++ Compiler
Viewing all articles
Browse latest Browse all 1616

常见的向量化技巧

$
0
0

面向英特尔® MIC 架构的编译器方法

本文收集了关于向量化的各种技巧

 

在向量循环中处理用户定义的函数调用

如果您希望对具有用户定义的函数调用的循环进行向量化处理,(可能要重建代码请将函数调用作为向量基本函数。

在基本函数中指定单位步长访问

如果您的基本函数访问单位步长中的内存您可以通过两种方式来编写

·         线性整数对统一指针进行索引

·         线性指针

__declspec(vector(uniform(a),linear(i:1)))

float foo(float *a, int i){

  return a[i]++;

}

 

__declspec(vector(linear(a:1)))

float foo1(float *a){

  return (*a)++;

}

处理向量循环内部的内存消歧

 

针对简单的循环考虑向量化

void vectorize(float *a, float *b, float *c, float *d, int n) {
    int i;
    for (i=0; i<n; i++) {
        a[i] = c[i] * d[i];
        b[i] = a[i] + c[i] - d[i];
    }

·         此处编译器不知道这 4 个指针指向何处。作为一名编程人员,你可能知道它们指向完全独立的位置。编译器不会这么认为。除非编程人员明确地告诉编译器它们指向独立的位置,否则编译器必须假定它们彼此使用 VERY BADLY 别名 --- 例如,c[1] a[0] 可能位于相同的地址,因此根本不能对循环进行向量化处理。

·         当未知指针的数量非常少时编译器可以生成一个运行时检查以及循环的优化和非优化版本编译时间、代码大小以及运行时测试中存在开销。由于开销会快速增长,因此"VERY SMALL"数值必须非常小 ---- 例如 2 --- 即便如此,由于没有告诉编译器“指针是独立的”,您仍会受到一定的影响。

·         因此更好的方法是告诉编译器指针是独立的。其中一个方法是使用 C99 "restrict pointer"关键字。即便你没有使用"C99 标准"进行编译,您可以使用 -restrict (Linux) -Qrestrict (Windows) 标记,以便使英特尔编译器接受"restrict"关键字。

void vectorize(float *restrict a, float *restrict b, float *c, float *d, int n) {
    int i;
    for (i=0; i<n; i++) {
        a[i] = c[i] * d[i];
        b[i] = a[i] + c[i] - d[i];
    }
}

·         此处编程人员应告诉编译器"a""b"没有其它别名。

·         另外一种方法是使用IVDEP 编译指示。IVDEP 的语义与限制指针不同但是它可以使编译器消除某些假定的依赖性这足以使编译器认为向量化是安全的。

void vectorize(float *a, float *b, float *c, float *d, int n) {
    int i;
#pragma ivdep
    for (i=0; i<n; i++) {
        a[i] = c[i] * d[i];
        b[i] = a[i] + c[i] - d[i];
    }
}

避免 64 位整数与浮点之间的转换

·         避免 64 位整数与浮点之间的转换。

·         请使用 32 位整数。

·         如果可能请使用 32 位的带符号整数最高效

避免 64 位整数对收集/分散进行索引

·         64 位索引收集/分散没有高效的硬件支持

带有间接访问的循环的向量化

考虑带有间接内存加载/存储的循环的向量化如下所示

 for (i = kstart; i < kend; ++i) {

    istart = iend;

    iend   = mp_dofStart[i+1];

    float w = xd[i];

 

    for (j = istart; j < iend; ++j) {

        index  = SCS[j];

        xd[index] -= lower[j]*w;

    }

 }

对于上面所示的代码来说向量化的关键条件是xd 值是不同的否则便会存在真正的依赖性从而不能对循环进行向量化处理。如果是这种情况,唯一的方法便是以向量友好型的方式重新编写算法)。如果 xd 值保证(由用户)是不同的,那么便可以使用 ivdep/simd 编译指示(在内部 j-loop 之前)执行向量化操作。编译器仍将生成收集/分散向量化 如果存在可以使用其单位步长的算法列示,则会达到更好的效果。

 

  • Desarrolladores
  • Linux*
  • C/C++
  • Fortran
  • Avanzado
  • Intel® C++ Compiler
  • Intel® Fortran Compiler
  • Arquitectura Intel® para muchos núcleos integrados
  • Optimización
  • Computación en paralelo
  • Vectorización
  • Dirección URL

  • Viewing all articles
    Browse latest Browse all 1616

    Trending Articles