OpenCL 设备队列
▶ 按书上写的设备队列的代码,需要 OpenCL2.0 的平台和设备,先把代码堆上来
● 程序主要功能:用主机上的数组 Ahost 和 Bhost 创建设备缓冲区 Adevice 和 Bdevice,调用核函数 foo 及其子核函数 fooChild 计算 factor * Adevice .* Bdevice,结果写入 Cdevice,最后拷贝回主机数组 Chost 检查结果。
● 代码
//deviceQueue.cl
__kernel void fooChild(const int nElement, const float factor,
__global const float *A, __global const float *B, __global float *C)
{
uint gid = get_global_id();
if (gid < nElement)
C[gid] = factor * A[gid] * B[gid];
} __kernel void foo(const int nElement, const float factor,
__global const float *A, __global const float *B, __global float *C)
{
uint gid = get_global_id(), gsize = get_global_size();
uint childGsize = nElement / gsize, childOffset = gid * childGsize; __global const float *Achild = &A[childOffset];
__global const float *Bchild = &B[childOffset];
__global const float *Cchild = &C[childOffset]; queue_t defQ = get_default_queue();
ndrange_t ndrange = ndrange_1D(childGsize);
void(^fooChildWrapper)(void) = ^{ fooChild(childGsize, factor, Achild, Bchild, Cchild); };
enqueue_kernel(defQ, CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, saxpyDpChildWrapper);
}
//main.c
#include <stdio.h>
#include <stdlib.h>
#include <cl.h> const char *sourceCode = "D:/Code/deviceQueue.cl"; char* readSource(const char* kernelPath)// 读取文本文件,存储为 char *
{
FILE *fp;
char *source;
long int size;
//printf("readSource, Program file: %s\n", kernelPath);
fopen_s(&fp, kernelPath, "rb");
if (!fp)
{
printf("Open kernel file failed\n");
exit(-);
}
if (fseek(fp, , SEEK_END) != )
{
printf("Seek end of file faildd\n");
exit(-);
}
if ((size = ftell(fp)) < )
{
printf("Get file position failed\n");
exit(-);
}
rewind(fp);
if ((source = (char *)malloc(size + )) == NULL)
{
printf("Allocate space failed\n");
exit(-);
}
fread(source, , size, fp);
fclose(fp);
source[size] = '\0';
return source;
} int main()
{
const int nElement = , nChildElement = , dataSize = nElement * sizeof(float);
float factor = 2.3f;
char info[] = { };
int i; // 初始化平台
cl_int status;
cl_platform_id platform;
status = clGetPlatformIDs(, &platform, NULL);
cl_device_id device;
status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, , &device, NULL);
cl_context_properties contextProp[] = { CL_CONTEXT_PLATFORM,(cl_context_properties)(platform), };
cl_context context = clCreateContext(contextProp, , &device, NULL, contextProp, &status);
cl_queue_properties queueProp[] = { CL_QUEUE_PROPERTIES,CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_ON_DEVICE | CL_QUEUE_ON_DEVICE_DEFAULT, };
cl_command_queue queue = clCreateCommandQueueWithProperties(context, device, queueProp, &status);
cl_event eventProducer, eventConsumer; const char* source = readSource(sourceCode);
cl_program program = clCreateProgramWithSource(context, , &source, NULL, &status);
status = clBuildProgram(program, , &device, NULL, NULL, NULL);
if (status)
{
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, , info, NULL);
printf("Build log:\n%s\n", info);
} cl_kernel foo = clCreateKernel(program, "foo", &status);
size_t globalSize = nElement / nChildElement, localSize = ;// 每个父工作项调度 nChildElement 个子工作项 float *Ahost = (float *)malloc(dataSize);
float *Bhost = (float *)malloc(dataSize);
float *Chost = (float *)malloc(dataSize);
for (i = ; i < nElement; Ahost[i] = i, Bhost[i] = i + , Chost[i] = .f, i++); cl_mem Adevice, Bdevice, Cdevice;
Adevice = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, dataSize, Ahost, &status);
Bdevice = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, dataSize, Bhost, &status);
Cdevice = clCreateBuffer(context, CL_MEM_WRITE_ONLY, dataSize, NULL, &status); clSetKernelArg(foo, , sizeof(int), (void*)&nElement);
clSetKernelArg(foo, , sizeof(float), (void*)&factor);
clSetKernelArg(foo, , sizeof(cl_mem), Adevice);
clSetKernelArg(foo, , sizeof(cl_mem), Bdevice);
clSetKernelArg(foo, , sizeof(cl_mem), Cdevice); clEnqueueNDRangeKernel(queue, foo, , NULL, &globalSize, &localSize, , NULL, &eventProducer);
clFinish(queue); clEnqueueReadBuffer(queue, Cdevice, CL_TRUE, dataSize, dataSize, Chost, , &eventConsumer, NULL);
clFinish(queue); for (i = ; i < nElement; i++)
{
if (Chost[i] != factor*i*(i + ))
break;
}
printf("Output is %s.\n", (i == nElement) ? "correct" : "incorrect"); free(Ahost);
free(Bhost);
free(Chost);
clReleaseContext(context);
clReleaseCommandQueue(queue);
clReleaseProgram(program);
clReleaseKernel(foo);
clReleaseMemObject(Adevice);
clReleaseMemObject(Bdevice);
clReleaseMemObject(Cdevice);
getchar();
return ;
}
● 输出结果
■ 一直卡在函数 clCreateCommandQueueWithProperties 的调用上,返回值 -6(CL_OUT_OF_HOST_MEMORY),原因不明,stackExchange 上有人说换了显卡驱动就好了(https://stackoverflow.com/questions/39864947/opencl-cl-out-of-host-memory-on-clcreatecommandqueuewithproperties-with-minima),还有人说是设备位数的问题(https://stackoverflow.com/questions/45231329/opencl-clcreatecommandqueue-cl-out-of-host-memory-error),但是我更新了显卡驱动,工程改成 32 位(才发现显卡是 32 位的)还是不行。
■ 强行忽略上面的问题(clCreateCommandQueueWithProperties 第四参数用 NULL)仍然程序编译失败,返回 -11(CL_BUILD_PROGRAM_FAILURE),原因是不能支持和函数中的 queue_t 和 ndrange_t 数据类型,后面的块语法就更别想了,应该是平台和设备不能完全支持 OpenCL2.0 所致。
■ 更新心啊卡驱动和 AMD OpenCL2.0 驱动,编译失败,报错 -11,报错信息变成了【Error: Inserting openCl Source to binary】和【Error: Compiling CL to IR】
OpenCL 设备队列的更多相关文章
- 《OpenCL异构并行编程实战》补充笔记散点,第一至四章
▶ 总体印象:适合 OpenCL 入门的书,有丰富的代码和说明,例子较为简单.先把 OpenCL 代码的基本结构(平台 → 设备 → 上下文 → 命令队列 → 创建缓冲区 → 读写缓冲区 → 编译代码 ...
- GPGPU OpenCL编程步骤与简单实例
http://www.cnblogs.com/xudong-bupt/p/3582780.html 1.OpenCL概念 OpenCL是一个为异构平台编写程序的框架,此异构平台可由CPU.GPU或其 ...
- OpenCL与CUDA,CPU与GPU
OpenCL OpenCL(全称Open Computing Language,开放运算语言)是第一个面向异构系统通用目的并行编程的开放式.免费标准,也是一个统一的编程环境,便于软件开发人员为高性能计 ...
- OPENCL 错误码
#define CL_SUCCESS 0 #define CL_DEVICE_NOT_FOUND -1 #define CL_DEVICE_NOT_AVAILABLE -2 #define CL_CO ...
- CUDA与OpenCL架构
CUDA与OpenCL架构 目录 CUDA与OpenCL架构 目录 1 GPU的体系结构 1.1 GPU简介 1.2 GPU与CPU的差异 2 CUDA架构 2.1 硬件架构 2.1.1 GPU困境 ...
- OpenCV、OpenCL、OpenGL、OpenPCL
对于几个开源库的总结,作为标记,以前看过,现在开始重视起来!更详细资料请移步 开源中国社区! 涉及:OpenCV,OpenCL,OpenGL,OpenPCL 截止到目前: OpenGL的最新版本为4. ...
- 【OpenCV开发】使用OpenCV的OpenCL(ocl)模块
参加OpenCV的OpenCL模块(以下称OCL)移植工作已经有2个月了.这里我说移植而不是开发,是因为大部分OCL模块的函数都是从已经很成熟的GPU模块移植过来的.于是目前阶段OCL模块所支持的函数 ...
- OpenCL介绍
OpenCL(全称Open Computing Language,开放运算语言)是第一个面向异构系统通用目的并行编程的开放式.免费标准,也是一个统一的编程环境,便于软件开发人员为高性能计算服务器.桌面 ...
- 一文说清OpenCL框架
背景 Read the fucking official documents! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: 对不 ...
随机推荐
- .NET 除了用 Task 之外,如何自己写一个可以 await 的对象?
.NET 中的 async / await 写异步代码用起来真的很爽,就像写同步一样.我们可以在各种各样的异步代码中看到 Task 返回值,这样大家便可以使用 await 等待这个方法.不过,有时需要 ...
- 《DSP using MATLAB》Problem 3.17
用差分方程两边进行z变换,再变量带换得到频率响应函数(或转移函数,即LTI系统脉冲响应的DTFT). 代码: %% ------------------------------------------ ...
- JAVA中神奇的双刃剑--Unsafe
前提 参考资料: Java魔法类:sun.misc.Unsafe 在openjdk8下看Unsafe源码 Unsafe介绍 在Oracle的Jdk8无法获取到sun.misc包的源码,想看此包的源码可 ...
- (研) int(*p)[10]; int *p[10]; int(*)[10]; 之间的区别
int *p[10]; 从这个最简单的说起 p先与后面的[4]结合,说明他本质是一个数组 ,“[]”的优先级比“*”要高.p先与“[]”结合,构成一个数组的定义,数组名为p,int *修饰的是数组的内 ...
- stenciljs 学习十一 pwa 支持
stenciljs 对于pwa 的支持是自动注入的,我们只需要简单的配置,stenciljs使用workbox 配置 默认配置 { skipWaiting: true, clientsClaim: t ...
- c++中的流
streambuf类为缓冲区提供内存,并提供了用于填充缓冲区,访问缓冲区,刷新新缓冲区和管理缓冲区内存的类方法. ios_base类表示流的一般特征,如是否可读,是二进制还是文本流等. ios类基于i ...
- 【转】每天一个linux命令(33):df 命令
原文网址:http://www.cnblogs.com/peida/archive/2012/12/07/2806483.html linux中df命令的功能是用来检查linux服务器的文件系统的磁盘 ...
- linux ssh公钥免密码登录
ssh 无密码登录要使用公钥与私钥.linux下可以用用ssh-keygen生成公钥/私钥对,下面我以CentOS为例. 一.SSH公钥登录原理 在平时工作中我们经常要远程登录服务器,这就要用到SSH ...
- bzoj 3622 已经没有什么好害怕的了——二项式反演
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3622 令 f[i] 表示钦定 i 对 a[ ]>b[ ] 的关系的方案数:g[i] 表 ...
- hadoop入门篇-hadoop下载安装教程(附图文步骤)
在前几篇的文章中分别就虚拟系统安装.LINUX系统安装以及hadoop运行服务器的设置等内容写了详细的操作教程,本篇分享的是hadoop的下载安装步骤. 在此之前有必要做一个简单的说明:分享的所有内容 ...