▶ 函数 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. Mac上安装配置和简单使用PostgreSQL(仍然很不懂)

    因为想要使用推荐的rails-template.需要使用postgres.并初始化了一个用户postgres,密码是postgres.( e.g. $ createuser -d postgres ) ...

  2. 将C语言的CRC32 代码转成JAVA的CRC32 代码

    public class CustomerCRC32 { private static long[] crc32Table = new long[256]; static { long crcValu ...

  3. java读取PHP接口数据的实现方法(四)

    PHP文件: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 3 ...

  4. POJ 1321 棋盘问题 dfs 难度:0

    http://poj.org/problem?id=1321 注意是在'#'的地方放棋子 矩阵大小不过8*8,即使是8!的时间复杂度也足以承受,可以直接dfs求解 dfs时标注当前点的行和列已被访问, ...

  5. Swift 获取plist文件展示在TableView上

    // 1.定义二维数组 var data:[[String]]! override func viewDidLoad() { super.viewDidLoad() // 2.实例化tableView ...

  6. deno学习二 基本代码

    deno 介绍是安全的ts 运行时 简单的代码 使用js(app.js) console.log("demoapp") 输出 dalongdemo 使用ts(app.ts) con ...

  7. 使用IAR编译STM8S 怎样生产烧录文件

      IAR编译后能够生成的烧录文件格式有4中,例如以下 第一种是Motorola,其生成文件和STVD生成烧录文件.s19格式一样的,即能够通用 另外一种是16进制,keil等等常都用到的. 第三种是 ...

  8. ASP.NET 程序优化

    一.SqlDataRead和Dataset的选择 Sqldataread优点:读取数据非常快.如果对返回的数据不需做大量处理的情况下,建议使用SqlDataReader,其性能要比datset好很多. ...

  9. cocos2dx内存管理机制

    参考以下两篇文章 http://blog.csdn.net/ring0hx/article/details/7946397 http://blog.csdn.net/whuancai/article/ ...

  10. 【转】在Visual Studio中怎样快速添加代码段

    原文网址:http://blog.csdn.net/yl2isoft/article/details/9735527 以前一直只知道,键入prop,再按两次tab键,会生成自动属性代码. 今天闲着无事 ...