跳转至

小作业四:自动向量化与基于 intrinsic 的手动向量化

负责助教:张晨 zhang-c21@mails.tsinghua.edu.cn

背景

在课堂上,我们学习了单指令多数据流(SIMD)的概念。本次实验中,你将体会到这项技术带来的性能提升。具体而言,你需要测试编译器自动向量化后的程序性能,并基于 intel intrinsic 手动实现向量化。

任务

实验文件在集群上的位置为 /home/course/hpc/assignments/2023/exp4

首先将实验文件 拷贝到自己的目录 ,并进入 exp4 目录:

cp -R /home/course/hpc/assignments/2023/exp4 ~/
cd ~/exp4/

本次实验使用 intel C++ 编译器,因此需要加载对应的环境:

source /opt/intel/oneapi/setvars.sh

任务一:编译器自动向量化性能测试

直接运行 run.sh,你将得到如下输出:

+ set -e
+ make -j
icpc aplusb-baseline.cpp -c -o aplusb-baseline.o -g
icpc aplusb-autosimd.cpp -c -o aplusb-autosimd.o -g -xhost
icpc aplusb-intrinsic.cpp -c -o aplusb-intrinsic.o -g -xhost
icpc aplusb.cpp aplusb-baseline.o aplusb-autosimd.o aplusb-intrinsic.o -o aplusb -g -xhost
+ srun ./aplusb
baseline: ???? us
auto simd: ??? us
Wrong answer at 0: c1 = 1.224684, c3 = 0.000000
srun: error: conv3: task 0: Exited with exit code 1

其中,每个 ? 代表一个数字,你需要在实验报告中报告具体的数值。由此,你可以看出向量化带来的性能提升。

需要注意的是,若希望 intel C++ 编译器进行自动向量化,需要使用 -xhost 编译选项。在 gcc 编译器中的对应选项为 -march=native。开启该选项后,编译器会自动根据 CPU 支持的指令集进行向量化,且即使不使用 #pragma omp simd,编译器也能进行一定程度的向量化。

任务二:基于 intrinsic 的手动向量化

你需要使用 intel intrinsics 填写 aplusb-intrinsic.cpp 中的函数,以实现向量化版本的 c=a+b。为简化实现,你只需要考虑 n % 8 == 0 的情况。可能会用到以下的指令:

  • _mm256_load_ps: 接口为 extern __m256 _mm256_load_ps(float const *a),返回一个由数组 a 的前 8 个数组成的长度为 256 bit 的向量寄存器。官方文档
  • _mm256_store_ps:接口为 extern void _mm256_store_ps(float *a, __m256 b),表示将 256 bit 的向量寄存器 b 中的值存入数组 a 的前 8 个位置。 官方文档
  • _mm256_add_ps:接口为 extern __m256 _mm256_add_ps(__m256 m1, __m256 m2),返回向量寄存器 m1 中的 8 个单精度浮点数和 m2 中的 8 个单精度浮点数进行 SIMD 加法后得到的 8 个单精度浮点数。官方文档

在实现正确后,你将通过结果检查,并得到与编译器自动向量化相近的运行性能。

实验提交

本实验仅需提交实验报告,报告包含以下内容:

  1. baseline, auto simd 和 intrinsic 版本的 a+b 的运行时间。
  2. a_plus_b_intrinsic 函数的实现代码。

请将报告的 PDF 文件 提交至网络学堂。


最后更新: 2023年3月7日
作者: Harry Chen (3.03%), heheda (96.97%)