OpenCL 使用函数 clCreateProgramWithBinary 来创建程序
▶ 函数 clCreateProgramWithSource 接收 OpenCL 代码(设备无关)来创建程序,而函数 clCreateProgramWithBinary 接收已经经过函数 clBuildProgram 的 build 过的代码(设备有关)来创建程序
● 范例代码,还是计算两向量和
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cl.h> const int nElement = ;
const char *binaryFileName = "D:\\Code\\OpenCL\\OpenCLProjectTemp\\OpenCLProjectTemp\\vectorAdd.bin";
const char *programSource = " \
__kernel void vectorAdd(__global int *A, __global int *B, __global int *C) \
{ \
int idx = get_global_id(); \
C[idx] = A[idx] + B[idx]; \
return; \
} \
"; int readSource(const char* kernelPath, unsigned char **output)// 读取文本文件,存储为字符串,返回字符数
{
FILE *pf;
long int size;
printf("readSource, Program file: %s\n", kernelPath);
fopen_s(&pf, kernelPath, "rb");
if (!pf)
{
printf("Open kernel file failed\n");
exit(-);
}
if (fseek(pf, , SEEK_END) != )
{
printf("Seek end of file faildd\n");
exit(-);
}
if ((size = ftell(pf)) < )
{
printf("Get file position failed\n");
exit(-);
}
rewind(pf);
if ((*output = (unsigned char *)malloc(size + )) == NULL)
{
printf("Allocate space failed\n");
exit(-);
}
fread(*output, , size, pf);
fclose(pf);
(*output)[size] = '\0';
return strlen((char*)*output);
} int main()
{
const size_t datasize = sizeof(int) * nElement;
int i, *A, *B, *C;
cl_int status;
unsigned char *programBinary;
FILE *pf; A = (int*)malloc(datasize);
B = (int*)malloc(datasize);
C = (int*)malloc(datasize);
for (i = ; i < nElement; A[i] = B[i] = i, i++); cl_platform_id platform;
clGetPlatformIDs(, &platform, NULL);
cl_device_id device;
clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, , &device, NULL);
cl_context context = clCreateContext(NULL, , &device, NULL, NULL, &status);
cl_command_queue cmdQueue = clCreateCommandQueue(context, device, , &status);
cl_mem bufferA, bufferB, bufferC;
bufferA = clCreateBuffer(context, CL_MEM_READ_ONLY, datasize, NULL, &status);
bufferB = clCreateBuffer(context, CL_MEM_READ_ONLY, datasize, NULL, &status);
bufferC = clCreateBuffer(context, CL_MEM_WRITE_ONLY, datasize, NULL, &status);
clEnqueueWriteBuffer(cmdQueue, bufferA, CL_FALSE, , datasize, A, , NULL, NULL);
clEnqueueWriteBuffer(cmdQueue, bufferB, CL_FALSE, , datasize, B, , NULL, NULL);
cl_program program = clCreateProgramWithSource(context, , &programSource, NULL, &status);
clBuildProgram(program, , &device, NULL, NULL, NULL); // 抽取已经 build 的 program 的代码
size_t programBinarySize;
clGetProgramInfo(program, CL_PROGRAM_BINARY_SIZES, sizeof(cl_device_id), &programBinarySize, NULL); // 获取 build 的 program 的大小
programBinary = (unsigned char *)malloc(sizeof(unsigned char)*programBinarySize);
clGetProgramInfo(program, CL_PROGRAM_BINARIES, sizeof(unsigned char *), &programBinary, NULL); // 获取代码 // 将代码写入文件,再读回来,这说明可以从外部文件中直接读取已经 build 的 program 来使用
fopen_s(&pf, binaryFileName, "w");
fwrite(programBinary, , programBinarySize, pf);
free(programBinary);
fclose(pf);
programBinarySize = readSource(binaryFileName, &programBinary); // 使用clCreateProgramWithBinary 来建立 program
cl_program program2 = clCreateProgramWithBinary(context, , &device, &programBinarySize, (const unsigned char **)&programBinary, NULL, NULL);
clBuildProgram(program2, , &device, NULL, NULL, NULL); cl_kernel kernel = clCreateKernel(program2, "vectorAdd", &status);
status = clSetKernelArg(kernel, , sizeof(cl_mem), &bufferA);
status = clSetKernelArg(kernel, , sizeof(cl_mem), &bufferB);
status = clSetKernelArg(kernel, , sizeof(cl_mem), &bufferC);
size_t globalSize[] = { nElement }, localSize[] = { };
status = clEnqueueNDRangeKernel(cmdQueue, kernel, , NULL, globalSize, localSize, , NULL, NULL);
clEnqueueReadBuffer(cmdQueue, bufferC, CL_TRUE, , datasize, C, , NULL, NULL); for (i = ; i < nElement; i++)
{
if (C[i] != i + i)
break;
}
printf("Output is %s.\n", (i == nElement) ? "correct" : "incorrect"); free(A);
free(B);
free(C);
free(programBinary);
clReleaseContext(context);
clReleaseMemObject(bufferA);
clReleaseMemObject(bufferB);
clReleaseMemObject(bufferC);
clReleaseCommandQueue(cmdQueue);
clReleaseProgram(program);
clReleaseProgram(program2);
clReleaseKernel(kernel);
getchar();
return ;
}
● 输出结果
readSource, Program file: D:\Code\OpenCL\OpenCLProjectTemp\OpenCLProjectTemp\vectorAdd.bin
Output is correct.
● 由代码中的向量加法生成的 program 代码文件
//
// Generated by NVIDIA NVVM Compiler
//
// Compiler Build ID: UNKNOWN
// Driver
// Based on LLVM 3.4svn
// .version 6.1
.target sm_61, texmode_independent
.address_size // .globl vectorAdd .entry vectorAdd(
.param .u64 .ptr .global .align vectorAdd_param_0,
.param .u64 .ptr .global .align vectorAdd_param_1,
.param .u64 .ptr .global .align vectorAdd_param_2
)
{
.reg .b32 %r<>;
.reg .b64 %rd<>; ld.param.u64 %rd1, [vectorAdd_param_0];
ld.param.u64 %rd2, [vectorAdd_param_1];
ld.param.u64 %rd3, [vectorAdd_param_2];
mov.b32 %r1, %envreg3;
mov.u32 %r2, %ntid.x;
mov.u32 %r3, %ctaid.x;
mad.lo.s32 %r4, %r3, %r2, %r1;
mov.u32 %r5, %tid.x;
add.s32 %r6, %r4, %r5;
mul.wide.s32 %rd4, %r6, ;
add.s64 %rd5, %rd1, %rd4;
ld.global.u32 %r7, [%rd5];
add.s64 %rd6, %rd2, %rd4;
ld.global.u32 %r8, [%rd6];
add.s32 %r9, %r8, %r7;
add.s64 %rd7, %rd3, %rd4;
st.global.u32 [%rd7], %r9;
ret;
}
OpenCL 使用函数 clCreateProgramWithBinary 来创建程序的更多相关文章
- flask实战-个人博客-使用工厂函数创建程序实例 --
使用工厂函数创建程序实例 使用蓝本还有一个重要的好处,那就是允许使用工厂函数来创建程序实例.在OOP(Object-Oriented Programming,面向对象编程)中,工厂(factory)是 ...
- android 没有main函数,怎么找到程序执行入口呢?以及activity主要生命周期的方法说明
android应用程序,由一到多个Activity组成.每个Activity没有很紧密的联系,因为我们可以在自己的程序中调用其它Activity,特别是调用自己的代码之外生成的Activity,比如a ...
- 利用php函数mkdir递归创建层级目录
项目开发中免不了要在服务器上创建文件夹,比如上传图片时的目录,模板解析时的目录等.这不当前手下的项目就用到了这个,于是总结了几个循环创建层级目录的方法. php默认的mkdir一次只能创建一层目录,而 ...
- 重点:怎样正确的使用QThread类(很多详细例子的对比,注意:QThread 中所有实现的函数是被创建它的线程来调用的,不是在线程中)good
背景描述: 以前,继承 QThread 重新实现 run() 函数是使用 QThread唯一推荐的使用方法.这是相当直观和易于使用的.但是在工作线程中使用槽机制和Qt事件循环时,一些用户使用错了.Qt ...
- 函数计算: 让小程序开发进入 Serverless 时代
点击下载<不一样的 双11 技术:阿里巴巴经济体云原生实践> 本文节选自<不一样的 双11 技术:阿里巴巴经济体云原生实践>一书,点击上方图片即可下载! 作者 | 吴天龙(木吴 ...
- ROS wiki 学习(1)创建程序包时遇到的rosdep update出错
1. 使用turtlebot官网的ubuntu14.04走ROS维基时,在创建程序包后出现错误. 按照提示执行之后,出现以下错误. 搜寻度娘,几经波折后,终于解决.解决过程如下: 首先删除默认文件20 ...
- 使用select函数改进客户端/服务器端程序
一.当我们使用单进程单连接且使用readline修改后的客户端程序,去连接使用readline修改后的服务器端程序,会出现一个有趣的现象,先来看输出: 先运行服务器端,再运行客户端, simba@ub ...
- Ros学习——创建程序包
1.程序包 一个程序包要想称为catkin程序包必须符合以下要求: 该程序包必须包含catkin compliant package.xml文件 这个package.xml文件提供有关程序包的元信 ...
- vc++如何创建程序-设置断点-函数的覆盖,c++的多态性
---恢复内容开始--- 如何设置断点小笔记 将光标移动到你想设置断点的地方,按一下F9键即可,或者你可以用鼠标左键点击小手图标. CommentOut多行注释 函数的覆盖是在父类与子类之间的,函数的 ...
随机推荐
- 使用Bootstrap插件datapicker获取时间
引入css和js <link rel="stylesheet" href="/${appName}/commons/css/datapicker/datepicke ...
- idea中解决Git反复输入代码的问题
打开git终端,或者idea中的插件终端,输入命令: git config --global credential.helper store 借用一下别人的图不要介意哈.......... 执行上述命 ...
- git 如何关联多个库
git 如何关联多个库 在本地同一个库进行操作多个库,可以把代码推送到不同的库中,可以拉取某个库指定的代码,这样更加灵活使用 git remote 查看远程主机名 git remote -v // λ ...
- 将java打jar包成linux后台服务service
将java打jar包成linux后台服务service 第一步:将java程序打成jar包 build.gradle配置文件中加spring-boot-gradle-plugin插件,具体配置如下(配 ...
- C++ 标准库和标准模板库(STL)
转自原文http://blog.csdn.net/sxhelijian/article/details/7552499 一.C++标准库 C++标准库的内容分为10类,分别是(建议在阅读中,将你已经用 ...
- PostgreSQL逻辑复制槽
Schema | Name | Result data type | Argument data types | Type ------------+------------------------- ...
- mysql配置调优-开启慢查询日志-slow_query_log
工作中,会遇到需要查看mysql的top 20 慢sql,逐个进行优化,加上必要的索引这种需求,这时就需要开启数据库的慢查询日志的功能 1.查询当前慢查询日志的状态 # 默认为关闭状态 mysql - ...
- MarkDown格式作业模板
发布的随笔可复制下面的MarkDowm模板 注意事项 标题第XX次作业替换成相应的第一次作业.第二次作业...... 代码托管的链接一定要换成自己的项目 码云提交历史截图必须是自己每周的提交截图 #& ...
- Linux wget auto login and backup database
#!/bin/bash # 这是一份本来打算采用自动备份数据的代码,由于测试过程中出现了无法连接的问题,导致不能测试, # 于是最后放弃了这份代码的进一步的开发,但是记录还是有必要的 login_ur ...
- Codeforces 133A:HQ9+
A. HQ9+ time limit per test 2 seconds memory limit per test 256 megabytes input standard input outpu ...