OpenCL矢量加法例子

news2024/9/21 18:54:24

1.向量加内核函数

__kernel void vector_add(__global float* A, __global float* B, __global float* C) {
    int id = get_global_id(0);
    C[id] = A[id] + B[id];
}

2.向量加主程序

#include<stdio.h>
#include<stdlib.h>
#ifdef _APPLE_
#include<OpenCL/cl.h>
#else
#include<CL/cl.h>
#endif

#pragma warning( disable : 4996 )

const int ARRAY_SIZE = 1000;

char* ReadKernelSourceFile(const char* filename, size_t* length)
{
	FILE* file = NULL;
	size_t sourceLength;
	char* sourceString;
	int ret;
	file = fopen(filename, "rb");
	if (file == NULL)
	{
		printf("%s at %d :Can't open source file %s.\n", filename);
		return NULL;
	}
	fseek(file, 0, SEEK_END);
	sourceLength = ftell(file);
	fseek(file, 0, SEEK_SET);
	sourceString = (char*)malloc(sourceLength + 1);
	sourceString[0] = '\0';
	ret = fread(sourceString, sourceLength, 1, file);
	if (ret == 0)
	{
		printf("Can't read source %s.\n", filename);
		return NULL;
	}
	fclose(file);
	if (length != 0)
	{
		*length = sourceLength;
	}
	sourceString[sourceLength] = '\0';
	return sourceString;
}
/*
1.创建平台
2.创建设备
3.根据设备创建上下文
*/
cl_context CreateContext(cl_device_id* device)
{
	cl_int errNum;
	cl_uint numPlatforms;
	cl_platform_id firstPlatformId;
	cl_context context = NULL;
	errNum = clGetPlatformIDs(1, &firstPlatformId, &numPlatforms);
	if (errNum != CL_SUCCESS || numPlatforms <= 0)
	{
		printf("Failed to find any OpenCL platforms.");
		return NULL;
	}
	else
	{
		//打印平台信息
		size_t size;

		// get name
		errNum = clGetPlatformInfo(firstPlatformId, CL_PLATFORM_NAME, 0, NULL, &size);
		char* name = (char*)malloc(size);
		errNum = clGetPlatformInfo(firstPlatformId, CL_PLATFORM_NAME, size, name, NULL);
		printf("CL_PLATFORM_NAME:%s\n", name);

		// vendor
		errNum = clGetPlatformInfo(firstPlatformId, CL_PLATFORM_VENDOR, 0, NULL, &size);
		char* vendor = (char*)malloc(size);
		errNum = clGetPlatformInfo(firstPlatformId, CL_PLATFORM_VENDOR, size, vendor, NULL);
		printf("CL_PLATFORM_VENDOR:%s\n", vendor);

		// version
		errNum = clGetPlatformInfo(firstPlatformId, CL_PLATFORM_VERSION, 0, NULL, &size);
		char* version = (char*)malloc(size);
		errNum = clGetPlatformInfo(firstPlatformId, CL_PLATFORM_VERSION, size, version, NULL);
		printf("CL_PLATFORM_VERSION:%s\n", version);

		// profile
		errNum = clGetPlatformInfo(firstPlatformId, CL_PLATFORM_PROFILE, 0, NULL, &size);
		char* profile = (char*)malloc(size);
		errNum = clGetPlatformInfo(firstPlatformId, CL_PLATFORM_PROFILE, size, profile, NULL);
		printf("CL_PLATFORM_PROFILE:%s\n", profile);

		// extensions
		errNum = clGetPlatformInfo(firstPlatformId, CL_PLATFORM_EXTENSIONS, 0, NULL, &size);
		char* extensions = (char*)malloc(size);
		errNum = clGetPlatformInfo(firstPlatformId, CL_PLATFORM_EXTENSIONS, size, extensions, NULL);
		printf("CL_PLATFORM_EXTENSIONS:%s\n", extensions);
	}

	errNum = clGetDeviceIDs(firstPlatformId, CL_DEVICE_TYPE_GPU, 1, device, NULL);
	if (errNum != CL_SUCCESS)
	{
		printf("There is no GPU, trying CPU...");
		errNum = clGetDeviceIDs(firstPlatformId, CL_DEVICE_TYPE_CPU, 1, device, NULL);
	}
	if (errNum != CL_SUCCESS)
	{
		printf("There is NO GPU or CPU");
		return NULL;
	}
	else
	{
		//打印设备信息
		size_t valueSize;
		char* value;
		clGetDeviceInfo(*device, CL_DEVICE_NAME, 0, NULL, &valueSize);
		value = (char*)malloc(valueSize);
		clGetDeviceInfo(*device, CL_DEVICE_NAME, valueSize, value, NULL);
		printf("Device Name: %s\n", value);
		free(value);
	}


	context = clCreateContext(NULL, 1, device, NULL, NULL, &errNum);
	if (errNum != CL_SUCCESS)
	{
		printf(" create context error\n");
		return NULL;
	}
	return context;
}

/*
@在上下文可用的第一个设备中创建命令队列
*/
cl_command_queue CreateCommandQueue(cl_context context,
	cl_device_id device)
{
	cl_int errNum;
	cl_command_queue commandQueue = NULL;
	commandQueue = clCreateCommandQueue(context, device, 0, NULL);
	if (commandQueue == NULL)
	{
		printf("Failed to create commandQueue for device 0");
		return NULL;
	}
	return commandQueue;
}
/*
@读取内核源码创建OpenCL程序
*/
cl_program CreateProgram(cl_context context,
	cl_device_id device,
	const char* fileName)
{
	cl_int errNum;
	cl_program program;
	size_t program_length;
	char* const source = ReadKernelSourceFile(fileName,
		&program_length);
	program = clCreateProgramWithSource(context, 1,
		(const char**)&source,
		NULL, NULL);
	if (program == NULL)
	{
		printf("Failed to create CL program from source.");
		return NULL;
	}
	errNum = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
	if (errNum != CL_SUCCESS)
	{
		char buildLog[16384];
		clGetProgramBuildInfo(program, device,
			CL_PROGRAM_BUILD_LOG,
			sizeof(buildLog),
			buildLog, NULL);
		printf("Error in kernel:%s ", buildLog);
		clReleaseProgram(program);
		return NULL;
	}
	return program;
}
/*
@创建内存对象
*/
bool CreateMemObjects(cl_context context, cl_mem memObjects[3],
	float* a, float* b)
{
	memObjects[0] = clCreateBuffer(context,
		CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
		sizeof(float) * ARRAY_SIZE, a, NULL);
	memObjects[1] = clCreateBuffer(context,
		CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
		sizeof(float) * ARRAY_SIZE, b, NULL);
	memObjects[2] = clCreateBuffer(context, CL_MEM_READ_WRITE,
		sizeof(float) * ARRAY_SIZE, NULL, NULL);
	if (memObjects[0] == NULL || memObjects[1] == NULL
		|| memObjects[2] == NULL)
	{
		printf("Error creating memory objects.");
		return false;
	}
	return true;
}
/*
@清除OpenCL资源
*/
void Cleanup(cl_context context, cl_command_queue commandQueue,
	cl_program program, cl_kernel kernel,
	cl_mem memObjects[3])
{
	for (int i = 0; i < 3; i++)
	{
		if (memObjects[i] != 0)
			clReleaseMemObject(memObjects[i]);
	}
	if (commandQueue != 0)
		clReleaseCommandQueue(commandQueue);
	if (kernel != 0)
		clReleaseKernel(kernel);
	if (program != 0)
		clReleaseProgram(program);
	if (context != 0)
		clReleaseContext(context);
}
int main(int argc, char** argv)
{
	cl_context context = 0;
	cl_command_queue commandQueue = 0;
	cl_program program = 0;
	cl_device_id device = 0;
	cl_kernel kernel = 0;
	cl_mem memObjects[3] = { 0, 0, 0 };
	cl_int errNum;

	//1.平台层:查询平台、设备,根据设备创建OpenCL上下文
	context = CreateContext(&device);
	if (context == NULL)
	{
		printf("Failed to create OpenCL context.");
		return 1;
	}

	//2.运行时:获得OpenCL设备,并创建命令队列
	commandQueue = CreateCommandQueue(context, device);
	if (commandQueue == NULL)
	{
		Cleanup(context, commandQueue, program, kernel,
			memObjects);
		return 1;
	}

	//创建OPenCL程序
	program = CreateProgram(context, device, "vecAdd.cl");
	if (program == NULL)
	{
		Cleanup(context, commandQueue, program,
			kernel, memObjects);
		return 1;
	}
	//创建OpenCL内核
	kernel = clCreateKernel(program, "vector_add", NULL);
	if (kernel == NULL)
	{
		printf("Failed to create kernel");
		Cleanup(context, commandQueue, program,
			kernel, memObjects);
		return 1;
	}
	//创建OpenCL内存对象
	float result[ARRAY_SIZE];
	float a[ARRAY_SIZE];
	float b[ARRAY_SIZE];
	for (int i = 0; i < ARRAY_SIZE; i++)
	{
		a[i] = (float)(i + 1);
		b[i] = (float)(i + 1);
	}
	if (!CreateMemObjects(context, memObjects, a, b))
	{
		Cleanup(context, commandQueue, program,
			kernel, memObjects);
		return 1;
	}
	//设置内核参数
	errNum = clSetKernelArg(kernel, 0, sizeof(cl_mem), &memObjects[0]);
	errNum |= clSetKernelArg(kernel, 1, sizeof(cl_mem),
		&memObjects[1]);
	errNum |= clSetKernelArg(kernel, 2, sizeof(cl_mem),
		&memObjects[2]);
	if (errNum != CL_SUCCESS)
	{
		printf("Error setting kernel arguments.");
		Cleanup(context, commandQueue, program,
			kernel, memObjects);
		return 1;
	}
	size_t globalWorkSize[1] = { ARRAY_SIZE };
	size_t localWorkSize[1] = { 1 };

	//执行内核
	errNum = clEnqueueNDRangeKernel(commandQueue, kernel,
		1, NULL,
		globalWorkSize,
		localWorkSize, 0, NULL,
		NULL);
	if (errNum != CL_SUCCESS)
	{
		printf("Error queuing kernel for execution.");
		Cleanup(context, commandQueue, program, kernel,
			memObjects);
		return 1;
	}

	//计算结果拷贝回主机
	errNum = clEnqueueReadBuffer(commandQueue, memObjects[2],
		CL_TRUE, 0,
		ARRAY_SIZE * sizeof(float),
		result, 0, NULL, NULL);
	if (errNum != CL_SUCCESS)
	{
		printf("Error reading result buffer.");
		Cleanup(context, commandQueue, program, kernel,
			memObjects);
		return 1;
	}
	for (int i = 0; i < ARRAY_SIZE; i++)
	{
		printf("i=%d:%f\n", i, result[i]);
	}
	printf("Executed program succesfully.");
	Cleanup(context, commandQueue, program, kernel, memObjects);
	return 0;
}

3.运行结果
在这里插入图片描述

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

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

相关文章

通过DBeaver 给Postgre SQL表 设置主键自增

1.创建表 CREATE TABLE public.company ( id int4 NOT NULL , name text NOT NULL, age int4 NOT NULL, address bpchar(50) NULL, salary float4 NULL, join_date date NULL, CONSTRAINT company_pkey PRIMARY KEY (id) ); 2.插入数据&#xff08;不传入id&#xff…

探索高效的HTTP异步接口测试方法:从轮询等待到自动化方案

本文将深入探讨HTTP异步接口测试的多个方面&#xff0c;包括轮询等待、性能测试以及自动化方案。通过详细的解释和实际案例&#xff0c;帮助您了解如何有效地测试异步接口&#xff0c;确保系统的稳定性和性能。 在现代软件开发中&#xff0c;HTTP异步接口扮演着至关重要的角色&…

电子电路学习笔记之SA1117BH-1.2TR——LDO低压差线性稳压器

关于LDO调节器&#xff08;Low Dropout Regulator&#xff09;是一种电压稳压器件&#xff0c;常用于电子设备中&#xff0c;用于将高电压转换为稳定的低电压。它能够在输入电压和输出电压之间产生较小的差异电压&#xff0c;因此被称为"低压差稳压器"。 LDO调节器通…

PHP自己的框架自定义错误器set_error_handler和register_shutdown_function(完善篇五)

1、PHP自己的框架实现错误显示和记录日志 2、运行时错误set_error_handler和致命错误register_shutdown_function KJ.php public static function run(){//定义常量self::_set_const();//创建模块目录self::_mk_module();//加载文件self::_import_file();self::_set_system();s…

安卓机显示屏的硬件结构

显示屏的硬件结构 显示屏的硬件结构主要由背光源、液晶面板和驱动电路构成。可以将液晶面板看成一个三明治的结构&#xff0c;即在两片偏振方向互相垂直的偏光片系统中夹着一层液晶层。自然光源通过起偏器&#xff08;偏光片之一&#xff09;后&#xff0c;变成了垂直方向的偏…

短视频矩阵seo关键词霸屏开发源码逻辑

目录 ​编辑 一、短视频矩阵系统seo是如何从开发上实现的 二、短视频SEO矩阵系统源码开发&#xff0c;需要遵循一下步骤&#xff1a; 三、矩阵开发源码&#xff0c;功能开发&#xff0c;代码展示如下&#xff1a; 一、短视频矩阵系统seo是如何从开发上实现的 短视频矩阵系…

陕西广电 HG6341C FiberHome烽火 光猫获取超级密码 改桥接模式 提升网速

光猫默认的路由模式实测在100M宽带下只能跑到60M左右&#xff0c;只有改成桥接模式才能跑满&#xff0c;不损失性能。但是改桥接需要给运营商打电话&#xff0c;有的时候不想麻烦他们&#xff0c;这时获取超级密码进行更改就是一个不错的选择了 分析 之前写了一篇HGU B2 光猫的…

微服务流程引擎:简单又灵活,实现流程全生命周期管理!

伴随着日益激烈的市场竞争&#xff0c;传统的办公操作已经无法满足发展需要了。如果采用微服务流程引擎加油助力&#xff0c;就可以帮助企业更好地管理数据资源&#xff0c;高效做好各种表单制作&#xff0c;实现高效率办公。流辰信息以市场为导向&#xff0c;用心钻研低代码技…

二、5.单线程与多线程调度

任务轮转工作由任务调度器来完成的&#xff0c;任务调度器就是操作系统中用于把任务轮流调度上处理器运行的一个软件模块&#xff0c;它是操作系统的一部分。调度器在内核中维护一个任务表&#xff08;也称进程表、线程表或调度表&#xff09;&#xff0c;然后按照一定的算法&a…

2022年03月 C/C++(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题&#xff1a;和数 给定一个正整数序列&#xff0c;判断其中有多少个数&#xff0c;等于数列中其他两个数的和。 比如&#xff0c;对于数列1 2 3 4, 这个问题的答案就是2, 因为3 2 1, 4 1 3。 时间限制&#xff1a;10000 内存限制&#xff1a;65536 输入 共两行&#x…

Lucky player —— Java 项目(Spring Boot)

一、项目介绍 项目名称&#xff1a;lucky player 项目的主要功能&#xff1a;本系统主要功能为构建了一个用户分享音乐的平台&#xff0c;普通用户不进行登录即可收听其他用户已经发布的专辑中的音乐。 作为博主则可以在该平台上传音频&#xff0c;以及在线音频录制上传。音频上…

Kafka 学习笔记

&#x1f600;&#x1f600;&#x1f600;创作不易&#xff0c;各位看官点赞收藏. 文章目录 Kafka 学习笔记1、消息队列 MQ2、Kafka 下载安装2.1、Zookeeper 方式启动2.2、KRaft 协议启动2.3、Kafka 集群搭建 3、Kafka 之生产者3.1、Java 生产者 API3.2、Kafka 生产者生产分区3…

8月17日上课内容 第三章 LVS+Keepalived群集

本章结构 Keepalived概述 keepalived 概述 1.服务功能 故障自动切换 健康检查 节点服务器高可用 HA keepalived工作原理 Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案&#xff0c;可以解决静态路由出现的单点故障问题 在一个LVS服务集群中通常有主服务器 (MAST…

【AWS】安装配置适用于 Eclipse 的 AWS 工具包

目录 0.环境 1.步骤 1&#xff09;安装Eclipse 2&#xff09;安装AWS工具包 ① 在这个路径下点开安装软件的界面 ② 点击【Add】打开添加窗口 ③ 输入aws的工具包地址 ④ 勾选需要的工具&#xff0c;点击【Next】 ⑤ 将要安装的工具&#xff0c;点击【Next】 ⑥ 选择接受…

华为云CodeArts Snap 智能编程助手PyCharm实验手册. 插件安装与使用指南

作为一款自主创新的AI代码辅助编程工具&#xff0c;华为云智能编程助手CodeArts Snap目标打造现代化开发新范式。通过将自然语言转化为规范可阅读、无开源漏洞的安全编程语言&#xff0c;提升开发者编程效率&#xff0c;助力企业快速响应市场需求。华为云CodeArts Snap现进入邀…

【算法C++实现】5、二叉树

二叉树节点结构体 class Node { public:int val;Node* left;Node* right;Node(int a) : val(a), left(nullptr), right(nullptr) {}Node(int a, Node* l, Node* r): val(a), left(l), right(r) {}}1、递归遍历 递归遍历二叉树&#xff0c;每个节点的遍历顺序叫递归序&#xf…

【广州华锐互动】3D空间编辑器:一款简洁易用的VR/3D在线编辑工具

随着虚拟现实技术的不断发展&#xff0c;数字孪生技术的应用已经被广泛应用于产品设计和制作中&#xff0c;能充分发挥企业应用3D建模的优势&#xff0c;凸显了三维设计的价值&#xff0c;在生产阶段也能够充分发挥3D模型的作用。 如今&#xff0c;广州华锐互动开发的3D空间编辑…

十、flume的安装

1.解压 2.改名 3.修改权限 4.编辑环境变量并source export FLUME_HOME/usr/local/flume export PATH$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$HIVE_HOME/bin:$HBASE_HOME/bin:$SQOOP_HOME/bin:$PIG_HOME/bin:$FLUME_HOME/bin 5.配置 6.查看版本 7.启动Hadoo…

GuitarPro8软件最新版本更新安装下载

可以为众多用户提供乐谱&#xff0c;谱面简单&#xff0c;不会影响观看。Guitar pro 8的曲谱比较全面&#xff0c;寻找方便&#xff0c;每天还会有免费曲谱供用户下载。同时&#xff0c;Guitar pro 8允许用户对于软件内置曲谱进行编辑&#xff0c;播放&#xff0c;方便用户进行…

Apache Hudi初探(二)(与flink的结合)--flink写hudi的操作(JobManager端的提交操作)

背景 在Apache Hudi初探(一)(与flink的结合)中&#xff0c;我们提到了Pipelines.hoodieStreamWrite 写hudi文件,这个操作真正写hudi是在Pipelines.hoodieStreamWrite方法下的transform(opName("stream_write", conf), TypeInformation.of(Object.class), operatorFa…