2011-09-07 24 views
5

Tôi đang cố gắng để có được một chương trình cơ bản để làm việc bằng cách sử dụng clCreateProgramWithBinary. Điều này là vì vậy tôi biết làm thế nào để sử dụng nó chứ không phải là một ứng dụng "đúng".Làm thế nào để sử dụng clCreateProgramWithBinary trong OpenCL?

Tôi thấy rằng một trong các tham số là danh sách các tệp nhị phân. Làm thế nào chính xác tôi sẽ đi về việc tạo ra một nhị phân để kiểm tra với? Tôi có một số mã thử nghiệm mà tạo ra một chương trình từ nguồn, xây dựng và enqueues nó. Có một nhị phân được tạo ra tại một số điểm trong quá trình này mà tôi có thể nạp vào clCreateProgramWithBinary?

Đây là một số mã của tôi, chỉ để đưa ra ý tưởng về luồng tổng thể của tôi. Tôi đã bỏ qua nhận xét và kiểm tra lỗi để đơn giản.

program = clCreateProgramWithSource(clctx, 1, &dumbkernelsource, NULL, &errcode); 
errcode = clBuildProgram(program, env->num_devices, env->device, NULL, NULL, NULL); 
mykernel = clCreateKernel(program, "flops", &errcode); 
errcode = clGetKernelWorkGroupInfo(mykernel, *(env->device), CL_KERNEL_WORK_GROUP_SIZE, sizeof(local), &local, NULL); 
global = num_workgroups * local; 
errcode = clEnqueueNDRangeKernel(commands, mykernel, 1, NULL, &global, &local, 0, NULL, NULL); 

Trả lời

2

Sau khi bạn biên dịch chương trình, bạn có thể nhận mã nhị phân bằng clGetProgramInfo và sau đó lưu tệp đó vào tệp.

Ví dụ mã (không cố gắng để biên dịch, nhưng nên có một cái gì đó dọc theo những dòng):

program = clCreateProgramWithSource(clctx, 1, &dumbkernelsource, NULL, &errcode); 
errcode = clBuildProgram(program, env->num_devices, env->device, NULL, NULL, NULL); 
int number_of_binaries; 
char **binary; 
int *binary_sizes; 
errcode = clGetProgramInfo(program, CL_PROGRAM_BINARY_SIZES, NULL, 0, &number_of_binaries); 
binary_sizes = new int[number_of_binaries]; 
binary = new char*[number_of_binaries]; 
errcode = clGetProgramInfo(program, CL_PROGRAM_BINARY_SIZES, binary_sizes, number_of_binaries*sizeof(int), &number_of_binaries); 
for (int i = 0; i < number_of_binaries; ++i) binary[i] = new char[binary_sizes[i]]; 
errcode = clGetProgramInfo(program, CL_PROGRAM_BINARIES, binary, number_of_binaries*sizeof(char*), &number_of_binaries); 
0

Cuốn sách OpenCL Lập trình Hướng dẫn chính thức có một ví dụ đẹp về điều này. Ngoài ra còn có một dự án mã của Google, các sách mẫu opencl, bao gồm mã từ cuốn sách. Ví dụ bạn đang tìm kiếm là here.

0

Minimal dụ Runnable

Biên dịch nhúng shader increment vector từ nguồn CL C, lưu nhị phân để a.bin, nạp shader nhị phân, và chạy nó:

./a.out 

Khẳng định được thực hiện tại cuối chương trình.

Bỏ qua nhị phân shader tải CL C từ a.bin, và chạy nó:

./a.out 0 

Biên dịch và chạy với:

gcc -ggdb3 -std=c99 -Wall -Wextra a.c -lOpenCL && ./a.out 

Tested trong Ubuntu 16.10, NVIDIA NVS5400, tài xế 375,39.

GitHub thượng nguồn: https://github.com/cirosantilli/cpp-cheat/blob/b1e9696cb18a12c4a41e0287695a2a6591b04597/opencl/binary_shader.c

#include <assert.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#define CL_USE_DEPRECATED_OPENCL_1_2_APIS 
#include <CL/cl.h> 

const char *source = 
    "__kernel void kmain(__global int *out) {\n" 
    " out[get_global_id(0)]++;\n" 
    "}\n" 
; 

#define BIN_PATH "a.bin" 

char* common_read_file(const char *path, long *length_out) { 
    char *buffer; 
    FILE *f; 
    long length; 

    f = fopen(path, "r"); 
    assert(NULL != f); 
    fseek(f, 0, SEEK_END); 
    length = ftell(f); 
    fseek(f, 0, SEEK_SET); 
    buffer = malloc(length); 
    if (fread(buffer, 1, length, f) < (size_t)length) { 
     return NULL; 
    } 
    fclose(f); 
    if (NULL != length_out) { 
     *length_out = length; 
    } 
    return buffer; 
} 

int main(int argc, char **argv) { 
    FILE *f; 
    char *binary; 
    cl_command_queue command_queue; 
    cl_context context; 
    cl_device_id device; 
    cl_int input[] = {1, 2}, errcode_ret, binary_status; 
    cl_kernel kernel, binary_kernel; 
    cl_mem buffer; 
    cl_platform_id platform; 
    cl_program program, binary_program; 
    const size_t global_work_size = sizeof(input)/sizeof(input[0]); 
    int use_cache; 
    long lenght; 
    size_t binary_size; 

    if (argc > 1) { 
     use_cache = !strcmp(argv[1], "0"); 
    } else { 
     use_cache = 0; 
    } 

    /* Get the binary, and create a kernel with it. */ 
    clGetPlatformIDs(1, &platform, NULL); 
    clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 1, &device, NULL); 
    context = clCreateContext(NULL, 1, &device, NULL, NULL, NULL); 
    command_queue = clCreateCommandQueue(context, device, 0, NULL); 
    if (use_cache) { 
     binary = common_read_file(BIN_PATH, &lenght); 
     binary_size = lenght; 
    } else { 
     program = clCreateProgramWithSource(context, 1, &source, NULL, NULL); 
     clBuildProgram(program, 1, &device, "", NULL, NULL); 
     kernel = clCreateKernel(program, "kmain", NULL); 
     clGetProgramInfo(program, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &binary_size, NULL); 
     binary = malloc(binary_size); 
     clGetProgramInfo(program, CL_PROGRAM_BINARIES, binary_size, &binary, NULL); 
     f = fopen(BIN_PATH, "w"); 
     fwrite(binary, binary_size, 1, f); 
     fclose(f); 
    } 
    binary_program = clCreateProgramWithBinary(
     context, 1, &device, &binary_size, 
     (const unsigned char **)&binary, &binary_status, &errcode_ret 
    ); 
    free(binary); 
    clBuildProgram(binary_program, 1, &device, NULL, NULL, NULL); 
    binary_kernel = clCreateKernel(binary_program, "kmain", &errcode_ret); 

    /* Run the kernel created from the binary. */ 
    buffer = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(input), input, NULL); 
    clSetKernelArg(binary_kernel, 0, sizeof(buffer), &buffer); 
    clEnqueueNDRangeKernel(command_queue, binary_kernel, 1, NULL, &global_work_size, NULL, 0, NULL, NULL); 
    clFlush(command_queue); 
    clFinish(command_queue); 
    clEnqueueReadBuffer(command_queue, buffer, CL_TRUE, 0, sizeof(input), input, 0, NULL, NULL); 

    /* Assertions. */ 
    assert(input[0] == 2); 
    assert(input[1] == 3); 

    /* Cleanup. */ 
    clReleaseMemObject(buffer); 
    clReleaseKernel(kernel); 
    clReleaseKernel(binary_kernel); 
    clReleaseProgram(program); 
    clReleaseProgram(binary_program); 
    clReleaseCommandQueue(command_queue); 
    clReleaseContext(context); 
    return EXIT_SUCCESS; 
} 

tôi khuyên bạn nên cat a.bin, trong đó có thể đọc được (và có thể chỉnh sửa) lắp ráp PTX nhân lực cho thực hiện này.

Các vấn đề liên quan