>>From e836562568e8ffca023f866a5d06500ecb6ca65d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claudio=20Andr=C3=A9?= Date: Wed, 19 Dec 2012 14:36:19 -0200 Subject: [PATCH 3/3] Shared code to allow to build and use binary OpenCL kernels. --- src/common-opencl.c | 121 ++++++++++++++++++++++++++++++++++++++------------- src/common-opencl.h | 2 + 2 files changed, 93 insertions(+), 30 deletions(-) diff --git a/src/common-opencl.c b/src/common-opencl.c index eb6fadc..77c2f19 100644 --- a/src/common-opencl.c +++ b/src/common-opencl.c @@ -4,6 +4,9 @@ #include #include #include +#include +#include + #define LOG_SIZE 1024*16 static char opencl_log[LOG_SIZE]; @@ -121,7 +124,7 @@ static char *include_source(char *pathname, int dev_id, char *options) return include; } -static void build_kernel(int dev_id, char *options) +static void build_kernel(int dev_id, char *options, int save, char * file_name) { cl_int build_code; char * build_log; size_t log_size; @@ -156,28 +159,34 @@ static void build_kernel(int dev_id, char *options) fprintf(stderr, "Compilation log: %s\n", build_log); #endif MEM_FREE(build_log); -#if 0 - FILE *file; - size_t source_size; - char *source; - - HANDLE_CLERROR(clGetProgramInfo(program[dev_id], - CL_PROGRAM_BINARY_SIZES, - sizeof(size_t), &source_size, NULL), "error"); - fprintf(stderr, "source size %zu\n", source_size); - source = malloc(source_size); - - HANDLE_CLERROR(clGetProgramInfo(program[dev_id], - CL_PROGRAM_BINARIES, sizeof(char *), &source, NULL), "error"); - - file = fopen("program.bin", "w"); - if (file == NULL) - fprintf(stderr, "Error opening binary file\n"); - else if (fwrite(source, source_size, 1, file) != 1) - fprintf(stderr, "error writing binary\n"); - fclose(file); - MEM_FREE(source); + + if (save) { + FILE *file; + size_t source_size; + char *source; + + HANDLE_CLERROR(clGetProgramInfo(program[dev_id], + CL_PROGRAM_BINARY_SIZES, + sizeof(size_t), &source_size, NULL), "error"); +#if DEBUG + fprintf(stderr, "source size %zu\n", source_size); #endif + source = malloc(source_size); + + HANDLE_CLERROR(clGetProgramInfo(program[dev_id], + CL_PROGRAM_BINARIES, sizeof(char *), &source, NULL), "error"); + + file = fopen(path_expand(file_name), "w"); + + if (file == NULL) + fprintf(stderr, "Error creating binary file %s\n", file_name); + else { + if (fwrite(source, source_size, 1, file) != 1) + fprintf(stderr, "error writing binary\n"); + fclose(file); + } + MEM_FREE(source); + } } static void build_kernel_from_binary(int dev_id) @@ -456,7 +470,7 @@ void opencl_init_dev(unsigned int dev_id, unsigned int platform_id) void opencl_build_kernel_opt(char *kernel_filename, unsigned int dev_id, char *options) { read_kernel_source(kernel_filename); - build_kernel(dev_id, options); + build_kernel(dev_id, options, 0, NULL); } void opencl_build_kernel(char *kernel_filename, unsigned int dev_id) @@ -465,6 +479,53 @@ void opencl_build_kernel(char *kernel_filename, unsigned int dev_id) opencl_build_kernel_opt(kernel_filename, dev_id, NULL); } +//Only AMD gpu code will benefit from this routine. +void opencl_build_kernel_save(char *kernel_filename, unsigned int dev_id, char *options, int save, int warn) { + struct stat source_stat, bin_stat; + char dev_name[128], bin_name[128]; + char * p; + uint64_t startTime, runtime; + + kernel_loaded = 0; + + if (!gpu_amd(device_info[ocl_gpu_id]) || !save || stat(path_expand(kernel_filename), &source_stat)) + opencl_build_kernel_opt(kernel_filename, dev_id, options); + + else { + startTime = (unsigned long) time(NULL); + + //Get device name. + HANDLE_CLERROR(clGetDeviceInfo(devices[ocl_gpu_id], CL_DEVICE_NAME, + sizeof (dev_name), dev_name, NULL), "Error querying DEVICE_NAME"); + + //Decide the binary name. + p = strstr(kernel_filename, ".cl"); + strncpy(bin_name, kernel_filename, (p - kernel_filename)); + sprintf(bin_name, "%s_%s.bin", bin_name, dev_name); + + //Select the kernel to run. + if (!stat(path_expand(bin_name), &bin_stat) && (source_stat.st_mtime < bin_stat.st_mtime)) { + read_kernel_source(bin_name); + build_kernel_from_binary(dev_id); + + } else { + + if (warn) { + fprintf(stderr, "Building the kernel, this could take a while\n"); + fflush(stdout); + } + read_kernel_source(kernel_filename); + build_kernel(dev_id, options, 1, bin_name); + + if (warn) { + if ((runtime = (unsigned long) (time(NULL) - startTime)) > 2UL) + fprintf(stderr, "Elapsed time: %lu seconds\n", runtime); + fflush(stdout); + } + } + } +} + void opencl_build_kernel_from_binary(char *kernel_filename, unsigned int dev_id) { read_kernel_source(kernel_filename); diff --git a/src/common-opencl.h b/src/common-opencl.h index f143929..e15451d 100644 --- a/src/common-opencl.h +++ b/src/common-opencl.h @@ -58,6 +58,8 @@ void opencl_init_opt(char *kernel_filename, unsigned int dev_id, void opencl_init_from_binary(char *kernel_filename, unsigned int dev_id, unsigned int platform_id); void opencl_build_kernel(char *kernel_filename, unsigned int dev_id); +void opencl_build_kernel_from_binary(char *kernel_filename, unsigned int dev_id); +void opencl_build_kernel_save(char *kernel_filename, unsigned int dev_id, char *options, int save, int warn); void opencl_find_best_workgroup(struct fmt_main *self); void opencl_find_best_workgroup_limit(struct fmt_main *self, size_t group_size_limit); -- 1.7.9.5