oneAPI学习-使用oneAPI 实现矩阵乘法并分析性能瓶颈
oneAPI学习-使用oneAPI 实现矩阵乘法并分析性能瓶颈
一.相关链接
- Get the Intel® oneAPI Base Toolkit
- oneapi_docs
- installation-guide-linux
- oneAPI-samples
- Intel® oneAPI Programming Guide
- Intel® VTune™ Profiler User Guide
- SYCL Specification
二.oneAPI介绍
Intel® oneAPI 是一个跨平台的编程模型,能够在不同的计算架构(如 CPU、GPU、FPGA)上提供统一的开发体验。通过使用 Data Parallel C++ (DPC++),开发者可以编写高性能的并行代码,以充分利用硬件的计算能力。
本文将使用 oneAPI 实现矩阵乘法,并使用 Intel® VTune™ Profiler 对程序进行性能分析,找出可能的性能瓶颈。
三.矩阵乘法简介
矩阵乘法是线性代数中的基本操作,其计算如下:
给定矩阵 A(尺寸为 M×K)和矩阵 B(尺寸为 K×N),它们的乘积矩阵 C(尺寸为 M×N)的每个元素计算为:
C[i][j] = Σ(k=0 到 K-1) A[i][k] * B[k][j]
四.环境准备
wget https://registrationcenter-download.intel.com/akdlm/IRC_NAS/e6ff8e9c-ee28-47fb-abd7-5c524c983e1c/l_BaseKit_p_2024.2.1.100_offline.sh
sudo sh ./l_BaseKit_p_2024.2.1.100_offline.sh -a --silent --cli --eula accept
source /opt/intel/oneapi/setvars.sh
五.获取设备列表
tee syscl_devices.cpp<<-'EOF'
#include <CL/sycl.hpp>
#include <iostream>
int main() {
std::vector<sycl::device> devices = sycl::device::get_devices();
for (const auto& dev : devices) {
std::cout << "设备名称: " << dev.get_info<sycl::info::device::name>() << std::endl;
std::cout << "厂商: " << dev.get_info<sycl::info::device::vendor>() << std::endl;
std::cout << "驱动版本: " << dev.get_info<sycl::info::device::driver_version>() << std::endl;
std::cout << "设备类型: ";
switch (dev.get_info<sycl::info::device::device_type>()) {
case sycl::info::device_type::cpu:
std::cout << "CPU" << std::endl;
break;
case sycl::info::device_type::gpu:
std::cout << "GPU" << std::endl;
break;
case sycl::info::device_type::accelerator:
std::cout << "加速器" << std::endl;
break;
default:
std::cout << "其他" << std::endl;
}
std::cout << "--------------------------" << std::endl;
}
return 0;
}
EOF
icpx -fsycl -O3 -o syscl_devices syscl_devices.cpp
./syscl_devices
- 输出
设备名称: Intel(R) Xeon(R) CPU E5-2690 v4 @ 2.60GHz
厂商: Intel(R) Corporation
驱动版本: 2024.18.7.0.11_160000
设备类型: CPU
六.基础版实现
tee matrix_multiplication.cpp<<-'EOF'
#include <CL/sycl.hpp>
#include <iostream>
#include <vector>
#include <chrono>
#include <exception>
using namespace sycl;
using namespace std;
// 矩阵尺寸
constexpr size_t M = 1024; // 行数
constexpr size_t N = 1024; // 列数
constexpr size_t K = 1024; // 中间维度
int main() {
// 创建 CPU 或 GPU 设备的队列
queue q(default_selector{
}, [](exception_list e_list) {
for (exception_ptr const& e : e_list) {
try {
rethrow_exception(e);
} catch (std::exception const& e) {
std::cout << "Caught asynchronous SYCL exception:\n" << e.what() << std::endl;
}
}
});
std::cout << "Device: " << q.get_device().get_info<info::device::name>() << std::endl;
// 分配并初始化主机内存
vector<float> A(M * K);
vector<float> B(K * N);
vector<float> C(M * N, 0.0f);
// 初始化矩阵 A 和 B
for (size_t i = 0; i < M * K; ++i) {
A[i] = static_cast<float>(i % 100);
}
for (size_t i = 0; i < K * N; ++i) {
B[i] = static_cast<float>(i % 100);
}
// 创建设备内存缓冲区
buffer<float, 1> buffer_A(A.data(), range<1>(M * K));
buffer<float, 1> buffer_B(B.data(),