▶ 函数 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. Java Spring-传统AOP开发

    2017-11-10 17:25:48 Spring中通知Advice类型(增强代码): 前置通知,org.springframework.aop.MethodBeforeAdvice:方法前 后置通 ...

  2. apache配置文件详解与优化

    apache配置文件详解与优化 一.总结 一句话总结:结合apache配置文件中的英文说明和配置详解一起看 1.apache模块配置用的什么标签? IfModule 例如: <IfModule ...

  3. Mac Hadoop2.6(CDH5.9.2)伪分布式集群安装

    操作系统: MAC OS X 一.准备 1. JDK 1.8 下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-dow ...

  4. mongodb 之linux下安装、启动、停止、连接

    今天在linux上面安装了mongodb 1.下载linux的mongodb 2.在目录usr/local下创建文件夹mongodb,把安装包解压到该文件夹中 # mkdir mongodb # ta ...

  5. HDU-1532 Drainage Ditches (最大流,EK算法模板)

    题目大意:最大流的模板题...源点是0,汇点是n-1. 代码如下: # include<iostream> # include<cstdio> # include<cma ...

  6. CSS padding 属性

    定义和用法 padding 简写属性在一个声明中设置所有内边距属性. 说明 这个简写属性设置元素所有内边距的宽度,或者设置各边上内边距的宽度.行内非替换元素上设置的内边距不会影响行高计算:因此,如果一 ...

  7. IOS-网络(JSON解析数据与XML解析数据)

    一.JSON解析数据 // // VideoModel.h // IOS_0130_网络视频 // // Created by ma c on 16/1/30. // Copyright © 2016 ...

  8. HDU 1029 基础dp

    题目链接:Ignatius and the Princess IV 大意:就是在N个数里找出唯一一个至少出现过(N+1)/ 2 次的数. 1 <= N <= 999999. hash: / ...

  9. 在ubuntu16中部署Django使用memcached作为缓存

    Django支持很多缓存系统,如 文件系统缓存. 数据库缓存. 内存缓存(Memcached),其中,Memcached是最快的,没有之一,是绝配.因为所有的缓存数据都放在内存,没有了IO延迟,也没有 ...

  10. [sqlserver脚本]查看指定SQL语句生成了哪些执行计划

    参考SQL技术内幕写了一段脚本,可以通过这段脚本查看执行指定SQL语句后,系统生成了哪些执行计划.使用时注意以下几点: 修改use MyTest,换成自己的数据库名字. 将 exec sp_page_ ...