Intel oneAPI笔记(3)--jupyter官方文档(SYCL Program Structure)学习笔记

前言

本文是对jupyterlab中oneAPI_Essentials/02_SYCL_Program_Structure文档的学习记录,包含对Device Selector、Data Parallel Kernel、Host Accessor、Buffer Destruction、的介绍,最后还有一个小关于向量(Vector)加法的实例

设备(Device)

设备类包含用于查询设备信息的成员函数,这对于创建多个设备的SYCL程序很有用,成员函数get_info,可以获取包括以下的信息:

名称,供应商,版本号,本地和全局工作编号,宽度内置类型,时钟频率,缓存宽度和大小,在线或离线等

设备选择器(Device Selector) 

这个类允许在运行时根据用户提供的启发式方法选择特定设备来执行内核。下面的代码示例显示了标准设备选择器的使用

运行结果

队列(Queue) 

队列类提交要由SYCL运行时执行的命令组。队列是一种将工作提交给设备的机制。一个队列映射到一个设备,多个队列可以映射到同一个设备

内核(Kernel)

内核对象不是由用户显式构造的,而是在调用parallel_for等内核调度函数时构造的,用于在设备上执行代码的方法和数据

Scope

Application scope和command group scope

执行在主机上的代码,在这个scope中可以使用c++全部代码

Kernel scope

执行在设备(Device)上的代码,这个scope中可以无法使用部分c++的功能

Parallel Kernels

并行内核允许一个操作的多个实例并行执行。这对于offload的基本for循环的并行执行非常有用,因为for循环中的每个迭代都是完全独立的,并且按任意顺序执行。并行内核是用parallel_for函数表示的。c++应用程序中的一个简单的'for'循环编写如下

用下面这种方法,可以offload到一个加速器(accelerator)中

基本并行内核的功能主要包含range、id和item类。Range类用于描述并行执行的迭代空间,id类用于在并行执行中索引内核的单个实例

上述的i可以换成item,这样的话,可以通过相关函数不仅得到原来的索引值i,还可以在这个循环内部得到range

Nd Range Kernels

基本并行内核是并行for循环的简单方法,但不允许在硬件级别进行性能优化。ND-Range内核是表达并行性的另一种方式,它通过提供对本地内存的访问和将执行映射到硬件上的计算单元来实现低级性能调优。整个迭代空间被分成称成很多工作组,工作组中的工作项被安排在硬件上的单个计算单元上

nd_range内核的功能通过nd_range和nd_item类公开。Nd_range类表示使用全局执行范围和每个工作组的本地执行范围的分组执行范围。Nd_item类表示内核函数的单个实例,并允许查询工作组范围和索引

比如上面这个例子,第一个range<1>(1024)表示全局执行范围是1024个工作单元,第二个range<1>(64)表示每个工作组的本地执行范围是64,也就是一个工作组有64个单元,也照应了图上的(4*4*4)区域

Buffer Model 

缓冲区在跨设备和主机的SYCL应用程序中封装数据。访问器是访问缓冲区数据的机器

SYCL的代码开头内容:

SYCL程序是标准的c++。该程序在主机上调用,并将计算offload到加速器上。程序员使用SYCL的队列、缓冲区、设备和内核抽象来指示应该卸载哪些部分的计算和数据

SYCL程序的第一步,我们创建一个队列。我们通过将任务提交到队列,将计算量转移到设备上。程序员可以通过选择器选择CPU、GPU、FPGA等器件。这个程序在这里使用默认的q,这意味着SYCL运行时通过使用默认选择器来选择运行时可用的最有能力的设备。但下面是一个简单的SYCL程序

设备和主机可以共享物理内存,也可以拥有不同的内存。当内存不同时,offload计算需要在主机和设备之间复制数据。SYCL不要求程序员管理数据副本。通过创建缓冲区和访问器,SYCL确保数据对主机和设备可用,而无需程序员的任何努力。SYCL还允许程序员在需要实现最佳性能时显式控制数据移动

在SYCL程序中,我们定义了一个内核(就是device 运行的那部分代码)。对于像这样的简单程序,索引空间直接映射到数组的元素。内核被封装在一个c++ lambda函数中。lambda函数在索引空间中以坐标数组的形式传递一个点。对于这个简单的程序,索引空间坐标与数组索引相同。下面程序中的parallel_for将lambda应用到索引空间。索引空间在parallel_for的第一个参数中定义为从0到N-1的一维范围

对访问器(Accessor)的隐式依赖 

访问器在SYCL图中创建对内核执行排序的数据依赖关系,如果两个内核使用相同的缓冲区,第二个内核需要等待第一个内核完成,以避免竞争条件,比如下面这个图,必须在kernel1运行完之后,缓冲区A才能空闲,然后才能继续运行kernel2

样例

%%writefile lab/buffer_sample.cpp
//==============================================================
// Copyright © Intel Corporation
//
// SPDX-License-Identifier: MIT
// =============================================================
#include <sycl/sycl.hpp>constexpr int num=16;
using namespace sycl;int main() {auto R = range<1>{ num };//Create Buffers A and Bbuffer<int> A{ R }, B{ R };//Create a device queuequeue Q;//Submit Kernel 1Q.submit([&](handler& h) {//Accessor for buffer Aaccessor out(A,h,write_only);h.parallel_for(R, [=](auto idx) {out[idx] = idx[0]; }); });//Submit Kernel 2Q.submit([&](handler& h) {//This task will wait till the first queue is completeaccessor out(A,h,write_only);h.parallel_for(R, [=](auto idx) {out[idx] += idx[0]; }); });//Submit Kernel 3Q.submit([&](handler& h) { //Accessor for Buffer Baccessor out(B,h,write_only);h.parallel_for(R, [=](auto idx) {out[idx] = idx[0]; }); });//Submit task 4Q.submit([&](handler& h) {//This task will wait till kernel 2 and 3 are completeaccessor in (A,h,read_only);accessor inout(B,h);h.parallel_for(R, [=](auto idx) {inout[idx] *= in[idx]; }); }); // And the following is back to device codehost_accessor result(B,read_only);for (int i=0; i<num; ++i)std::cout << result[i] << "\n";      return 0;
}

运行结果

结果解释:并行运行kerne11和kernel3,在缓冲区A和B中分别写入0--15这16个数,然后运行kernel2,让缓冲区A中的数翻二倍,最后运行kernel4,让缓冲区A中的0--30这16个数和缓冲区B中的0--15这16个数相乘,最后输出

Host Accessor

主机访问器是使用主机缓冲区访问目标的访问器。它是在命令组的作用域之外创建的,它们用于通过构造主机访问器对象将数据同步回主机。缓冲区销毁是将数据同步回主机的另一种方法

缓冲区获取存储在vector中的数据的所有权。创建主机访问器是一个阻塞调用,只有在所有队列中修改同一缓冲区的SYCL内核完成执行并且主机可以通过该主机访问器访问数据之后才会返回

运行结果

下面介绍,主机和设备数据同步的另一种方法:缓冲区销毁

Buffer Destruction

在下面的示例中,缓冲区创建发生在单独的函数作用域中。当执行超出此函数作用域时,调用缓冲区析构函数,从而放弃数据的所有权并将数据复制回主机内存

运行结果

Custom Device Selector

自定义设备选择器使用您自己的逻辑(评分机制)自定义设备选择器

特定供应商名称的自定义设备选择器

具有GPU和特定设备名称的自定义设备选择器

基于设备的优先级的自定义设备选择器

下面是基于上种情况的案例

运行结果

Lab Exercise: Vector Add

下面是官方文档中向量相加这个练习

下面是我已经补全的代码

#include <sycl/sycl.hpp>
using namespace sycl;
int main() {const int N = 256;//# Initialize a vector and print valuesstd::vector<int> vector1(N, 10);std::cout<<"\nInput Vector1: ";    for (int i = 0; i < N; i++) std::cout << vector1[i] << " ";//# STEP 1 : Create second vector, initialize to 20 and print values//# YOUR CODE GOES HEREstd::vector<int> vector2(N, 20);std::cout<<"\nInput Vector2: ";for (int i = 0; i < N; i++) std::cout << vector2[i] << " ";//# Create Bufferbuffer vector1_buffer(vector1);//# STEP 2 : Create buffer for second vector //# YOUR CODE GOES HEREbuffer vector2_buffer(vector2);//# Submit task to add vectorqueue q;q.submit([&](handler &h) {//# Create accessor for vector1_bufferaccessor vector1_accessor (vector1_buffer,h);//# STEP 3 - add second accessor for second buffer//# YOUR CODE GOES HEREaccessor vector2_accessor (vector2_buffer,h);h.parallel_for(range<1>(N), [=](id<1> index) {//# STEP 4 : Modify the code below to add the second vector to first onevector1_accessor[index] += vector2_accessor[index];});});//# Create a host accessor to copy data from device to hosthost_accessor h_a(vector1_buffer,read_only);//# Print Output values std::cout<<"\nOutput Values: ";for (int i = 0; i < N; i++) std::cout<< vector1[i] << " ";std::cout<<"\n";return 0;
}

运行结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/134221.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

zookeeper:启动原理

主类&#xff1a; QuorumPeerMain, 其中调用了main对象的initializeAndRun方法&#xff0c; 首先定义了QuorumPeerConfig对象&#xff0c;然后调用了parse方法&#xff0c;parse方法代码如下&#xff1a; 其中调用的parseProperties方法的代码如下&#xff1a; 可以看到&am…

Linux 实现原理 — NUMA 多核架构中的多线程调度开销与性能优化

前言 NOTE&#xff1a;本文中所指 “线程” 均为可执行调度单元 Kernel Thread。 NUMA 体系结构 NUMA&#xff08;Non-Uniform Memory Access&#xff0c;非一致性存储器访问&#xff09;的设计理念是将 CPU 和 Main Memory 进行分区自治&#xff08;Local NUMA node&#x…

【GO】项目import第三方的依赖包

目录 一、导入第三方包 1.执行命令 2.查看go环境变量参数 3.查看go.mod文件的变化情况 二、程序里如何import 1. import依赖包 2. 程序编写 本次学习go如果依赖第三方的包&#xff0c;并根据第三方的包提供的接口进行编程&#xff0c;这里需要使用go get命令。下面将go…

无人机红外相机的畸变矫正

在项目开展过程中&#xff0c;发现大疆M30T的红外相机存在比较明显的畸变问题&#xff0c;因此需要对红外图像进行畸变矫正。在资料检索过程中&#xff0c;发现对红外无人机影像矫正的资料较少&#xff0c;对此&#xff0c;我从相机的成像原理角度出发&#xff0c;探索出一种效…

Redis主从配置和哨兵模式

主从简介 1、主从 – 用法 像MySQL一样&#xff0c;redis是支持主从同步的&#xff0c;而且也支持一主多从以及多级从结构。 主从结构&#xff0c;一是为了纯粹的冗余备份&#xff0c;二是为了提升读性能&#xff0c;比如很消耗性能的SORT就可以由从服务器来承担。 redis的主…

动态规划实例——01 背包详解

题目描述 有 n 件物品&#xff0c;每件物品有一个重量和一个价值&#xff0c;分别记为 w1&#xff0c;w2&#xff0c;…&#xff0c;wn 和 c1&#xff0c;c2&#xff0c;…&#xff0c;cn。现在有一个背包&#xff0c;其容量为 wk&#xff0c;要从 n 件物品种任取若干件。要求…

ansible安装和常见模块

文章目录 ansible的安装1.1 yum install epel-release.noarch1.2配置epel源的baseurl1.3安装ansible1.4安装ansible报错问题1.5 yum卸载 ansible的安装 ansible是由epel源提供的&#xff0c;所以需要配置epel源。要么通过配置好的baseos源直接执行“yum install epel-release.…

Modbus转Profinet网关在暖通空调系统中应用案例

在过去&#xff0c;空调系统一般采用传统的控制方式&#xff0c;通常需要使用独立的控制模块和传感器来监测和控制温度、湿度等参数。这种传统的控制方式不仅复杂&#xff0c;而且容易出现故障和误差&#xff0c;给用户的使用和维护带来了一定的困扰。 然而&#xff0c;通过P…

20.8 OpenSSL 套接字SSL传输文件

有了上面的基础那么传输文件的实现就变得简单了&#xff0c;在传输时通常我们需要打开文件&#xff0c;并每次读入1024个字节的数据包&#xff0c;通过SSL加密传输即可&#xff0c;此处的文件传输功能在原生套接字章节中也进行过详细讲解&#xff0c;此处我们还是使用原来的密钥…

Mysql8与mariadb的安装与常用设置

一、v10服务器mariadb的安装与常用设置 V10服务器默认安装了mariadb数据库。也可使用命令sudo yum install mariadb手动安装或升级默认安装的版本。 1.1 修改数据库密码 systemctl restart mariadb,重启mariadb服务&#xff1b;mysql -u root -p,要求输入密码直接回车&#…

微信小程序自动化采集方案

本文仅供学习交流&#xff0c;只提供关键思路不会给出完整代码&#xff0c;严禁用于非法用途&#xff0c;拒绝转载&#xff0c;若有侵权请联系我删除&#xff01; 一、引言 1、对于一些破解难度大&#xff0c;花费时间长的目标&#xff0c;我们可以先采用自动化点击触发请求&…

centos7安装jdk-阿里云服务器

1.背景 2.安装步骤 步骤:(特别注意:虚拟机安装的一般是32位的操作系统,jdk也必须使用32位的) 查看虚拟机版本:sudo uname --m i686 //表示是32位 x86_64 // 表示是64位 查看是否已经安装jdk 看看 是否设置了jdk环境变量: echo $JAVA_HOME&#xff1b; 或运行命令&#xff1a; …

CMD命令行中如何切换路径。

问题描述&#xff1a; windows命令行中我记得切换命令是cd E:命令就行了呀。但是现在好像不行了。 问题解决&#xff1a;现在windows命令行中切换命令需要在cd E:之间增加一个/D。注意是/D&#xff0c;不是\D。 具体命令如下&#xff1a;CD /D E: 结果如下如所示&#xff1a…

Linux开发工具的使用(vim、gcc/g++ 、make/makefile)

文章目录 一 &#xff1a;vim1:vim基本概念2:vim的常用三种模式3:vim三种模式的相互转换4:vim命令模式下的命令集- 移动光标-删除文字-剪切/删除-复制-替换-撤销和恢复-跳转至指定行 5:vim底行模式下的命令集 二:gcc/g1:gcc/g的作用2:gcc/g的语法3:预处理4:编译5:汇编6:链接7:函…

Leetcode—2731.移动机器人【中等】

2023每日刷题&#xff08;二十二&#xff09; Leetcode—2731.移动机器人 算法思路 参考自灵茶山艾府 实现代码 class Solution { public:const int MOD 1e9 7;int sumDistance(vector<int>& nums, string s, int d) {int n nums.size();vector<long long…

Vue Vuex模块化编码

正常写vuex的index的时候如果数据太多很麻烦&#xff0c;如有的模块是管理用户信息或修改课程等这两个是不同一个种类的&#xff0c;如果代码太多会造成混乱&#xff0c;这时候可以使用模块化管理 原始写法 如果功能模块太多很乱 import Vue from vue import Vuex from vuex …

[JavaWeb]——JWT令牌技术,如何从获取JWT令牌

&#x1f308;键盘敲烂&#xff0c;年薪30万&#x1f308; 目录 一、前言&#xff1a; 二、JWT令牌技术 2.1 概念介绍 2.2 组成介绍 2.3 JWT对象介绍 2.4 JWT生成 2.5 JWT校验 三、获取JWT令牌 四、总结 一、前言&#xff1a; 问题抛出❓ 许多网页都会设置登录界面&a…

Qt 继承QAbstractListModel实现自定义ListModel

1.简介 QAbstractListModel类提供了一个抽象模型&#xff0c;可以将其子类化以创建一维列表模型。 QAbstractListModel为将其数据表示为简单的非层次项目序列的模型提供了一个标准接口。它不直接使用&#xff0c;但必须进行子类化。 由于该模型提供了比QAbstractItemModel更…

ZZ308 物联网应用与服务赛题第B套

2023年全国职业院校技能大赛 中职组 物联网应用与服务 任 务 书 &#xff08;B卷&#xff09; 赛位号&#xff1a;______________ 竞赛须知 一、注意事项 1.检查硬件设备、电脑设备是否正常。检查竞赛所需的各项设备、软件和竞赛材料等&#xff1b; 2.竞赛任务中所使用的…

JAVA中类和对象的认识

1、面向对象的初步认知 1.1 什么是面向对象 Java是一门纯面向对象的语言(Object Oriented Program&#xff0c;简称OOP)&#xff0c;在面向对象的世界里&#xff0c;一切皆为对象。面 向对象是解决问题的一种思想&#xff0c;主要依靠对象之间的交互完成一件事情。用面向对象的…