Oneapi应用——矩阵相乘实践
oneapi简介
One API 是 Intel 推出的一个软件开发工具套件,旨在简化和加速跨多个硬件加速器的高性能计算和数据处理应用程序的开发。该套件支持包括 CPU、GPU、FPGA 等多种硬件平台。
优点主要有:
- 多硬件支持: One API 提供了支持 Intel 处理器、图形处理器(GPU)和可编程逻辑器件(FPGA)的 API,使开发者能够更轻松地利用各种硬件加速器的性能。
- 统一编程模型: One API 的目标是提供一个统一的编程模型,使开发人员能够以相似的方式开发和优化应用程序,而无需为不同的硬件平台编写不同的代码。
- DPC++ 编程语言: One API 引入了 Data Parallel C++(DPC++)编程语言,它是一种基于 C++ 的语言,支持异构计算和并行性,使开发者能够更好地利用硬件加速器。
- 开放标准: One API 倡导开放标准,支持行业标准如 SYCL(C++ 标准库的异构并行性支持)、OpenMP 等。
当然对于学生党来说最幸福的是可以白嫖intel的GPU资源进行训练
one api使用
基本工具包示例 |英特尔® DevCloud (intel.com)
适用于 Windows 的 OpenSSH 入门 | Microsoft Learn
首先用openssh连接到DevCloud,然后运行Hello World样本(这里的样本并不是hello world,而是vector add,难度近似),但由于官方给出的文档并没有进行编译,因此需要自行编译后再运行
Solved: Re: Vectoradd build error - Intel Community
笔者尝试过openssh+wins terminal或jupyter进行连接,两者都比较方便,只是jupyter上手更快,建议懒的初学者直接使用jupyter
矩阵相乘算法实践
-
矩阵定义
矩阵A的维度为M* N 矩阵B的维度为N* P,数值可以自行修改
constexpr int M = 2; constexpr int N = 3; constexpr int P = 4;
-
矩阵分配和初始化
float(*c_back)[P] = new float[M][P]; float(*a_back)[N] = new float[M][N]; float(*b_back)[P] = new float[N][P]; for (int i = 0; i < M; i++) for (int j = 0; j < P; j++) c_back[i][j] = 0.0f; for(int i = 0;i<M;i++) for(int j = 0;j<N;j++) cin >> a_back[i][j]; for(int i = 0;i<N;i++) for(int j = 0;j<P;j++) cin >> b_back[i][j]
-
使用DPC++进行矩阵乘法
queue q(default_selector_v);//创建了一个 SYCL 队列 q,选择默认的设备 buffer<float, 2> a_buf(reinterpret_cast<float *>(a_back), range(M, N)); buffer<float, 2> b_buf(reinterpret_cast<float *>(b_back), range(N, P)); buffer c_buf(reinterpret_cast<float *>(c_back), range(M, P)); //创建了 SYCL 缓冲区 a_buf、b_buf 和 c_buf,用于在主机和设备之间传递数据 q.submit([&](auto &h) {//使用 SYCL 提交一个任务,该任务包含了矩阵乘法的核函数。 accessor a(a_buf, h, read_only); accessor b(b_buf, h, read_only); accessor c(c_buf, h, write_only); int width_a = a_buf.get_range()[1]; //执行核函数 h.parallel_for(range(M, P), [=](auto index) { //使用 SYCL 的 parallel_for 函数进行并行计算,其中每个工作项负责计算矩阵 c 中的一个元素。 int row = index[0]; int col = index[1]; float sum = 0.0f; for (int i = 0; i < width_a; i++) { sum += a[row][i] * b[i][col]; } c[index] = sum; }); });
-
进行额外异常处理
catch (sycl::exception const &e) { cout << "An exception is caught while multiplying matrices.\n"; terminate(); }//使用 try-catch 块捕获 SYCL 异常,输出异常信息并终止程序
-
输出结果
for (int i = 0; i < M; i++) { for (int j = 0; j < P; j++) cout << c_back[i][j] << " "; cout << "\n"; }
运行代码
在第二节one api使用中的链接可以看到官方的运行代码教程
- 在gpu节点上建立任务
qsub build.sh
当任务建立完成后,将会在目录下看到build.sh.oxxx文件,则可以执行代码任务
- 运行程序
qsub run.sh
其中build.sh为:
#!/bin/bash
#PBS -l nodes=1:gpu:ppn=2
#PBS -d .
source /opt/intel/oneapi/setvars.sh >
echo
echo start: $(date "+%y/%m/%d %H:%M:%S.%3N")
echo
make all
echo
echo stop: $(date "+%y/%m/%d %H:%M:%S.%3N")
echo
run.sh为:
#!/bin/bash
#PBS -l nodes=1:gpu:ppn=2
#PBS -d .
source /opt/intel/oneapi/setvars.sh
echo
echo start: $(date "+%y/%m/%d %H:%M:%S.%3N")
echo
make run
echo
echo end: $(date "+%y/%m/%d %H:%M:%S.%3N")
echo
其实可以看出没有太多指令…主要是source和make all、make run语句
- 观测输出
%m/%d %H:%M:%S.%3N")
echo
make run
echo
echo end: $(date “+%y/%m/%d %H:%M:%S.%3N”)
echo
其实可以看出没有太多指令...主要是source和make all、make run语句
- 观测输出
使用指令 `cat run.sh.oXXXX`,则可以在控制台看到输出。