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
卷积实践
-
初始化缓冲区
sycl::queue queue(cl::sycl::default_selector{});//创建 SYCL 队列对象 queue buffer<float, 2> input_buffer(input.data(), cl::sycl::range<2>(height, width)); buffer<float, 2> kernel_buffer(kernel.data(), cl::sycl::range<2>(kernel_height, kernel_width)); buffer<float, 2> output_buffer(output.data(), cl::sycl::range<2>(height, width));//创建缓冲区对象,分别用于输入图像、卷积核和输出结果。
-
提交卷积操作任务
queue.submit([&](cl::sycl::handler &cgh) { auto input_accessor = input_buffer.get_access<cl::sycl::access::mode::read>(cgh); auto kernel_accessor = kernel_buffer.get_access<cl::sycl::access::mode::read>(cgh); auto output_accessor = output_buffer.get_access<cl::sycl::access::mode::write>(cgh); cgh.parallel_for(cl::sycl::range<2>(height, width), [=](cl::sycl::id<2> idx) { // 卷积操作的具体实现在下一节 }); }); //在 cgh.parallel_for 中,通过 input_accessor、kernel_accessor 和 output_accessor 获取缓冲区的访问权限。
-
卷积操作的具体体现
int x = idx[1]; int y = idx[0]; float sum = 0.0f; for (int ky = -kernel_height / 2; ky <= kernel_height / 2; ky++) { for (int kx = -kernel_width / 2; kx <= kernel_width / 2; kx++) { int px = std::min(std::max(x + kx, 0), width - 1); int py = std::min(std::max(y + ky, 0), height - 1); sum += input_accessor[py][px] * kernel_accessor[ky + kernel_height / 2][kx + kernel_width / 2]; } } output_accessor[y][x] = sum; //执行卷积操作,将结果存储在 sum 中,将 sum 存储到输出缓冲区
-
等待任务完成
queue.wait_and_throw();
-
主函数进行调用
// 图像和卷积核的大小定义 int width = 1024; int height = 768; int kernel_width = 3; int kernel_height = 3; // 初始化图像和卷积核数据 std::vector<float> image(width * height, 1.0f); std::vector<float> kernel = { 0, -1, 0, -1, 5, -1, 0, -1, 0}; std::vector<float> output(width * height); convolve(image, kernel, output, width, height, kernel_width, kernel_height);
运行代码
在第二节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语句
- 观测输出
%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`,则可以在控制台看到输出。