openai并行矩阵运算


一、前言

编写⼀个基于oneAPI的C++/SYCL程序来执行矩阵乘法操作。需要考虑大尺寸矩阵的乘法操作以及不同线程之间的数据依赖关系。通常在实现矩阵乘法时,可以使用块矩阵乘法以及共享内存来提高计算效率。

二、代码解释

2.1 头文件包含

代码如下(示例):

#include <sycl/sycl.hpp>
#include <iostream>
#include <vector>
#include <random>

这里包含了SYCL、输入/输出操作、向量和随机数生成所需的头文件。

2.2 命名空间声明

代码如下(示例):

using namespace sycl;
using namespace std;

这些语句将sycl和std命名空间引入当前作用域。


2.3 CustomDeviceSelector 类

代码如下(示例):

class CustomDeviceSelector {
public:
  CustomDeviceSelector(std::string vendorName) : vendorName_(vendorName){};
  int operator()(const device &dev) {
    // ...
  };

private:
  std::string vendorName_;
};

这个类定义了一个自定义设备选择器,根据设备是GPU还是CPU,以及设备名称是否包含指定的供应商名称,为设备分配一个评级。


2.4 矩阵初始化和随机数生成

代码如下(示例):

vector<vector<float>> matrix1(N, vector<float>(N));
vector<vector<float>> matrix2(N, vector<float>(N));
vector<vector<float>> matrix3(N, vector<float>(N));
// ...

创建了三个二维向量,表示大小为N x N的矩阵,并使用随机数填充矩阵 matrix1 和 matrix2。


2.5 创建缓冲区

代码如下(示例):

buffer<float, 2> Matrix1_buffer(reinterpret_cast<float*>(matrix1.data()), range<2>(N, N));
buffer<float, 2> Matrix2_buffer(reinterpret_cast<float*>(matrix2.data()), range<2>(N, N));
buffer<float, 2> Output_buffer(reinterpret_cast<float*>(matrix3.data()), range<2>(N, N));

创建了用于保存矩阵数据的 SYCL 缓冲区。


2.6 提交任务执行矩阵乘法

代码如下(示例):

queue q(selector);
q.submit([&](handler &h) {
  // ...
});

创建了一个使用自定义设备选择器的 SYCL 队列,并向队列提交了一个执行矩阵乘法的任务。


2.7 为输出缓冲区创建访问器

代码如下(示例):

host_accessor h_a(Output_buffer, read_write);

创建了一个主机访问器,用于从输出缓冲区读取结果。


三.全部代码

代码如下(示例):

#include <sycl/sycl.hpp>
#include <iostream>
#include <vector>
#include <random>
 
using namespace sycl;
using namespace std;
 
class CustomDeviceSelector {
 public:
  CustomDeviceSelector(std::string vendorName) : vendorName_(vendorName){};
  int operator()(const device &dev) {
    int device_rating = 0;
    if (dev.is_gpu() & (dev.get_info<info::device::name>().find(vendorName_) !=
                        std::string::npos))
      device_rating = 3;
    else if (dev.is_gpu())
      device_rating = 2;
    else if (dev.is_cpu())
      device_rating = 1;
    return device_rating;
  };
 
 private:
  std::string vendorName_;
};
 
int main() {
    const int N = 1024;
    
    //二维数组
    vector<vector<float>> matrix1(N, vector<float>(N));
    vector<vector<float>> matrix2(N, vector<float>(N));
    vector<vector<float>> matrix3(N, vector<float>(N));
    //初始化
    random_device rd;
    mt19937 rng(rd());
    uniform_int_distribution<int> dist(0, 2); 
 
    for (size_t i = 0; i < N; i++) {
        for (size_t j = 0; j < N; j++) {
            matrix1[i][j] = dist(rng);
            matrix2[i][j] = dist(rng);
        }
    }
    
    cout<<"\nmatrix1:\n";
     for (size_t i=0;i<N;i++)
{
    for (size_t j=0;j<N;j++){
        cout<<matrix1[i][j]<<" ";
    }
    cout<<"\n";
}
    cout<<"\nmatrix2:\n";
     for (size_t i=0;i<N;i++)
{
    for (size_t j=0;j<N;j++){
        cout<<matrix2[i][j]<<" ";
    }
    cout<<"\n";
}
    //Create buffers
    buffer<float, 2> Matrix1_buffer(reinterpret_cast<float*>(matrix1.data()), range<2>(N, N));
    buffer<float, 2> Matrix2_buffer(reinterpret_cast<float*>(matrix2.data()), range<2>(N, N));
    buffer<float, 2> Output_buffer(reinterpret_cast<float*>(matrix3.data()), range<2>(N, N));
 
 
    //Choose device
    std::string vendor_name = "Intel";
    CustomDeviceSelector selector(vendor_name);
    
 
    //Submit task to multiply matrices
    queue q(selector);
    q.submit([&](handler &h) {
      //# Create accessors for buffers
      accessor M1 (Matrix1_buffer,h,read_only);
      accessor M2 (Matrix2_buffer,h,read_only);
      accessor M3 (Output_buffer,h,write_only);
 
      h.parallel_for(nd_range<2>({N, N}, {64, 64}), [=](nd_item<2> item) {
          //# Multiplication
          size_t row = item.get_global_id(0);
          size_t col = item.get_global_id(1);
          for (size_t k = 0; k < N; ++k) {
              M3[row][col] += M1[row][k] * M2[k][col];
          }
        });
    });
 
 
    //Create accessor
    host_accessor h_a(Output_buffer, read_write);
 
    
    cout << "\nmatrix3:\n";
    for (size_t i = 0; i < N; i++) {
        for (size_t j = 0; j < N; j++) {
            cout << matrix3[i][j] << " ";
        }
        cout << "\n";
    }
    return 0;
}

四.学习心得

oneAPI强大之处在于其支持异构计算。在此作业中,我利用了oneAPI的SYCL扩展,它提供了一个标准的C++编程模型,简化了在不同类型的处理器上编程的复杂性,且算法本身可以在不进行任何更改的情况下,支持异构计算,这种跨平台兼容性对于降本增效、优化性能至关重要。我使用了oneAPI中的并行编程工具来加速矩阵乘法。这个过程让我体会到了并行化对于提高大规模计算任务效率的重要性,


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个菜鸡猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值