简介

此文简单介绍如何使用intel c++编译器实现向量化加速。

全文如下安排:

  • base : 待优化的源代码。
  • vectorization : 第一个向量化版本。
  • aligned : 内存对其对向量化的影响。

base

base版本代码:

// filename : main.cpp
#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <cstdint>
#include <malloc.h>
#include <windows.h>
using namespace std;

int64_t cpu_freq;
int64_t cpu_counter(){
  int64_t clock;
    QueryPerformanceCounter((LARGE_INTEGER*)&clock);
  return clock;
}

// output time
#if 1
  int64_t gloabel_timer_begin;
  int64_t gloabel_timer_end;
  #define TB__ gloabel_timer_begin=cpu_counter()
  #define TE__ gloabel_timer_end  =cpu_counter(); \
  cout << __LINE__ << " : " << double(gloabel_timer_end-gloabel_timer_begin)/double(cpu_freq) << " seconds" << endl
#else
  #define TB__
  #define TE__
#endif

// repeat times
#define REPEATTIMES 100000

// initialize data
void init(float *data, int rows, int cols, int true_cols){
  for (int i = 0; i < rows; i++){
    for (int j = 0; j < cols; j++){
      data[i*true_cols+j] = float(rand())/float(RAND_MAX);
    }
  }
}

void multiply(float *C, float *A, float *B, int rows, int cols, int true_cols);

void print_sum(float *data, int rows, int cols, int true_cols){
  float total = 0;
  for (int i = 0; i < rows; i++){
    for (int j = 0; j < cols; j++){
      total += data[i*true_cols+j];
    }
  }
  cout << total << endl;
}

int main(){
  QueryPerformanceFrequency((LARGE_INTEGER *)&cpu_freq);

  int rows = 100;
  int cols = 101;

  int true_cols = cols;
  float *A = (float*)malloc(rows*true_cols*sizeof(float));
  float *B = (float*)malloc(rows*sizeof(float));
  float *C = (float*)malloc(rows*sizeof(float));

  init(A, rows, cols, true_cols);
  init(B, rows, 1, 1);

  // computing
  TB__;
  for (int k = 0; k < REPEATTIMES; k++){
    multiply(C, A, B, rows, cols, true_cols);
  }
  TE__;

  // print result.
  print_sum(C, rows, 1, 1);

  free(A); A = NULL;
  free(B); B = NULL;
  free(C); C = NULL;

  return 0;
}
// filename : multiply.cpp
void multiply(float *C, float *A, float *B, int rows, int cols, int true_cols){
  for (int i = 0; i < rows; i++){
    C[i] = 0;
    for (int j = 0; j < cols; j++){
      C[i] += A[i*true_cols+j]*B[j];
    }
  }
}

编译:

user@machine> icl /O1 /Qopt-report:1 /Qopt-report-phase:vec main.cpp multiply.cpp

执行:

user@machine> main.exe
73 : 0.877882 seconds
2483.53

vectorization

源代码保持不变

编译:

user@machine> icl /O2 /Qopt-report:1 /Qopt-report-phase:vec main.cpp multiply.cpp

执行:

user@machine> main.exe
73 : 0.205989 seconds
2483.53

执行速度提升了 4倍左右。


aligned

源代码修改。(注意:下面的代码有问题,结果可能有错误,原因可能是内存的问题。

// filename : main.cpp
#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <cstdint>
#include <malloc.h>
#include <windows.h>
using namespace std;

int64_t cpu_freq;
int64_t cpu_counter(){
  int64_t clock;
    QueryPerformanceCounter((LARGE_INTEGER*)&clock);
  return clock;
}

// output time
#if 1
  int64_t gloabel_timer_begin;
  int64_t gloabel_timer_end;
  #define TB__ gloabel_timer_begin=cpu_counter()
  #define TE__ gloabel_timer_end  =cpu_counter(); \
  cout << __LINE__ << " : " << double(gloabel_timer_end-gloabel_timer_begin)/double(cpu_freq) << " seconds" << endl
#else
  #define TB__
  #define TE__
#endif

// repeat times
#define REPEATTIMES 100000

// initialize data
void init(float *data, int rows, int cols, int true_cols){
  for (int i = 0; i < rows; i++){
    for (int j = 0; j < cols; j++){
      data[i*true_cols+j] = float(rand())/float(RAND_MAX);
    }
  }
}

void multiply(float *C, float *A, float *B, int rows, int cols, int true_cols);

void print_sum(float *data, int rows, int cols, int true_cols){
  float total = 0;
  for (int i = 0; i < rows; i++){
    for (int j = 0; j < cols; j++){
      total += data[i*true_cols+j];
    }
  }
  cout << total << endl;
}

int main(){
  QueryPerformanceFrequency((LARGE_INTEGER *)&cpu_freq);

  int rows = 100;
  int cols = 101;

#ifdef ALIGNED
  #define ALLIGNED_LEN 32
  int true_cols = ((((cols*sizeof(float))+ALLIGNED_LEN-1)/ALLIGNED_LEN)*ALLIGNED_LEN)/sizeof(float);
  //cout << true_cols << endl;
  float *A = (float*)_aligned_malloc(rows*true_cols*sizeof(float), ALLIGNED_LEN);
  float *B = (float*)_aligned_malloc(rows*sizeof(float), ALLIGNED_LEN);
  float *C = (float*)_aligned_malloc(rows*sizeof(float), ALLIGNED_LEN);
#else
  int true_cols = cols;
  float *A = (float*)malloc(rows*true_cols*sizeof(float));
  float *B = (float*)malloc(rows*sizeof(float));
  float *C = (float*)malloc(rows*sizeof(float));
#endif

  init(A, rows, cols, true_cols);
  init(B, rows, 1, 1);

  // computing
  TB__;
  for (int k = 0; k < REPEATTIMES; k++){
    multiply(C, A, B, rows, cols, true_cols);
  }
  TE__;

  // print result.
  print_sum(C, rows, 1, 1);

#ifdef ALIGNED
  _aligned_free(A); A = NULL;
  _aligned_free(B); B = NULL;
  _aligned_free(C); C = NULL;
#else
  free(A); A = NULL;
  free(B); B = NULL;
  free(C); C = NULL;
#endif

  return 0;
}
// filename : multiply.cpp
void multiply(float *C, float *A, float *B, int rows, int cols, int true_cols){
  for (int i = 0; i < rows; i++){
    C[i] = 0;
    #ifdef ALIGNED
    #pragma vector aligned
    #endif
    for (int j = 0; j < cols; j++){
      C[i] += A[i*true_cols+j]*B[j];
    }
  }
}

编译:

user@machine> icl /DALIGNED /O2 /Qopt-report:1 /Qopt-report-phase:vec main.cpp multiply.cpp

执行:

82 : 0.17747 seconds
2483.53

相对第一个优化的版本又提升了一点速度。


结论

vectorization版本:不需要改变源代码,通过修改编译器选项直接实现向量化。

aligned版本:需要修改代码,使得内存对其。可以进一步获得性能。

ICL Auto Vectorization的更多相关文章

  1. 使用Auto TensorCore CodeGen优化Matmul

    使用Auto TensorCore CodeGen优化Matmul 本文将演示如何使用TVM Auto TensorCore CodeGen在Volta / Turing GPU上编写高性能matmu ...

  2. C++11特性——变量部分(using类型别名、constexpr常量表达式、auto类型推断、nullptr空指针等)

    #include <iostream> using namespace std; int main() { using cullptr = const unsigned long long ...

  3. overflow:hidden与margin:0 auto之间的冲突

    相对于父容器水平居中的代码margin:0 auto与overflow:hidden之间存在冲突.当这两个属性同时应用在一个DIV上时,在chrome浏览器中将无法居中.至于为啥我也不明白.

  4. Android Auto开发之一《开始学习Auto 》

    共同学习,共同进步, 转载请注明出处.欢迎微信交流:sfssqs,申请注明"Android Car"字样 ================= =================== ...

  5. width:100%;与width:auto;的区别

    <div> <p>1111</p> </div> div{ width:980px; background-color: #ccc; height:30 ...

  6. SQl 2005 For XMl 简单查询(Raw,Auto,Path模式)(1)

    很多人对Xpath可能比较熟悉,但不知道有没有直接操作过数据库,我们都知道 在Sql2005里公支持的几种查询有Raw,Auto模式,页并没有Path和Elements用法等,如果在2000里使用过 ...

  7. margin:0 auto;不居中

    margin:0 auto:不居中可能有以下两个的原因; 1.没有设置宽度<div style="margin:0 auto;"></div>看看上面的代码 ...

  8. 初学C++ 之 auto关键字(IDE:VS2013)

    /*使用auto关键字,需要先赋初值,auto关键字是会根据初值来判断类型*/ auto i = ; auto j = ; cout << "auto i = 5" & ...

  9. C++11 - 类型推导auto关键字

    在C++11中,auto关键字被作为类型自动类型推导关键字 (1)基本用法 C++98:类型 变量名 = 初值;   int i = 10; C++11:auto 变量名 = 初值;  auto i ...

随机推荐

  1. [LeetCode] Pour Water 倒水

    We are given an elevation map, heights[i] representing the height of the terrain at that index. The ...

  2. [LeetCode] Palindromic Substrings 回文子字符串

    Given a string, your task is to count how many palindromic substrings in this string. The substrings ...

  3. Leetcode-颠倒整数

    给定一个范围为 32 位 int 的整数,将其颠倒. 例 1: 输入: 123 输出: 321 例 2: 输入: -123 输出: -321 例 3: 输入: 120 输出: 21 注意: 假设我们的 ...

  4. LGTB 与序列

    LGTB 有一个长度为N 的序列A,现在他想构造一个新的长度为N 的序列B,使得B 中的任意两个数都 互质. 并且他要使ai与bi对应项之差最小 请输出最小值 输入 第一行包含一个数N 代表序列初始长 ...

  5. 幸运序列(lucky)

    [问题描述] Lsy喜欢幸运数字,众所周知,幸运数字就是数字位上只有4和7的数字. 但是本题的幸运序列和幸运数字完全没关系,就是一个非常非常普通的序列.哈哈,是不是感觉被耍了,没错,你就是被耍了. L ...

  6. 【luogu P4005 清华集训2017】小Y和地铁

    题目描述 小 Y 是一个爱好旅行的 OIer.一天,她来到了一个新的城市.由于不熟悉那里的交通系统,她选择了坐地铁. 她发现每条地铁线路可以看成平面上的一条曲线,不同线路的交点处一定会设有 换乘站 . ...

  7. ●UVA 10652 Board Wrapping

    题链: https://vjudge.net/problem/UVA-10652 题解: 计算几何,Andrew求凸包, 裸题...(数组开小了,还整了半天...) 代码: #include<c ...

  8. ●BZOJ 4826 [Hnoi2017]影魔

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4826 题解: 主席树,单调栈 以前还没做过这种维护信息的题,感觉好奇妙. 每对相邻的两个数所 ...

  9. 测试修改gcs_server_processes参数

    RAC部署前提是要求各节点的主机硬件一致的,但实际如果碰上一些不规范的客户,经费有限或是扩容时已买不到同样的机器,那么采购的机器会有一些区别,比如RAC各节点的CPU核数有区别,那么默认的gcs_se ...

  10. URLDecoder: Illegal hex characters in escape (%) pattern - For input string

    原因:后台发布文章的时候,内容里面有%,导致后台URLDecoder.decode()转码的时候报错. 看了java.net.URLDecoder的decode()的源码,原来是转码错误. 贴出部分代 ...