关于DPC++编译器部署试用的过程分享

目标:

  • 部署好DPC++编译器环境

  • 实现示例程序的本地编译并分析


内容:

        1.了解什么是DPC++

 DPC++是Data Parallel C++(数据并行C++)的首字母缩写,它是Intel为了将SYCL引入LLVM和oneAPI所开发的开源项目。SYCL是为了提高各种加速设备上的编程效率而开发的一种高级别的编程模型,简单来说它是一种跨平台的抽象层,用户不需要关心底层的加速器具体是什么,按照标准编写统一的代码就可以在各种平台上运行。可以说SYCL大大提高了编写异构计算代码的可移植性和编程效率,已经成为了异构计算的行业标准

        2.实验环境准备

DPC++的实践环境分为以下三种:

①基于Intel DevCloud环境

②Dpcpp编译器的本地安装

③基于Docker的环境

由于部分方式受限于Git访问受限和下载速度堪忧,本文着重介绍方法①

        3.DevCloud注册

①点击链接,创建账户

https://idzcn.com/devcloud.htmicon-default.png?t=N5F7https://idzcn.com/devcloud.htm

②填写个人账户信息

③验证电子邮件后跳转至主页

若未能正常跳转请直接访问主页:Overview | Intel® DevCloud

        3.JupyterLab登录

①登录个人账号

②Get Started后选择页面最下方 Lauch JupyterLab

③实现登录到JupyterLab页面后则恭喜环境搭建完成

         4.实现hello world程序

①创建新笔记本写代码,使用终端编译运行

 

②编写输出“Hello World”代码

在笔记本中编写代码,注意的是下附代码第一行表示在test/hello.cpp文件下编写,则需我们到终端中创建文件路径

%%writefile test/hello.cpp
#include <CL/sycl.hpp>
#include <iostream>
using namespace sycl;
const std::string secret {
"Ifmmp-!xpsme\"\012J(n!tpssz-!Ebwf/!"
"J(n!bgsbje!J!dbo(u!ep!uibu/!.!IBM\01"};
const auto sz = secret.size();
int main() {
    queue Q;
char *result = malloc_shared<char>(sz, Q);
std::memcpy(result, secret.data(), sz);
Q.parallel_for(sz, [=] (auto &i) {
result[i] -= 1;
}).wait();
std::cout << result << "\n";
return 0;
}

 ③运行笔记本代码,终端编译执行

点击笔记本上方运行三角号

ps:此时在终端中目标路径输入ls指令,应该可以看见已经编写好的cpp文件

 

在终端中编译 运行

icpx -fsycl hello.cpp -o hello

./hello

         5.示例代码运行

①DPC++设备选择方式1:默认的设备选择器

代码如下:

#include <CL/sycl.hpp>
#include <iostream>
using namespace sycl;
int main(){
    queue Q;
    std::cout << "Select device: "<<
    Q.get_device().get_info<info::device::name>() << "\n";
    return 0;
}

编译运行结果:

 此时输出的是默认设备

②DPC++设备选择方式2:使用host_selector

代码如下:

#include <CL/sycl.hpp>
#include <iostream>
using namespace sycl;
int main(){
    queue Q (host_selector{} );
    std::cout << "Select device: "<<
    Q.get_device().get_info<info::device::name>() << "\n";
    std::cout <<" -> Device vendor: " <<
    Q.get_device().get_info<info::device::vendor>() << "\n";
    return 0;
}

由于老版的sycl支持host_selector,到sycl 2020版本host_selector被弃用,无法运行的原因,

执行结果无法运行:

 ③DPC++设备选择方式3:使用cpu_selector

代码如下:

#include <CL/sycl.hpp>
#include <iostream>
using namespace sycl;
int main(){
    queue Q ( cpu_selector_v );
    std::cout << "Select device: "<<
    Q.get_device().get_info<info::device::name>() << "\n";
    std::cout <<" -> Device vendor: " <<
    Q.get_device().get_info<info::device::vendor>() << "\n";
    return 0;
}

运行结果:

 该运行结果显示出cpu设备选择器

④DPC++设备选择方式4:使用多个设备选择器

代码如下:

#include <CL/sycl.hpp>
#include <iostream>
using namespace sycl;
 
int main(){
        queue my_default_queue(default_selector_v);
        queue my_accelerator_queue(accelerator_selector_v);
 
        std::cout << "Selected device 1:" << my_default_queue.get_device().get_info<info::device::name>() << "\n";
        std::cout << "Selected device 2:" << my_accelerator_queue.get_device().get_info<info::device::name>() << "\n";
 
        return 0;
}

运行结果:

代码中的accelerator_selector_v为选择一个加速器设备(如 FPGA、ASIC 等)

⑤向数组中填充数据

代码如下:

#include <CL/sycl.hpp>
#include <array>
#include <iostream>
using namespace sycl;
 
int main(){
        constexpr int size = 16;
        std::array<int,size> data;
        buffer  B {data};
 
        queue Q{};
        std::cout << "Selected device is : " << Q.get_device().get_info<info::device::name>() << "\n";
 
        Q.submit([&](handler& h){
                                accessor acc{B,h};
                                h.parallel_for(size,[=](auto&idx){
                                                        acc[idx] = idx;
                                                });
                        });
        return 0;
}

 运行结果:

这段代码使用SYCL(ComputeCpp)库实现了并行计算的示例。它创建了一个队列,选择一个计算设备,并在该设备上执行并行任务。任务使用访问器访问缓冲区,并在每个迭代中将索引值赋给缓冲区中的元素。代码的主要目的是展示SYCL的基本用法,以及如何利用SYCL库在异构计算设备上进行并行计算。

 


### 线性 DP 的 C++ 实现及相关概念 #### 什么是线性 DP? 线性动态规划(Linear Dynamic Programming, 简称线性 DP)是一种经典的动态规划形式,适用于解决具有线性结构的问题。其核心思想是通过状态转移方程逐步计算最优解,通常用于求解最值问题、路径问题以及子序列相关问题。 --- #### 线性 DP 的基本实现流程 以下是基于 C++ 的线性 DP 基本框架: 1. **定义状态** 设定 `dp[i]` 表示以第 `i` 个位置为终点的状态值。例如,在最大子数组和问题中,`dp[i]` 可表示以 `a[i]` 结尾的最大连续子段和[^3]。 2. **初始化状态** 初始化边界条件,通常是第一个元素或者某些特殊值。例如:`dp[0] = a[0]`. 3. **状态转移方程** 根据具体问题设计状态转移关系。对于最大子数组和问题,可以采用如下公式: ```cpp dp[i] = max(dp[i-1] + a[i], a[i]); ``` 4. **返回最终结果** 遍历整个 `dp` 数组,取其中的最大值作为答案。 --- #### 示例代码:最大子数组和问题 以下是一个完整的 C++ 示例程序,展示如何利用线性 DP 解决最大子数组和问题: ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { int n; cin >> n; // 输入数组长度 vector<int> a(n); for (auto &x : a) cin >> x; // 输入数组元素 vector<int> dp(n); // 动态规划数组 dp[0] = a[0]; // 初始状态 int result = dp[0]; for (int i = 1; i < n; ++i) { // 计算每个状态 dp[i] = max(a[i], dp[i - 1] + a[i]); // 转移方程 result = max(result, dp[i]); // 更新全局最大值 } cout << result << endl; // 输出结果 return 0; } ``` 上述代码实现了 Kadane 算法的核心逻辑,并展示了线性 DP 的典型应用方式[^2]。 --- #### 进一步扩展:其他经典线性 DP 问题 除了最大子数组和之外,还有许多常见的线性 DP 应用场景,例如: 1. **最长上升子序列(LIS)** 给定一个整数数组,寻找其中最长的严格递增子序列。 ```cpp dp[i] = max(dp[j] + 1), where j < i and a[j] < a[i] ``` 2. **数字三角形问题** 寻找从顶到底的一条路径,使得经过的数字之和最大。 ```cpp dp[i][j] = triangle[i][j] + max(dp[i-1][j-1], dp[i-1][j]) ``` 3. **摘花生问题** 在二维网格上移动并收集尽可能多的物品。 ```cpp dp[x][y] = grid[x][y] + max(dp[x-1][y], dp[x][y-1]) ``` 这些问题是学习线性 DP 的良好起点,能够帮助理解状态的设计与转移过程[^5]。 --- #### 推荐资源 如果希望深入学习线性 DP 和 C++ 编程技巧,推荐参考以下资料: - 【C/C++算法】动态规划(线性 dp、区间 dp) - 【c++入门(2)】线性 DP ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值