|
@@ -24,56 +24,10 @@
|
|
#include <sys/wait.h>
|
|
#include <sys/wait.h>
|
|
|
|
|
|
#include <starpu_opencl.h>
|
|
#include <starpu_opencl.h>
|
|
-#include <common/list.h>
|
|
|
|
-#include <common/htable32.h>
|
|
|
|
#include <core/workers.h>
|
|
#include <core/workers.h>
|
|
#include "driver_opencl_utils.h"
|
|
#include "driver_opencl_utils.h"
|
|
#include "driver_opencl.h"
|
|
#include "driver_opencl.h"
|
|
|
|
|
|
-#define CRC32C_POLY_BE 0x1EDC6F41
|
|
|
|
-
|
|
|
|
-static
|
|
|
|
-inline uint32_t __attribute__ ((pure)) crc32_be_8(uint8_t inputbyte, uint32_t inputcrc)
|
|
|
|
-{
|
|
|
|
- unsigned i;
|
|
|
|
- uint32_t crc;
|
|
|
|
-
|
|
|
|
- crc = inputcrc ^ (inputbyte << 24);
|
|
|
|
- for (i = 0; i < 8; i++)
|
|
|
|
- crc = (crc << 1) ^ ((crc & 0x80000000) ? CRC32C_POLY_BE : 0);
|
|
|
|
-
|
|
|
|
- return crc;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static
|
|
|
|
-uint32_t crc32_string(char *str)
|
|
|
|
-{
|
|
|
|
- uint32_t hash = 0;
|
|
|
|
-
|
|
|
|
- size_t len = strlen(str);
|
|
|
|
-
|
|
|
|
- unsigned i;
|
|
|
|
- for (i = 0; i < len; i++)
|
|
|
|
- {
|
|
|
|
- hash = crc32_be_8((uint8_t)str[i], hash);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return hash;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static
|
|
|
|
-cl_uint _starpu_opencl_device_uniqueid(cl_device_id id)
|
|
|
|
-{
|
|
|
|
- char name[1024];
|
|
|
|
- cl_int err;
|
|
|
|
-
|
|
|
|
- err = clGetDeviceInfo(id, CL_DEVICE_NAME, 1024, name, NULL);
|
|
|
|
- if (err != CL_SUCCESS) STARPU_OPENCL_REPORT_ERROR(err);
|
|
|
|
- // fprintf(stderr, "name %s\n", name);
|
|
|
|
-
|
|
|
|
- return crc32_string(name);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
char *_starpu_opencl_codelet_dir;
|
|
char *_starpu_opencl_codelet_dir;
|
|
|
|
|
|
#define _STARPU_STRINGIFY_(x) #x
|
|
#define _STARPU_STRINGIFY_(x) #x
|
|
@@ -103,163 +57,22 @@ int _starpu_opencl_locate_file(char *source_file_name, char *located_file_name)
|
|
return EXIT_FAILURE;
|
|
return EXIT_FAILURE;
|
|
}
|
|
}
|
|
|
|
|
|
-static
|
|
|
|
-unsigned char *_starpu_opencl_load_program_binary(char *filename, size_t *len)
|
|
|
|
-{
|
|
|
|
- struct stat statbuf;
|
|
|
|
- FILE *fh;
|
|
|
|
- unsigned char *binary;
|
|
|
|
-
|
|
|
|
- fh = fopen(filename, "r");
|
|
|
|
- if (fh == 0)
|
|
|
|
- return NULL;
|
|
|
|
-
|
|
|
|
- stat(filename, &statbuf);
|
|
|
|
-
|
|
|
|
- binary = (unsigned char *) malloc(statbuf.st_size);
|
|
|
|
- if(!binary)
|
|
|
|
- return binary;
|
|
|
|
-
|
|
|
|
- fread(binary, statbuf.st_size, 1, fh);
|
|
|
|
-
|
|
|
|
- *len = statbuf.st_size;
|
|
|
|
- return binary;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static
|
|
|
|
-char *_starpu_basename(const char *name)
|
|
|
|
-{
|
|
|
|
- const char *base = name;
|
|
|
|
- while (*name) {
|
|
|
|
- if (*name++ == '/') {
|
|
|
|
- base = name;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return (char *) base;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static
|
|
|
|
-int _starpu_opencl_get_binary_filename(char *program_name, cl_device_id device, char *binary_filename)
|
|
|
|
-{
|
|
|
|
- char *p;
|
|
|
|
- char *basename;
|
|
|
|
- cl_uint uniqueid;
|
|
|
|
- cl_device_type type;
|
|
|
|
- uid_t uid;
|
|
|
|
- int err;
|
|
|
|
-
|
|
|
|
- // Get type of device
|
|
|
|
- err = clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(cl_device_type), &type, NULL);
|
|
|
|
- if (err != CL_SUCCESS) {
|
|
|
|
- STARPU_OPENCL_REPORT_ERROR(err);
|
|
|
|
- return err;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- uniqueid = _starpu_opencl_device_uniqueid(device);
|
|
|
|
- uid = getuid();
|
|
|
|
-
|
|
|
|
- sprintf(binary_filename, "/tmp/%llu_", (long long unsigned int)uid);
|
|
|
|
- basename = _starpu_basename(program_name);
|
|
|
|
- strcat(binary_filename, basename);
|
|
|
|
- p = strstr(binary_filename, ".cl");
|
|
|
|
- if (p == NULL) {
|
|
|
|
- OPENCL_ERROR("Program file name doesn't have the '.cl' extension!\n");
|
|
|
|
- return EXIT_FAILURE;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- strcpy(p, (type == CL_DEVICE_TYPE_GPU) ? ".gpu." : ".cpu.");
|
|
|
|
- sprintf(p + strlen(p), "%u", uniqueid);
|
|
|
|
-
|
|
|
|
- return EXIT_SUCCESS;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static
|
|
|
|
-cl_int _starpu_opencl_load_program(cl_context context, char *program_name, cl_device_id device, cl_program *program)
|
|
|
|
-{
|
|
|
|
- // cl_program program;
|
|
|
|
- const unsigned char *binary;
|
|
|
|
- size_t len;
|
|
|
|
- cl_int err;
|
|
|
|
- cl_int status;
|
|
|
|
-
|
|
|
|
- char binary_filename[1024];
|
|
|
|
-
|
|
|
|
- // Get the name of the binary file
|
|
|
|
- _starpu_opencl_get_binary_filename(program_name, device, binary_filename);
|
|
|
|
-
|
|
|
|
- // Load the binary file
|
|
|
|
- binary = _starpu_opencl_load_program_binary(binary_filename, &len);
|
|
|
|
- if(binary == NULL)
|
|
|
|
- OPENCL_ERROR("Cannot load binary file %s\n", binary_filename);
|
|
|
|
-
|
|
|
|
- //_STARPU_OPENCL_DEBUG("[%s] binary file loaded.\n", binary_filename);
|
|
|
|
- *program = clCreateProgramWithBinary(context, 1, &device, &len, &binary, &status, &err);
|
|
|
|
- if (err != CL_SUCCESS) {
|
|
|
|
- STARPU_OPENCL_REPORT_ERROR(err);
|
|
|
|
- return err;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Build the program executable
|
|
|
|
- err = clBuildProgram(*program, 0, NULL, NULL, NULL, NULL);
|
|
|
|
- if (err != CL_SUCCESS) {
|
|
|
|
- size_t len;
|
|
|
|
- char buffer[2048];
|
|
|
|
-
|
|
|
|
- fprintf(stderr, "Error: Failed to build program executable!\n");
|
|
|
|
- clGetProgramBuildInfo(*program, device, CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, &len);
|
|
|
|
- fprintf(stderr, "%s\n", buffer);
|
|
|
|
- return err;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return CL_SUCCESS;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static struct starpu_htbl32_node_s *history_program_hash[STARPU_MAXOPENCLDEVS] = {NULL};
|
|
|
|
-LIST_TYPE(program,
|
|
|
|
- char *program_name;
|
|
|
|
- cl_program program;
|
|
|
|
- );
|
|
|
|
-program_list_t history_program_list[STARPU_MAXOPENCLDEVS];
|
|
|
|
-
|
|
|
|
-int _starpu_opencl_init_programs(int dev)
|
|
|
|
-{
|
|
|
|
- history_program_list[dev] = program_list_new();
|
|
|
|
- return CL_SUCCESS;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-int _starpu_opencl_release_programs(int dev)
|
|
|
|
-{
|
|
|
|
- while (!program_list_empty(history_program_list[dev])) {
|
|
|
|
- program_t pp = program_list_pop_front(history_program_list[dev]);
|
|
|
|
- _STARPU_OPENCL_DEBUG("Releasing program=<%s> on dev=<%d>\n", pp->program_name, dev);
|
|
|
|
- clReleaseProgram(pp->program);
|
|
|
|
- }
|
|
|
|
- program_list_delete(history_program_list[dev]);
|
|
|
|
- return CL_SUCCESS;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-int starpu_opencl_load_kernel(cl_kernel *kernel, cl_command_queue *queue, char *program_name, char *kernel_name, int devid)
|
|
|
|
|
|
+int starpu_opencl_load_kernel(cl_kernel *kernel, cl_command_queue *queue, struct starpu_opencl_codelet *codelet,
|
|
|
|
+ char *kernel_name, int devid)
|
|
{
|
|
{
|
|
int err;
|
|
int err;
|
|
cl_device_id device;
|
|
cl_device_id device;
|
|
cl_context context;
|
|
cl_context context;
|
|
- uint32_t key;
|
|
|
|
cl_program program;
|
|
cl_program program;
|
|
|
|
|
|
starpu_opencl_get_device(devid, &device);
|
|
starpu_opencl_get_device(devid, &device);
|
|
starpu_opencl_get_context(devid, &context);
|
|
starpu_opencl_get_context(devid, &context);
|
|
starpu_opencl_get_queue(devid, queue);
|
|
starpu_opencl_get_queue(devid, queue);
|
|
|
|
|
|
- key = crc32_string(program_name);
|
|
|
|
- program = _starpu_htbl_search_32(history_program_hash[devid], key);
|
|
|
|
|
|
+ program = codelet->programs[devid];
|
|
if (!program) {
|
|
if (!program) {
|
|
- err = _starpu_opencl_load_program(context, program_name, device, &program);
|
|
|
|
- if (err != CL_SUCCESS) STARPU_OPENCL_REPORT_ERROR(err);
|
|
|
|
- _starpu_htbl_insert_32(&(history_program_hash[devid]), key, program);
|
|
|
|
- program_t pp = program_new();
|
|
|
|
- pp->program_name = program_name;
|
|
|
|
- pp->program = program;
|
|
|
|
- program_list_push_front(history_program_list[devid], pp);
|
|
|
|
|
|
+ fprintf(stderr, "Program not available\n");
|
|
|
|
+ return CL_INVALID_PROGRAM;
|
|
}
|
|
}
|
|
|
|
|
|
// Create the compute kernel in the program we wish to run
|
|
// Create the compute kernel in the program we wish to run
|
|
@@ -269,7 +82,7 @@ int starpu_opencl_load_kernel(cl_kernel *kernel, cl_command_queue *queue, char *
|
|
return CL_SUCCESS;
|
|
return CL_SUCCESS;
|
|
}
|
|
}
|
|
|
|
|
|
-int starpu_opencl_release(cl_kernel kernel) {
|
|
|
|
|
|
+int starpu_opencl_release_kernel(cl_kernel kernel) {
|
|
cl_int err;
|
|
cl_int err;
|
|
|
|
|
|
err = clReleaseKernel(kernel);
|
|
err = clReleaseKernel(kernel);
|
|
@@ -299,133 +112,74 @@ char *_starpu_opencl_load_program_source(const char *filename)
|
|
return source;
|
|
return source;
|
|
}
|
|
}
|
|
|
|
|
|
-static
|
|
|
|
-int _starpu_opencl_store_program_binary(const char *filename, const char *binary, size_t len)
|
|
|
|
|
|
+int starpu_opencl_load_opencl_from_string(char *opencl_codelet_source, struct starpu_opencl_codelet *codelet)
|
|
{
|
|
{
|
|
- FILE *fh;
|
|
|
|
|
|
+ unsigned int dev;
|
|
|
|
+ unsigned int nb_devices;
|
|
|
|
+
|
|
|
|
+ nb_devices = _starpu_opencl_get_device_count();
|
|
|
|
+ // Iterate over each device
|
|
|
|
+ for(dev = 0; dev < nb_devices; dev ++) {
|
|
|
|
+ cl_device_id device;
|
|
|
|
+ cl_context context;
|
|
|
|
+ cl_program program;
|
|
|
|
+ cl_int err;
|
|
|
|
+
|
|
|
|
+ starpu_opencl_get_device(dev, &device);
|
|
|
|
+ starpu_opencl_get_context(dev, &context);
|
|
|
|
+ codelet->programs[dev] = NULL;
|
|
|
|
+
|
|
|
|
+ if (context == NULL) continue;
|
|
|
|
+
|
|
|
|
+ // Create the compute program from the source buffer
|
|
|
|
+ program = clCreateProgramWithSource(context, 1, (const char **) &opencl_codelet_source, NULL, &err);
|
|
|
|
+ if (!program || err != CL_SUCCESS) STARPU_OPENCL_REPORT_ERROR(err);
|
|
|
|
+
|
|
|
|
+ // Build the program executable
|
|
|
|
+ err = clBuildProgram(program, 1, &device, "-Werror -cl-mad-enable", NULL, NULL);
|
|
|
|
+ if (err != CL_SUCCESS) {
|
|
|
|
+ size_t len;
|
|
|
|
+ static char buffer[4096];
|
|
|
|
+
|
|
|
|
+ fprintf(stderr, "Error: Failed to build program executable!\n");
|
|
|
|
+ clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, &len);
|
|
|
|
+
|
|
|
|
+ fprintf(stderr, "<%s>\n", buffer);
|
|
|
|
+ return EXIT_FAILURE;
|
|
|
|
+ }
|
|
|
|
|
|
- fh = fopen(filename, "w");
|
|
|
|
- if(fh == NULL) {
|
|
|
|
- perror("fopen"); return EXIT_FAILURE;
|
|
|
|
|
|
+ // Store program
|
|
|
|
+ codelet->programs[dev] = program;
|
|
}
|
|
}
|
|
-
|
|
|
|
- fwrite(binary, len, 1, fh);
|
|
|
|
- fclose(fh);
|
|
|
|
-
|
|
|
|
return EXIT_SUCCESS;
|
|
return EXIT_SUCCESS;
|
|
}
|
|
}
|
|
|
|
|
|
-int _starpu_opencl_compile_source_to_opencl(char *source_file_name)
|
|
|
|
|
|
+int starpu_opencl_load_opencl_from_file(char *source_file_name, struct starpu_opencl_codelet *codelet)
|
|
{
|
|
{
|
|
- int err;
|
|
|
|
- int device_type = CL_DEVICE_TYPE_ALL;
|
|
|
|
- cl_device_id devices[STARPU_MAXOPENCLDEVS];
|
|
|
|
- unsigned max = STARPU_MAXOPENCLDEVS;
|
|
|
|
- unsigned nb_devices = 0;
|
|
|
|
- cl_uint history[STARPU_MAXOPENCLDEVS]; // To track similar devices
|
|
|
|
- char located_file_name[1024];
|
|
|
|
- cl_platform_id platform_ids[STARPU_OPENCL_PLATFORM_MAX];
|
|
|
|
- cl_uint platform, nb_platforms;
|
|
|
|
- char *basename;
|
|
|
|
|
|
+ char located_file_name[1024];
|
|
|
|
|
|
// Locate source file
|
|
// Locate source file
|
|
_starpu_opencl_locate_file(source_file_name, located_file_name);
|
|
_starpu_opencl_locate_file(source_file_name, located_file_name);
|
|
_STARPU_OPENCL_DEBUG("Source file name : <%s>\n", located_file_name);
|
|
_STARPU_OPENCL_DEBUG("Source file name : <%s>\n", located_file_name);
|
|
- basename = _starpu_basename(located_file_name);
|
|
|
|
-
|
|
|
|
- // Get Platforms
|
|
|
|
- err = clGetPlatformIDs(STARPU_OPENCL_PLATFORM_MAX, platform_ids, &nb_platforms);
|
|
|
|
- if (err != CL_SUCCESS) STARPU_OPENCL_REPORT_ERROR(err);
|
|
|
|
-
|
|
|
|
- // Iterate over each platform
|
|
|
|
- for(platform=0; platform<nb_platforms; platform++) {
|
|
|
|
- // Get devices
|
|
|
|
- err = clGetDeviceIDs(platform_ids[platform], device_type, max, devices, &nb_devices);
|
|
|
|
- if (err != CL_SUCCESS) STARPU_OPENCL_REPORT_ERROR(err);
|
|
|
|
- if(nb_devices > max)
|
|
|
|
- nb_devices = max;
|
|
|
|
-
|
|
|
|
- // Iterate over each device
|
|
|
|
- unsigned int dev;
|
|
|
|
- for(dev = 0; dev < nb_devices; dev ++) {
|
|
|
|
- cl_context context;
|
|
|
|
- cl_program program;
|
|
|
|
- cl_device_type type;
|
|
|
|
- cl_int err;
|
|
|
|
- cl_uint uniqueid;
|
|
|
|
-
|
|
|
|
- uniqueid =_starpu_opencl_device_uniqueid(devices[dev]);
|
|
|
|
- // Look up and update history (to avoid unuseful compilations in the case of identical devices)
|
|
|
|
- {
|
|
|
|
- unsigned int d;
|
|
|
|
- for(d = 0; d < dev; d++)
|
|
|
|
- if(history[d] == uniqueid)
|
|
|
|
- break; // Just skip compiling for this device
|
|
|
|
- if(d != dev)
|
|
|
|
- continue;
|
|
|
|
- history[dev] = uniqueid;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- err = clGetDeviceInfo(devices[dev], CL_DEVICE_TYPE, sizeof(cl_device_type), &type, NULL);
|
|
|
|
- if (err != CL_SUCCESS) STARPU_OPENCL_REPORT_ERROR(err);
|
|
|
|
-
|
|
|
|
- // Create a compute context
|
|
|
|
- context = clCreateContext(0, 1, devices + dev, NULL, NULL, &err);
|
|
|
|
- if (err != CL_SUCCESS) STARPU_OPENCL_REPORT_ERROR(err);
|
|
|
|
-
|
|
|
|
- // Load the compute program from disk into a cstring buffer
|
|
|
|
- char *source = _starpu_opencl_load_program_source(located_file_name);
|
|
|
|
- if(!source)
|
|
|
|
- OPENCL_ERROR("Failed to load compute program from file <%s>!\n", located_file_name);
|
|
|
|
-
|
|
|
|
- // Create the compute program from the source buffer
|
|
|
|
- program = clCreateProgramWithSource(context, 1, (const char **) & source, NULL, &err);
|
|
|
|
- if (!program || err != CL_SUCCESS) STARPU_OPENCL_REPORT_ERROR(err);
|
|
|
|
-
|
|
|
|
- // Build the program executable
|
|
|
|
- err = clBuildProgram(program, 1, devices + dev, "-Werror -cl-mad-enable", NULL, NULL);
|
|
|
|
- if (err != CL_SUCCESS) {
|
|
|
|
- size_t len;
|
|
|
|
- static char buffer[4096];
|
|
|
|
-
|
|
|
|
- fprintf(stderr, "Error: Failed to build program executable!\n");
|
|
|
|
- clGetProgramBuildInfo(program, devices[dev], CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, &len);
|
|
|
|
-
|
|
|
|
- fprintf(stderr, "%s\n", buffer);
|
|
|
|
- return EXIT_FAILURE;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Store program binary
|
|
|
|
- {
|
|
|
|
- char binary_filename[1024];
|
|
|
|
- char *binary;
|
|
|
|
- size_t binary_len;
|
|
|
|
-
|
|
|
|
- // Get the name of the binary file
|
|
|
|
- _starpu_opencl_get_binary_filename(located_file_name, devices[dev], binary_filename);
|
|
|
|
-
|
|
|
|
- err = clGetProgramInfo(program, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &binary_len, NULL);
|
|
|
|
- if(err != CL_SUCCESS)
|
|
|
|
- OPENCL_ERROR("Cannot get program binary size (err = %d)!\n", err);
|
|
|
|
-
|
|
|
|
- binary = malloc(binary_len);
|
|
|
|
-
|
|
|
|
- err = clGetProgramInfo(program, CL_PROGRAM_BINARIES, sizeof(binary), &binary, NULL);
|
|
|
|
- if(err != CL_SUCCESS) STARPU_OPENCL_REPORT_ERROR(err);
|
|
|
|
-
|
|
|
|
- err = _starpu_opencl_store_program_binary(binary_filename, binary, binary_len);
|
|
|
|
- if (err != EXIT_SUCCESS)
|
|
|
|
- OPENCL_ERROR("Cannot store program binary (err = %d)!\n", err);
|
|
|
|
-
|
|
|
|
- free(binary);
|
|
|
|
-
|
|
|
|
- _STARPU_OPENCL_DEBUG("Binary file [%s] successfully built (%ld bytes).\n", binary_filename, binary_len);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- clReleaseProgram(program);
|
|
|
|
- clReleaseContext(context);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
+ // Load the compute program from disk into a cstring buffer
|
|
|
|
+ char *opencl_codelet_source = _starpu_opencl_load_program_source(located_file_name);
|
|
|
|
+ if(!opencl_codelet_source)
|
|
|
|
+ OPENCL_ERROR("Failed to load compute program from file <%s>!\n", located_file_name);
|
|
|
|
+
|
|
|
|
+ return starpu_opencl_load_opencl_from_string(opencl_codelet_source, codelet);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int starpu_opencl_unload_opencl(struct starpu_opencl_codelet *codelet)
|
|
|
|
+{
|
|
|
|
+ unsigned int dev;
|
|
|
|
+ unsigned int nb_devices;
|
|
|
|
+
|
|
|
|
+ nb_devices = _starpu_opencl_get_device_count();
|
|
|
|
+ // Iterate over each device
|
|
|
|
+ for(dev = 0; dev < nb_devices; dev ++) {
|
|
|
|
+ if (codelet->programs[dev])
|
|
|
|
+ clReleaseProgram(codelet->programs[dev]);
|
|
|
|
+ }
|
|
return EXIT_SUCCESS;
|
|
return EXIT_SUCCESS;
|
|
}
|
|
}
|