英特尔OneAPI--加速计算与DPC++

英特尔OneAPI–加速计算与DPC++

OneAPI是什么

oneAPI 行业计划,英特尔提出的一种跨架构的编程模型,使开发人员可以自由面对异构场景,使用一套编程模型进行编程加速计算。One API通过开放社区促进企业和社区合作,支持针对不同架构和供应商的代码重用。

DPC++

DPC++(Data Parallel C++) 数据并行C++,是一个基于C++和SYCL标准的跨架构语言,方便用户直接编程。
DPC++为用户提供选择的自由,是面向未来的编程模型。
▪ 允许跨硬件目标重复使用代码
▪ 允许对特定加速器进行定制化调优
▪ 替代专属语言的开放式、跨行业方案

实验介绍

这两次实验都是在Intel提供的JupyterLab中进行,免去了环境安装,非常方便。本次介绍利用CPU和GPU协同计算交叉熵的实验。
交叉熵(cross entropy)在神经网络当中经常被用作损失值,要说清楚交叉熵的概念,还需要从熵说起。

CPU计算kernel

使用CPU来计算和我们的常见过程类似,通过两层循环计算交叉熵。

//CPU计算
float cpu_kernel(float* X, int* mask, float* weight, float* loss) {
    double duration = 0.0;
    chrono::high_resolution_clock::time_point s, e;

    s = chrono::high_resolution_clock::now();//获取运算开始时间戳
    for (int i = 0; i < K; ++i) {
        for (int j = 0; j < N; ++j) {
            float exp_sum = 0.0;

            for (int k = 0; k < M; ++k) {
                exp_sum += exp(X[i * M * N + k * N + j]);//计算每一个M列的exp值之和
            }
			//计算过程与GPU相同
            int mask_id = mask[i * N + j];

            loss[i * N + j] = weight[i * N + j] * (log(exp(X[i * M * N + mask_id * N + j]) / exp_sum));
        }
    }
    e = chrono::high_resolution_clock::now();
    duration = chrono::duration<float, milli>(e - s).count();//计算CPU时间差(ms)

    return duration;
}

GPU计算kernel

GPU的实现过程则需要用到DPC++框架的一些方法:

  • 首先在主机和设备中申请存储空间,主机生成数组后,需要把数据从主机拷贝到设备上
  • 调用GPU kernel
  • kernel中根据设定的数据划分,计算自己负责的那部分数据的交叉熵
//GPU计算
float gpu_kernel(float* X, int* mask, float* weight, float* loss, queue& q) {

    float duration = 0.0;
    auto e = q.submit([&](handler& h) {

        //对于该计算,K维度和N维度相互独立,这里也用K*N作为并行化的range
        h.parallel_for( K*N, [=](auto& idx) {

            //K为行,下面是行列值的计算
            int row = idx / N ;
            int col = idx % N ;

            float exp_sum = 0.0;
            for (int i = 0; i < M; ++i) {
                exp_sum += exp(X[row * M * N + i * N + col]);	//计算每一个M列的exp值之和
            }

            int mask_id = mask[row * N + col];	//选择K,N二维列表对应掩膜值
            loss[row * N + col] = weight[row * N + col] * log(exp(X[row * M * N + mask_id * N + col]) / exp_sum);//找出对应的xi值,计算yi值,并乘以对应的权重值得到loss值

            });
        });

    e.wait();//阻塞等等该计算完成

    // 获取GPU kernal的开始和介绍时间戳之差(ns),转换成ms
    duration = (e.get_profiling_info<info::event_profiling::command_end>() - e.get_profiling_info<info::event_profiling::command_start>()) / 1000.0f / 1000.0f;

    return duration;
}

结果

计算结果加速比约为4
英特尔OneAPI--加速计算与DPC++_第1张图片

你可能感兴趣的:(课程,oneapi)