opencl学习(一)

OpenCL中kernel设置的序号关系 发起kernel运算的API: cl_int enqueueNDRangeKernel( const Kernel& kernel, const NDRange& offset, const NDRange& global, const NDRange& local = NullRange, const VECTOR_CLASS<Event>* events = NULL, Event* event = NULL) 我们会设置数据数组的核心参数: 阅读详情
AI摘要

该博客演示了一个使用OpenCL进行数据并行计算的例子,包括获取平台和设备信息、创建上下文、命令队列、缓冲区,加载内核源代码,执行内核以及读取结果。程序涉及一维和二维NDRangeKernel的调用,解释了get_global_id的作用,展示了如何将主机数据传输到设备并执行计算,最后显示了计算结果。

  • 细分了流程,并注释了相应函数
  • 对get_global_id的理解:如果clEnqueueNDRangeKernel设置的是一维且global_item_size = 9,那么get_global_id(0)返回0到8,对应9个work-group。如果clEnqueueNDRangeKernel设置的是二维且global_item_size[2] = {9, 8},那么get_global_id(0)和get_global_id(1)的结果是(0,j)(1,j)(2,j)(3,j)(4,j)(5,j)(6,j)(7,j)(8,j),其中j是0到7且顺序不定。
  • 主机程序,注意kernel.cl的路径
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <CL/cl.h>
#include <time.h>
 
#define MAX_SOURCE_SIZE (0x100000)
//data parallel
int main()
{ 
	int i, j;
	float *A;
	float *B;
	float *C;
	const int row = 9, col = 8;
 
	A = (float *)malloc(row * col * sizeof(float));
	B = (float *)malloc(row * col * sizeof(float));
	C = (float *)malloc(row * col * sizeof(float));
 
	/* Initialize input data */
	printf("Initialize input data");
	for (i = 0; i < row; i++) {
		for (j = 0; j < col; j++) {
			A[i * col + j] = i + j;
			B[i * col + j] = i + j + 1;
		}
	}
	printf("\n");
 
	printf("A array data:\n");
	for (i = 0; i < row; i++) {
		for (int j=0; j<col; j++){
		printf("%.2f\t",A[i*col+j]);	
		}
		printf("\n");
	}
 
	printf("B array data:\n");
	for (i = 0; i < row; i++) {
		for (int j=0; j<col; j++){
		printf("%.2f\t",B[i*col+j]);	
		}
		printf("\n");
	}
 
	clock_t start, finish;
	double  duration;
	printf("DataParallel kernels start to execute\n");
	start = clock();
    
    cl_int ret;
	/* 1.Get Platform Information */
	cl_platform_id platform_id = NULL;
	cl_uint ret_num_platforms;
	// 查询的最大数量,返回的平台列表,实际平台数
	ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms);

	/* 2.Device Information */
	cl_device_id device_id = NULL;
	cl_uint ret_num_devices;
	// 平台列表,查询的设备类型,查询的最大数量,返回的设备列表,实际设备数
	ret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU, 1, &device_id, &ret_num_devices);

	/* 3.Create OpenCL Context */
	cl_context context = NULL;
	// properties,设备数,设备列表,pfn_notify,user_data,返回码
	context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret);

	/* 4.Create command queue */
	cl_command_queue command_queue = NULL;
	// context,device_id,properties,返回码
	command_queue = clCreateCommandQueue(context, device_id, 0, &ret);

	/* 5.Create Buffer Object */
	cl_mem Amobj = NULL;
	cl_mem Bmobj = NULL;
	cl_mem Cmobj = NULL;
	// context,flag,大小,host指针,返回码
	Amobj = clCreateBuffer(context, CL_MEM_READ_WRITE, row * col * sizeof(float), NULL, &ret);
	Bmobj = clCreateBuffer(context, CL_MEM_READ_WRITE, row * col * sizeof(float), NULL, &ret);
	Cmobj = clCreateBuffer(context, CL_MEM_READ_WRITE, row * col * sizeof(float), NULL, &ret);

	/* 6.Copy input data to the memory buffer */
	// command_queue,buffer,是否阻塞,偏移,大小,主机数据,等待事件数,等待事件列表,事件命令
	ret = clEnqueueWriteBuffer(command_queue, Amobj, CL_TRUE, 0, row * col * sizeof(float), A, 0, NULL, NULL);
	ret = clEnqueueWriteBuffer(command_queue, Bmobj, CL_TRUE, 0, row * col * sizeof(float), B, 0, NULL, NULL);

	/* 7.Load kernel source file */
	FILE *fp;
	const char fileName[] = "../src/kernel.cl";
	size_t source_size;
	char *source_str;
	fp = fopen(fileName, "r");
	if (!fp) {
		fprintf(stderr, "Failed to load kernel.cl");
		exit(1);
	}
	source_str = (char *)malloc(MAX_SOURCE_SIZE);
	source_size = fread(source_str, 1, MAX_SOURCE_SIZE, fp);
	fclose(fp);

	/* 8.Create kernel program from source file*/
	cl_program program = NULL;
	// context,count,kernel代码,代码长度,返回码
	program = clCreateProgramWithSource(context, 1, (const char **)&source_str, (const size_t *)&source_size, &ret);

	/*  9. build program*/
	// program,设备数,device_id,options,pfn_notify,user_data
	ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);

	/* 10.Create data parallel OpenCL kernel */
	cl_kernel kernel = NULL;
	// program, 名字, 返回码
	kernel = clCreateKernel(program, "dataParallel", &ret);

	/* 11.Set OpenCL kernel arguments */
	// kernel, 参数索引,参数大小,参数
	ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&Amobj);
	ret = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&Bmobj);
	ret = clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&Cmobj);
	
	/* 12.Execute OpenCL kernel as data parallel */
	size_t global_item_size = 9;
	size_t local_item_size = 1;
	// command_queue,kernel,数据维度,global_work_offset,global_item_size,local_item_size,等待事件数,等待事件列表,事件命令
	ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_item_size, &local_item_size, 0, NULL, NULL);
	// 2D clEnqueueNDRangeKernel
	// size_t global_item_size[2] = {9, 8};
	// ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, global_item_size, NULL, 0, NULL, NULL);

	/* 13.wait for the commands to complete before reading back results */
	ret = clFlush(command_queue);
	ret = clFinish(command_queue);
 
	/* 14.Transfer result to host */
	// command_queue,buffer,是否阻塞,偏移,大小,主机数据,等待事件数,等待事件列表,事件命令
	ret = clEnqueueReadBuffer(command_queue, Cmobj, CL_TRUE, 0, row * col * sizeof(float), C, 0, NULL, NULL);
	// cost
	finish = clock();
	duration = (double)(finish - start) / CLOCKS_PER_SEC;
	printf("cost : %f seconds\n", duration);
	/* Display Results */
	printf("Calculation result:\n");
	for (i = 0; i < row; i++) {
		for (j = 0; j < col; j++) {
			printf("%7.2f\t", C[i * col + j]);
		}
		printf("\n");
	}
 
 
	/* 15.Finalization */
	ret = clReleaseKernel(kernel);
	ret = clReleaseProgram(program);
	ret = clReleaseMemObject(Amobj);
	ret = clReleaseMemObject(Bmobj);
	ret = clReleaseMemObject(Cmobj);
	ret = clReleaseCommandQueue(command_queue);
	ret = clReleaseContext(context);
 
	free(source_str);
 
	free(A);
	free(B);
	free(C);
	return 0;
 }
  • kernel.cl
__kernel void dataParallel(__global float* A, __global float* B, __global float* C)
{
	int i = 8*get_global_id(0);
	printf("%d\n", i);
	C[i+0] = A[i+0] + B[i+0];
	C[i+1] = A[i+1] - B[i+1];
	C[i+2] = A[i+2] * B[i+2];
	C[i+3] = A[i+3] / B[i+3];
	C[i+4] = A[i+4];
	C[i+5] = B[i+5];
}
opencl 基础:如何编译核函数 CUDA和OpenCL类似,都是异构并行计算系统。系统中有一台主机和一个或多个计算设备。关于计算设备,CUDA中叫做多喝流处理器(SM),而OpenCL中叫做计算单元(CU)。另外,在OpenCL中一个CU在CPU中相当于CPU的一个内核。get_global_id是OpenCL编程语言中的一个内置函数,用于在OpenCL内核(kernel)中获取当前工作项在全球工作空间中的唯一标识符(ID)。这个标识符通常是多维的,对应于内核执行时定义的全局工作项的索引。 阅读详情

相关推荐

OpenCL C 内核(Kernel)

函数用途说明创建程序从源代码创建程序对象创建程序从二进制创建程序对象编译程序编译程序源代码创建内核创建特定的内核对象创建所有内核创建程序中的所有内核设置参数设置内核参数值执行内核在设备上执行内核。

深之JohnChen的专栏 1578

getGlobalId与getGlobalSize等参数释义

最近在《OpenCL异构计算》这本书(《Heterogeneous computing with OpenCL》翻译而来)上看到有一部分解释这些异构常用字段方法的含义,加上个人理解,希望可以帮助“码友”快速理解。 get_work_dim     返回线程调度的维度数;(个人理解)表示NDRange的维度数。 get_global_size     返回所请求维度上work-item的总数...

Fortuna_i的博客 5023

OpenCL简介-----OpenCL学习(一)

OpenCL (Open Computing Language,开放计算机语言)是一个为异构平台编写程序的框架,此异构平台可由CPU,GPU或其他类型的处理器组成。OpenCL由一门用于编写kernels(在OpenCL设备上运行的函数)的语言(基于C99)和一组用于定义并控制平台的API组成。OpenCL提供了基于任务分区和数据分区的并行计算机制。

XianBT的专栏 6825

自写代码来理解 get_global_id 和 get_global_size

《OpenCL编程指南》读书笔记,第三章,用 C++ 重写 kernel 函数,理解 get_global_id 和 get_global_size

ftuc5dn的博客 940

从零开始安装pytorch(包含GPU和CPU版本的安装)

Pytorch是。

qiaoxinyu1989的博客 8万+

Windows下Colmap编译安装全攻略:从Boost到CUDA的避坑指南

本文详细介绍了在Windows系统下编译安装Colmap三维重建工具的完整流程与实战经验。针对Boost库版本兼容性、CUDA与Visual Studio的版本匹配等常见难题提供了具体的避坑指南和解决方案,帮助开发者高效完成从环境配置到最终部署的全过程。

weixin_28235513的博客 198

OpenCL学习(一)

OpenCL已经听说很久了,但是一直也没有机会学,现在机会终于来了。 因为效率问题,之前的所有算法都是放到GPU上跑的,现在需要添加一个multiband算法,结果麻烦大了,我整理的multiband算法代码全是按照cpu计算的思想写的,由于对于gpu运算的概念比较少,只能临时抱佛脚了。 入手肯定是找个最熟悉的开始,什么最熟悉?肯定是OpenCV啦。什么,OpenCV里自带Opencl的相关东

bcfd_yundou的博客 931

【实战解析】RTL8306MB交换芯片驱动开发中的RMII接口调试陷阱

本文通过一个RTL8306MB交换芯片驱动开发的实战案例,深入剖析了RMII接口调试中的经典陷阱。文章详细描述了因TX_EN与CRS_DV信号线交叉连接错误导致的“静默”故障,并分享了使用逻辑分析仪和示波器进行硬件排查的完整流程与核心技巧,为嵌入式网络驱动开发提供了宝贵的避坑指南。

weixin_29267307的博客 421

OpenCL学习笔记一

什么是OpenCL 百度百科飞机票✈ OpenCL是一个为异构平台编写程序的框架,此异构平台可由CPU,GPU或其他类型的处理器组成。OpenCL由一门用于编写kernels (在OpenCL设备上运行的函数)的语言(基于C99)和一组用于定义并控制平台的API组成。OpenCL提供了基于任务分割和数据分割的并行计算机制。 上面是官方的一些解释,大体上是指用于编写运行在异构平台上的程序的一种框架,由特定的数据类型,数据结构,和一些API组成接口组成,说实话,我个人觉得它并不是一门语言,其实就是在C/C++的

恍恍惚惚的大穷猫的博客 440

从勒索软件攻击到数据重生:SQL Server MDF文件修复的实战生存指南

本文详细介绍了SQL Server MDF文件在遭遇勒索软件攻击后的修复策略,重点解析了Recovery Toolbox工具链的应用流程。从灾难评估到数据验证,提供分阶段修复操作、高级修复技术及防御加固方案,帮助企业快速恢复数据库并提升安全防护能力。

weixin_28327051的博客 715

气象干旱触发水文(农业)干旱的概率及其触发阈值的动态变化-贝叶斯copula模型

本文通过建立不同类型干旱传播过程的触发阈值模型,解析了在不同等级气象干旱胁迫下诱发次一级干旱类型的触发阈值。通过贝叶斯概率模型,我们推导了气象干旱与水文干旱、农业干旱、地下水干旱之间的条件概率关系,进一步明确了气象干旱引发水文干旱、农业干旱和地下水干旱的概率及其触发阈值。该模型有效揭示了气象干旱对各级干旱类型的传播机制及其动态变化,为干旱预警系统的建立和水资源管理提供了理论依据和技术支持。

frankgis的博客 2502

从零开始学习OpenCL开发(一)架构

多谢大家关注 转载本文请注明:http://blog.youkuaiyun.com/leonwei/article/details/8880012   本文将作为我《从零开始做OpenCL开发》系列文章的第一篇。   1 异构计算、GPGPU与OpenCL   OpenCL是当前一个通用的由很多公司和组织共同发起的多CPU\GPU\其他芯片 异构计算(heterogeneous)的标准,它是跨平台的

leon 12万+

Python爬虫实战:美团商家数据采集系统

本文将详细介绍如何使用Python最新技术栈构建高效的美团商家信息采集系统。内容涵盖异步爬虫、反爬对抗、数据存储、可视化分析等完整流程,提供可落地的代码方案和工程实践。

2201_76125261的博客 2658

OpenCL学习(一)——Windows平台下搭建核显的OpenCL运行环境

入坑OpenCL一周左右,万事开头难,但是发现后面的学习也不容易。。 通过设备管理器查看到自己的电脑配置的是Intel核显HD530,以下是自己搭建OpenCL运行环境的流程。 1)下载并安装Intel的SDK forOpenCL 打开网址https://software.intel.com/en-us/opencl-sdk/choose-download,选择SDKfor OpenCL...

On my way 7390

电子科技大学计算机预推免(最终去向)

电子科技大学,预推免报名时必须要有一封本校老师写的推荐信,推荐信基本上就是复试的入场券,所以一定要提前联系老师,拿到推荐信。只要有机会进了面试,我觉得老师对于双非并不歧视,面试的个人表现才是关键性决定因素,技巧性也是很强的,如果有需要帮助的,欢迎私信~~

D1379951481的博客 3366

C# Socket通信从入门到精通(14)——多个异步UDP客户端C#代码实现(史上最全)

本文详细介绍了Socket通信中多个异步Udp客户端功能的实现、介绍如何使用多个客户端与多个服务器进行数据的交互,包含连接服务器、断开服务器、发送数据、读取数据、C#代码实现,由高级工程师多年经验总结而成,绝对干货!

qq_34059233的博客 1982

OpenCL-学习教程(一)

最近因项目需要跨平台做算法的加速优化,需要使用opencl来做,所以准备将opencl的东西学习一遍,学习的目的在于使用,达到通用的水平,暂时不做实现硬件的最大化水平。之前做过一些Nivida的Cuda开发,现在做opencl的开发虽然有些差别,但整体变换不大,硬件层逻辑相同,主机代码环境配置模块有所不同。先放一张opencl处理的流程图: 从流程上我们可以看出,主要处理...

Bryan_Zhang的专栏 1967

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

OpenCL学习笔记(一)

今天看些了入门的东西,对opencl四个模型:平台模型、执行模型、内存模型、程序模型。一知半解,不做评论,只是记录。 建立一个opencl程序,一般有一下六步: 1.查询并选择一个平台; 2.查询设备; 3.建立一个上下文; 4.建立一个命令序列; 5.读/写设备; 6.执行内核. 其中前三步是平台层,后三者为执行层。

噌胥苑——行思驿站 2082

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

学习OpenCL开发(一)架构

转自:http://blog.youkuaiyun.com/leonwei/article/details/8880012   本文将作为我《从零开始做OpenCL开发》系列文章的第一篇。   1 异构计算、GPGPU与OpenCL   OpenCL是当前一个通用的由很多公司和组织共同发起的多CPU\GPU\其他芯片 异构计算(heterogeneous)的标准,它是跨平台的。旨在充分利用GPU强大

Cafe 370

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

OPENCL学习(一):获取平台和设备信息

OPENCL获取平台和版本信息 CL_PLATFORM_VERSION 返回所能支持最大openCL版本; CL_PLATFORM_PROFILE 确认平台是支持完全版还是嵌入式版本的openCL CL_PLATFORM_EXTENSIONS 返回平台所支持的扩展,每个openCL扩展都定义了一部分超出标准的内容,一旦该扩展被openCL工作组认可,则名字由cl_khr_开头。 #include <CL/cl.h> #include <stdio.h> #include <st

BV12345的博客 6254
上一篇: 行优先和列优先的循环写法
下一篇: opencl学习(二)
刀么克瑟拉莫
博客等级 码龄14年 68粉丝 268原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

刀么克瑟拉莫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值