2011-09-07 2 views
5

저는 clCreateProgramWithBinary를 사용하여 작동하는 기본 프로그램을 얻으려고합니다. 이것은 "진정한"어플리케이션보다는 그것을 사용하는 방법을 알고 있습니다.OpenCL에서 clCreateProgramWithBinary를 사용하는 방법은 무엇입니까?

매개 변수 중 하나가 바이너리 목록임을 확인했습니다. 테스트를 위해 얼마나 정확하게 바이너리를 생성 할 것인가? 나는 소스로부터 프로그램을 생성하고, 빌드하고 그것을 큐에 넣는 테스트 코드를 가지고있다. 이 과정에서 clCreateProgramWithBinary로 피드 할 수있는 바이너리가 생성 되었습니까?

여기 내 코드의 일부입니다. 전반적인 흐름을 알기 위해서입니다. 단순화를 위해 주석과 오류 검사를 생략했습니다. 당신이 당신의 프로그램을 컴파일 한 후

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); 

답변

2

, 당신은 clGetProgramInfo와의 바이너리 코드를 얻을 다음 파일로 저장할 수 있습니다.

예제 코드 (컴파일했는데,이 라인을 따라 뭔가해야되지 않음) :

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

공식 오픈 CL 프로그래밍 가이드 책이의 좋은 예있다. 또한이 책의 코드가 포함 된 Google 코드 프로젝트 인 opencl-book-samples도 있습니다. 찾고있는 예제는 here입니다.

0

최소 실행 가능한 예를

이, CL C 소스의 임베디드 벡터 증가 쉐이더를 컴파일 a.bin에 바이너리를 저장, 이진 쉐이더를로드하고 실행 :

./a.out 

어설가에 완료 프로그램의 끝.

a.bin에서 CL C 쉐이더, 부하 바이너리를 무시하고 실행 :

./a.out 0 

컴파일 및 실행 :

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

우분투 16.10, NVIDIA NVS5400, 드라이버 375.39에서 테스트. 상류

GitHub의 : 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; 
} 

은 내가보기 엔이 구현을 위해 사람이 읽을 수있는 (그리고 편집) PTX 어셈블리를 포함 cat a.bin을 권장합니다.

관련 문제