▶ 函数 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 来创建程序的更多相关文章

  1. flask实战-个人博客-使用工厂函数创建程序实例 --

    使用工厂函数创建程序实例 使用蓝本还有一个重要的好处,那就是允许使用工厂函数来创建程序实例.在OOP(Object-Oriented Programming,面向对象编程)中,工厂(factory)是 ...

  2. android 没有main函数,怎么找到程序执行入口呢?以及activity主要生命周期的方法说明

    android应用程序,由一到多个Activity组成.每个Activity没有很紧密的联系,因为我们可以在自己的程序中调用其它Activity,特别是调用自己的代码之外生成的Activity,比如a ...

  3. 利用php函数mkdir递归创建层级目录

    项目开发中免不了要在服务器上创建文件夹,比如上传图片时的目录,模板解析时的目录等.这不当前手下的项目就用到了这个,于是总结了几个循环创建层级目录的方法. php默认的mkdir一次只能创建一层目录,而 ...

  4. 重点:怎样正确的使用QThread类(很多详细例子的对比,注意:QThread 中所有实现的函数是被创建它的线程来调用的,不是在线程中)good

    背景描述: 以前,继承 QThread 重新实现 run() 函数是使用 QThread唯一推荐的使用方法.这是相当直观和易于使用的.但是在工作线程中使用槽机制和Qt事件循环时,一些用户使用错了.Qt ...

  5. 函数计算: 让小程序开发进入 Serverless 时代

    点击下载<不一样的 双11 技术:阿里巴巴经济体云原生实践> 本文节选自<不一样的 双11 技术:阿里巴巴经济体云原生实践>一书,点击上方图片即可下载! 作者 | 吴天龙(木吴 ...

  6. ROS wiki 学习(1)创建程序包时遇到的rosdep update出错

    1. 使用turtlebot官网的ubuntu14.04走ROS维基时,在创建程序包后出现错误. 按照提示执行之后,出现以下错误. 搜寻度娘,几经波折后,终于解决.解决过程如下: 首先删除默认文件20 ...

  7. 使用select函数改进客户端/服务器端程序

    一.当我们使用单进程单连接且使用readline修改后的客户端程序,去连接使用readline修改后的服务器端程序,会出现一个有趣的现象,先来看输出: 先运行服务器端,再运行客户端, simba@ub ...

  8. Ros学习——创建程序包

      1.程序包 一个程序包要想称为catkin程序包必须符合以下要求: 该程序包必须包含catkin compliant package.xml文件 这个package.xml文件提供有关程序包的元信 ...

  9. vc++如何创建程序-设置断点-函数的覆盖,c++的多态性

    ---恢复内容开始--- 如何设置断点小笔记 将光标移动到你想设置断点的地方,按一下F9键即可,或者你可以用鼠标左键点击小手图标. CommentOut多行注释 函数的覆盖是在父类与子类之间的,函数的 ...

随机推荐

  1. $state和$rootScope.$on($stateChangeStart)

    这两者的区别:请看博客:http://stackoverflow.com/questions/32680292/angularjs-state-and-rootscope-onstatechanges ...

  2. python 数字的四舍五入的问题

    由于 python3 包括python2.7 以后的round策略使用的是decimal.ROUND_HALF_EVEN 即Round to nearest with ties going to ne ...

  3. JSP 指令

    JSP 指令 JSP指令用来设置整个JSP页面相关的属性,如网页的编码方式和脚本语言. 语法格式如下: <%@ directive attribute="value" %&g ...

  4. python json与字典对象互相转换

    改文章转自:https://www.cnblogs.com/Lin-Yi/p/7640147.html 1 import requests 2 import json 3 ''' 4 json.loa ...

  5. UVA-11761-马尔可夫/记忆化搜索

    https://vjudge.net/problem/UVA-11762 给出一个整数n,每次随机挑选一个小于等于n的素数,如果是n的因子,n变为n/x ,否则不变,问n变为1的期望挑选次数. f[i ...

  6. HDU 4522 (恶心建图)

    湫湫系列故事——过年回家 Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total ...

  7. [转载]java正则表达式

    转载自:http://butter.iteye.com/blog/1189600 1.正则表达式的知识要点1.正则表达式是什么?正则表达式是一种可以用于模式匹配和替换的强有力的工具.2.正则表达式的优 ...

  8. 学习笔记20151211——AXI4 STREAM DATA FIFO

    AXI4 STREAM DATA FIFO是输入输出接口均为AXIS接口的数据缓存器,和其他fifo一样是先进先出形式.可以在跨时钟域的应用中用于数据缓冲,避免亚稳态出现.支持数据的分割和数据拼接.在 ...

  9. Type Script在Visual Studio 2013中的问题汇总(持续更新…)

    TypeScript在vs2012下的问题 TypeScript对VS2012支持度比较低,建议升级为VS2013版本以上. 在VS2013中无法创建TypeScript项目 VS2013默认不支持T ...

  10. Struts2基本使用(二)--配置文件简述

    配置文件简述 引入Struts2框架之后项目中多了一个struts.xml,以及web.xml也多了一些代码 web.xml只要的功能就是拦截用户的请求其多出的代码如下: <filter> ...