【高性能计算】opencl语法及相关概念(二):索引,队列,核函数

目录

  • 数据并行及任务并行
  • 异构编程语言的共性
  • opencl的划分方式
  • opencl上下文定义
  • 以字符串为主的程序对象
  • 同一设备,多个命令队列
  • 同时执行多个核函数的示例

数据并行及任务并行

数据并行是将大规模的计算任务划分为多个子任务,并将这些子任务同时应用于不同的数据集上。每个子任务在独立的处理器上执行,通过对不同的数据集进行并行处理来提高计算性能。数据并行特别适用于对大规模数据集进行相同操作的情况,例如矩阵乘法、图像处理等。

任务并行是将计算任务划分为多个子任务,每个子任务执行不同的操作或指令序列。不同的子任务在不同的处理器上同时执行,通过并行执行多个不同的操作来提高计算性能。任务并行特别适用于复杂的计算任务,其中不同的子任务之间存在依赖关系,需要协同工作完成。

异构编程语言的共性

在这里插入图片描述在高性能计算中,"内核"是指计算任务的最小执行单元或最小计算单元。它代表了一系列指令的集合,可以在处理器上执行,完成特定的计算或操作。

内核通常是针对某个特定的计算问题或算法进行优化的实现。它可以包含许多计算和数据处理操作,如矩阵乘法、向量运算、排序算法等。内核的设计旨在充分利用硬件资源(如处理器、内存等),通过并行执行多个内核实例,以提高计算性能和效率。

内核执行时通常独立于主程序运行,并且可以在多个处理器上并行执行。内核的优化包括利用数据局部性、向量化指令、缓存优化等技术,以最大程度地利用处理器的计算能力。

在高性能计算中,通过合理地划分和管理任务的内核,可以充分发挥并行计算的潜力,提高程序的执行效率和整体性能。内核的优化是高性能计算中关键的一环。
在这里插入图片描述

opencl的划分方式

在这里插入图片描述
(1)全局索引:对图示整个方阵而言,坐标位置在(6,5)。
(2)工作组(localSize),是对全局工作项的二次粗划分。
(3)局部索引,是工作项在工作组内部的索引。
在核函数内使用工作组,可以通过获取每个工作项的全局和局部索引来访问数据。索引的计算和访问逻辑如下:

  1. 获取全局索引:使用内置变量get_global_id(dim)可以获取当前工作项在维度dim上的全局索引。dim的值通常是0,表示第一个维度。

  2. 获取局部索引:使用内置变量get_local_id(dim)可以获取当前工作项在维度dim上的局部索引。dim的值通常是0,表示第一个维度。

  3. 获取全局范围:使用内置变量get_global_size(dim)可以获取整个执行范围(全局工作项数量)在维度dim上的大小。dim的值通常是0,表示第一个维度。

  4. 获取局部范围:使用内置变量get_local_size(dim)可以获取工作组在维度dim上的大小。dim的值通常是0,表示第一个维度。

通过这些索引和范围,您可以根据需要访问全局和局部内存中的数据。下面是一个简单的示例:

__kernel void myKernel(__global float* input, __global float* output)
{// 获取全局索引和局部索引size_t globalId = get_global_id(0);size_t localId = get_local_id(0);// 获取全局范围和局部范围size_t globalSize = get_global_size(0);size_t localSize = get_local_size(0);// 计算对应全局索引的输入和输出数据索引size_t inputIndex = globalId;size_t outputIndex = globalId;// 计算对应局部索引的输入和输出数据索引size_t localInputIndex = localId;size_t localOutputIndex = localId;// 在此处使用索引访问输入和输出数据,并进行计算output[outputIndex] = input[inputIndex] + localInput[localInputIndex];// 等待所有工作项完成局部计算barrier(CLK_LOCAL_MEM_FENCE);// 在此处进行工作组级别的计算或协作}

在这个示例中,我们在核函数myKernel中获取了全局索引和局部索引。使用这些索引,我们可以计算出要访问的输入和输出数组的索引,并在核函数内执行相应的计算操作。还可以使用局部索引进行工作组级别的计算或者协作(例如使用局部内存进行数据共享)。最后的barrier函数用于等待所有工作项完成局部计算,以确保所有工作项能够同步执行。

opencl上下文定义

设备(device):宿主机使用的 OpenCL设备集合。
内核 (kernel):在 OpenCL 设备上运行的 OpenCL 函数。
程序对象 (program object):实现内核的程序源代码和可执行文件。
内存对象(memory object):内存中对OpenCL设备可见的组对象,包含可以由内核实
例处理的值。

以字符串为主的程序对象

上下文中还包括一个或多个程序对象 (program object),程序对象包含内核的代码。程序对
象这个名字的选择容易让人混淆。最好把它想象成一个动态库,可以从中取出内核使用的函
数。程序对象会在运行时由宿主机程序构建。对于不是从事图形领域的程序员来说,这看起来
可能有些奇怪。可以考虑一下 OpenCL程序员面对的挑战。他编写了 OpenCL应用程序并把这个
应用程序交给最终用户,但是这些用户可能选择在其他地方运行这个应用程序。程序员根本无
法控制最终用户在哪里运行应用程序 (可能是 CPU、CPU 或者其他芯片)。OpenCL 程序员所知
道的只是目标平台符合OpenCL规范。
对于这个问题,解决方法就是在运行时从源代码构建程序对象。宿主机程序定义上下文中
的设备。只有那时才有可能知道如何编译程序源代码来创建内核代码。对于源代码本身
OpenCL 在形式上相当灵活。在很多情况下,这会是一个常规的字符串,可以在宿主机程序中静
态定义,或者在运行时从一个文件加载,也可能在宿主机程序中动态生成。

同一设备,多个命令队列

在OpenCL中,您可以在一个设备上创建多个命令队列。这样做主要有以下几个优点:1. 并发执行:通过使用多个命令队列,您可以并行地执行多个内核或命令,从而提高程序的性能和效率。2. 独立管理:每个命令队列都有自己的内核执行顺序和状态,因此您可以更灵活地管理和调度不同的内核和任务。3. 异步操作:使用多个命令队列可以实现异步操作。您可以将多个命令添加到不同的队列中,并在需要时进行同步。然而,创建多个命令队列也可能有一些注意事项:1. 设备限制:每个设备的命令队列数量是有限的,具体取决于硬件和驱动程序,超出限制可能导致错误。可以使用`clGetDeviceInfo`函数查询设备支持的最大命令队列数。2. 内存和资源管理:每个命令队列都有独立的内存和资源管理,因此需要确保系统中的总资源使用不超过设备的限制。3. 同步和数据共享:不同命令队列之间的同步和数据共享可能需要额外的机制,如事件或内存对象的共享。为了示范在同一个设备上创建多个命令队列,下面是一个简单的代码片段:```cpp
cl_device_id device;
cl_context context;
cl_command_queue queue1, queue2;// 创建设备和上下文
clGetDeviceIDs(NULL, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
context = clCreateContext(NULL, 1, &device, NULL, NULL, NULL);// 创建命令队列
queue1 = clCreateCommandQueue(context, device, 0, NULL);
queue2 = clCreateCommandQueue(context, device, 0, NULL);// 在命令队列1中提交命令
clEnqueueNDRangeKernel(queue1, kernel1, ...);// 在命令队列2中提交命令
clEnqueueNDRangeKernel(queue2, kernel2, ...);

在这个示例中,我们通过调用clCreateCommandQueue函数两次来创建了两个命令队列:queue1queue2。然后,我们可以在这两个命令队列中分别提交不同的内核或任务。

需要注意的是,不同命令队列之间的执行顺序是不确定的,除非您使用额外的同步机制,如事件或屏障,来确保它们的顺序和同步。另外,多个命令队列的使用可能需要更复杂的任务和数据管理,以确保正确的同步和协调。

```cpp
queue:命令队列对象,用于提交命令。num_events_in_wait_list:等待事件列表中事件的数量。通常为0,表示没有等待的事件。event_wait_list:指向等待事件列表的指针,用于指定在执行标记之前需要等待的事件。通常为NULL,表示没有等待的事件。event:返回的事件对象,用于标识标记命令的事件。在事件完成之前,可以使用该事件来等待或查询内核的执行状态。

同时执行多个核函数的示例

#include <CL/cl.h>
#include <iostream>#define NUM_ELEMENTS 1000
// 在这段代码中,R"(...)" 是一种称为原始字符串字面量(raw string literals)的C++11特性。这种特性允许在字符串中包含特殊字符而无需进行转义。
// 在您给出的代码中,R"( 和 ")" 包围的部分是一个原始字符串字面量,其中包含了一个内核函数的定义。
// 使用原始字符串字面量的好处是,您可以在字符串中直接使用特殊字符,例如反斜杠和双引号,而无需对它们进行转义。这在编写包含许多转义字符的长字符串时特别方便。
const char* kernelSource[] = {R"(__kernel void copy(__global int* input, __global int* output) {int gid = get_global_id(0);output[gid] = input[gid];})",R"(__kernel void doublevalue(__global int* output) {int gid = get_global_id(0);output[gid] = output[gid]+1;})"
};int main() {cl_platform_id platform;cl_device_id device;cl_context context;cl_command_queue queue;cl_program program;cl_kernel kernel;cl_kernel kernel2;cl_mem inputBuffer, outputBuffer;cl_event syncEvent;int input[NUM_ELEMENTS];int output[NUM_ELEMENTS];// 初始化输入数据for (int i = 0; i < NUM_ELEMENTS; i++) {input[i] = i;}// 创建平台、设备和上下文clGetPlatformIDs(1, &platform, NULL);clGetDeviceIDs(platform, CL_DEVICE_TYPE_CPU, 1, &device, NULL);context = clCreateContext(NULL, 1, &device, NULL, NULL, NULL);queue = clCreateCommandQueue(context, device, 0, NULL);// 创建内存对象inputBuffer = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(int) * NUM_ELEMENTS, input, NULL);outputBuffer = clCreateBuffer(context,  CL_MEM_READ_WRITE, sizeof(int) * NUM_ELEMENTS, NULL, NULL);cl_int err;// 创建内核程序并构建program = clCreateProgramWithSource(context, 2, kernelSource, NULL, &err);if (program == NULL || err != CL_SUCCESS) {std::cout << "Failed to create program object." << std::endl;}//1即num_devices:构建程序的设备数量。clBuildProgram(program, 1, &device, NULL, NULL, NULL);// 创建内核,第2个参数需要对应核函数名kernel = clCreateKernel(program, "copy", NULL);kernel2 = clCreateKernel(program, "doublevalue", NULL);// 设置内核参数clSetKernelArg(kernel, 0, sizeof(cl_mem), &inputBuffer);clSetKernelArg(kernel, 1, sizeof(cl_mem), &outputBuffer);clSetKernelArg(kernel2, 0, sizeof(cl_mem), &outputBuffer);// 创建同步事件// syncEvent = clCreateUserEvent(context, NULL);size_t globalSize[1]={NUM_ELEMENTS};//注意:在同一个命令队列中,对于相同的命令队列上的内核函数,它们通常是按顺序执行的。//这意味着在命令队列中提交的内核函数将按照它们被插入的顺序进行执行。//执行第一个内核clEnqueueNDRangeKernel(queue, kernel, 1, NULL, globalSize, NULL, 0, NULL, NULL);// 执行第二个内核(在第一个内核完成后执行)第二个1为在内核程序执行前等待的数量clEnqueueNDRangeKernel(queue, kernel2, 1, NULL, globalSize, NULL, 0, NULL, NULL);// 读取结果clEnqueueReadBuffer(queue, outputBuffer, CL_TRUE, 0, sizeof(int) * NUM_ELEMENTS, output, 0, NULL, NULL);// 打印结果for (int i = 0; i < NUM_ELEMENTS; i++) {std::cout << "Output[" << i << "] = " << output[i] << std::endl;}// 释放资源clReleaseMemObject(inputBuffer);clReleaseMemObject(outputBuffer);clReleaseKernel(kernel);clReleaseKernel(kernel2);clReleaseProgram(program);clReleaseCommandQueue(queue);clReleaseContext(context);return 0;
}

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

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

相关文章

Android AGP版本

做个记录&#xff1a; Android AGP版本 https://developer.android.com/studio/releases/gradle-plugin?hlzh-cn

Android动态可编辑长度列表

概述 在界面实现一个列表&#xff0c;用户可以随意给列表新增或者删除项目&#xff0c;在开发中比较常用&#xff0c;但是真正做起来又有点花时间&#xff0c;今天花时间做一个&#xff0c;以便在以后的开发中用到。 详细 运行效果&#xff1a; 二、实现思路&#xff1a; 1…

官方推荐使用的OkHttp4网络请求库全面解析(Android篇)

作者&#xff1a;cofbro 前言 现在谈起网络请求&#xff0c;大家肯定下意识想到的就是 okhttp 或者 retrofit 这样的三方请求库。诚然&#xff0c;现在有越来越多的三方库帮助着我们快速开发&#xff0c;但是对于现在的程序员来说&#xff0c;我们不仅要学会如何去用&#xff…

MMSegmentation训练自己的语义分割数据集

全流程&#xff0c;训练语义分割数据集 数据标注json转mask 运行源码MMSegmentation模型选择运行部分 数据标注 # 安装 pip install labelme # 启动labelme labelme然后 ctrl N 开启多边形标注即可&#xff0c;命名类为person 之后会保存到同目录下json文件&#xff1a; js…

【YOLOV5】YOLOV5添加SPPCSPC

当前YOLOV5版本为7.0 第一步 在models/common.py添加SPPCSPC class SPPCSPC(nn.Module):# CSP https://github.com/WongKinYiu/CrossStagePartialNetworksdef __init__(self, c1, c2, n1, shortcutFalse, g1, e0.5, k(5, 9, 13)):super(SPPCSPC, self).__init__()c_ int(2 *…

java.lang.classnotfoundexception: com.android.tools.lint.client.api.vendor

Unity Android studio打包报错修复 解决方式 java.lang.classnotfoundexception: com.android.tools.lint.client.api.vendor 解决方式 在 launcherTemplate 目录下找到 Android/lintOptions 选项 加上 checkReleaseBuilds false lintOptions { abortOnError false checkRelea…

Spring Bean 生命周期顺序验证

看到一篇写的很好的 Spring Bean 生命周期的博客&#xff1a;一文读懂 Spring Bean 的生命周期&#xff0c;在此写个简单的 Bean 进行验证。 1. 创建Springboot项目 基于 springboot 的2.1.8.RELEASE 创建一个简单项目&#xff0c;只添加 spring-aop 包以引入spring依赖。 &…

Redis下载和安装(Windows系统)

文章目录 创建Redis临时服务1) 启动服务端程序2) 启动客户端程序命令创建Redis服务3) 启动Redis客户端4) 检查是否连接成功 为便于大多数读者学习本套教程&#xff0c;教程中采用 Windows 系统对 Redis 数据库进行讲解。虽然 Redis 官方网站没有提供 Windows 版的安装包&#x…

进程间通信

一、进程间通信&#xff08;interprocess communication&#xff0c;简称 IPC&#xff09;指两个进程之间的通信。 系统中每个进程都有自己的地址空间&#xff0c;并且相互独立、隔离&#xff0c;每个进程都处于自己的地址空间中。 二、通信机制 Linux 内核提供了多种 IPC 机制…

无涯教程-Android - List View函数

Android ListView 是垂直滚动列表中显示的视图&#xff0c;使用 Adapter 从列表(如数组或数据库)中获取内容的列表项会自动插入列表中。 适配器(Adapter)实际上是UI组件和将数据填充到UI组件中的数据源之间的桥梁&#xff0c;适配器保存数据并将数据发送到适配器视图&#xff0…

WordPress(3)会员插件安装

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、服务器中上传插件二、使用步骤1.启动插件前言 提示:会员插件的安装不能在网站后台插件中心中直接安装原因我还没有排查 原因:会导致网站停止运行 一、服务器中上传插件 二、使用步骤 …

Python钢筋混凝土结构计算.pdf-混凝土强度设计值

计算原理&#xff1a; 需要注意的是&#xff0c;根据不同的规范和设计要求&#xff0c;上述公式可能会有所差异。因此&#xff0c;在进行混凝土强度设计值的计算时&#xff0c;请参考相应的规范和设计手册&#xff0c;以确保计算结果的准确性和合规性。 代码实现&#xff1a; …

el-select 使用

案例&#xff1a; /* * label : 界面上展示的是哪个字段,我这里需要展示名称 * value : 绑定的字段&#xff0c;一般是id */<el-selectv-model"Form.BillNumber"placeholder"请选择"change"changeValue($event)"><el-optionv-for"…

ThePASS研究院|以Safe为例,解码DAO国库管理

本研究文章由ThePASS团队呈现。ThePASS是一家开创性的DAO聚合器和搜索引擎&#xff0c;在为DAO提供洞察力和分析方面发挥着关键作用。 Intro 随着去中心化自治组织&#xff08;DAOs&#xff09;的发展&#xff0c;它们被赋予了越来越多的角色和期望。在这种巨幅增长的背景下&…

ToBeWritten之VSOC安全运营

也许每个人出生的时候都以为这世界都是为他一个人而存在的&#xff0c;当他发现自己错的时候&#xff0c;他便开始长大 少走了弯路&#xff0c;也就错过了风景&#xff0c;无论如何&#xff0c;感谢经历 转移发布平台通知&#xff1a;将不再在CSDN博客发布新文章&#xff0c;敬…

论文阅读_医疗知识图谱_GraphCare

英文名称: GraphCare: Enhancing Healthcare Predictions with Open-World Personalized Knowledge Graphs 中文名称: GraphCare&#xff1a;通过开放世界的个性化知识图增强医疗保健预测 文章: http://arxiv.org/abs/2305.12788 代码: https://github.com/pat-jj/GraphCare 作…

Mac版JFormDesigner IDEA插件安装(非商业用途)

前言 仅供个人开发者使用&#xff0c;勿用作商业用途。 仅供个人开发者使用&#xff0c;勿用作商业用途。 仅供个人开发者使用&#xff0c;勿用作商业用途。 感觉做了这些年开发&#xff0c;怎么感觉市场越搞越回去了。桌面应用又成主流了&#xff1f; 甲方让做桌面客户端&am…

搭建个人备忘录中心服务memos、轻量级笔记服务

目录 一、源码 二、官网 三、搭建 四、使用 一、源码 GitHub - usememos/memos: A privacy-first, lightweight note-taking service. Easily capture and share your great thoughts. 二、官网 memos - Easily capture and share your great thoughts 三、搭建 docke…

Python Pyecharts 制图

基本图表 - pyecharts - A Python Echarts Plotting Library built with love. from pyecharts import options as opts from pyecharts.charts import Pie from pyecharts.faker import Fakerc (Pie().add("",[list(z) for z in zip(["7室1厅", "5…

MindsDB为许多不支持内置机器学习的数据库带来了机器学习功能

选择平台的首要原则是“靠近数据”,让代码靠近数据是保持低延迟的必要条件。 机器学习,特别是深度学习往往会多次遍历所有数据(遍历一次被称为一个epoch)。对于非常大的数据集来说,理想的情况是在存储数据的地方建立模型,这样就不需要大量的数据传输。目前已经有部分数据…