123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 |
- /*
- * This file is part of oclkit.
- *
- * oclkit is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * oclkit is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <assert.h>
- #include <getopt.h>
- #include "ocl.h"
- struct OclPlatform {
- cl_platform_id platform;
- cl_context context;
- cl_uint num_devices;
- cl_device_id *devices;
- cl_command_queue *cmd_queues;
- int own_queues;
- };
- static const char* opencl_error_msgs[] = {
- "CL_SUCCESS",
- "CL_DEVICE_NOT_FOUND",
- "CL_DEVICE_NOT_AVAILABLE",
- "CL_COMPILER_NOT_AVAILABLE",
- "CL_MEM_OBJECT_ALLOCATION_FAILURE",
- "CL_OUT_OF_RESOURCES",
- "CL_OUT_OF_HOST_MEMORY",
- "CL_PROFILING_INFO_NOT_AVAILABLE",
- "CL_MEM_COPY_OVERLAP",
- "CL_IMAGE_FORMAT_MISMATCH",
- "CL_IMAGE_FORMAT_NOT_SUPPORTED",
- "CL_BUILD_PROGRAM_FAILURE",
- "CL_MAP_FAILURE",
- "CL_MISALIGNED_SUB_BUFFER_OFFSET",
- "CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST",
- /* next IDs start at 30! */
- "CL_INVALID_VALUE",
- "CL_INVALID_DEVICE_TYPE",
- "CL_INVALID_PLATFORM",
- "CL_INVALID_DEVICE",
- "CL_INVALID_CONTEXT",
- "CL_INVALID_QUEUE_PROPERTIES",
- "CL_INVALID_COMMAND_QUEUE",
- "CL_INVALID_HOST_PTR",
- "CL_INVALID_MEM_OBJECT",
- "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR",
- "CL_INVALID_IMAGE_SIZE",
- "CL_INVALID_SAMPLER",
- "CL_INVALID_BINARY",
- "CL_INVALID_BUILD_OPTIONS",
- "CL_INVALID_PROGRAM",
- "CL_INVALID_PROGRAM_EXECUTABLE",
- "CL_INVALID_KERNEL_NAME",
- "CL_INVALID_KERNEL_DEFINITION",
- "CL_INVALID_KERNEL",
- "CL_INVALID_ARG_INDEX",
- "CL_INVALID_ARG_VALUE",
- "CL_INVALID_ARG_SIZE",
- "CL_INVALID_KERNEL_ARGS",
- "CL_INVALID_WORK_DIMENSION",
- "CL_INVALID_WORK_GROUP_SIZE",
- "CL_INVALID_WORK_ITEM_SIZE",
- "CL_INVALID_GLOBAL_OFFSET",
- "CL_INVALID_EVENT_WAIT_LIST",
- "CL_INVALID_EVENT",
- "CL_INVALID_OPERATION",
- "CL_INVALID_GL_OBJECT",
- "CL_INVALID_BUFFER_SIZE",
- "CL_INVALID_MIP_LEVEL",
- "CL_INVALID_GLOBAL_WORK_SIZE"
- };
- const char*
- ocl_strerr (int error)
- {
- int index = 0;
- if (error >= -14)
- index = -error;
- else if (error <= -30 && error >= -64)
- index = -error-15;
- return opencl_error_msgs[index];
- }
- static void
- transfer_error (cl_int src, cl_int *dst)
- {
- if (dst != NULL)
- *dst = src;
- }
- char *
- ocl_read_program (const char *filename)
- {
- FILE *fp;
- char *buffer;
- size_t length;
- size_t buffer_length;
- if ((fp = fopen(filename, "r")) == NULL)
- return NULL;
- fseek (fp, 0, SEEK_END);
- length = ftell (fp);
- rewind (fp);
- buffer = malloc (length + 1);
- buffer[length] = '\0';
- if (buffer == NULL) {
- fclose(fp);
- return NULL;
- }
- buffer_length = fread (buffer, 1, length, fp);
- fclose(fp);
- if (buffer_length != length) {
- free (buffer);
- buffer = NULL;
- }
- return buffer;
- }
- OclPlatform *
- ocl_new (unsigned platform,
- cl_device_type type)
- {
- OclPlatform *ocl;
- cl_int errcode;
- cl_uint num_platforms;
- cl_platform_id *platforms;
- ocl = malloc (sizeof(OclPlatform));
- OCL_CHECK_ERROR (clGetPlatformIDs (0, NULL, &num_platforms));
- platforms = malloc (sizeof (cl_platform_id) * num_platforms);
- if (platform >= num_platforms) {
- fprintf (stderr, "invalid platform %i out of %i platforms\n", platform, num_platforms);
- goto ocl_new_cleanup;
- }
- OCL_CHECK_ERROR (clGetPlatformIDs (num_platforms, platforms, NULL));
- ocl->platform = platforms[platform];
- OCL_CHECK_ERROR (clGetDeviceIDs (ocl->platform, type, 0, NULL, &ocl->num_devices));
- ocl->devices = malloc (ocl->num_devices * sizeof(cl_device_id));
- OCL_CHECK_ERROR (clGetDeviceIDs (ocl->platform, type, ocl->num_devices, ocl->devices, NULL));
- ocl->context = clCreateContext (NULL, ocl->num_devices, ocl->devices, NULL, NULL, &errcode);
- OCL_CHECK_ERROR (errcode);
- ocl->own_queues = 0;
- free (platforms);
- return ocl;
- ocl_new_cleanup:
- free (ocl);
- free (platforms);
- return NULL;
- }
- OclPlatform *
- ocl_new_with_queues (unsigned platform,
- cl_device_type type,
- cl_command_queue_properties queue_properties)
- {
- OclPlatform *ocl;
- cl_int errcode;
- ocl = ocl_new (platform, type);
- if (ocl == NULL)
- return NULL;
- ocl->own_queues = 1;
- ocl->cmd_queues = malloc (ocl->num_devices * sizeof(cl_command_queue));
- for (cl_uint i = 0; i < ocl->num_devices; i++) {
- ocl->cmd_queues[i] = clCreateCommandQueue (ocl->context, ocl->devices[i],
- queue_properties, &errcode);
- OCL_CHECK_ERROR (errcode);
- }
- return ocl;
- }
- void
- ocl_print_usage (void)
- {
- printf ("oclkit options\n"
- " --ocl-platform\tIndex of platform, starting with 0, to use\n"
- " --ocl-type\tDevice type: gpu, cpu or accelerator\n");
- }
- int
- ocl_read_args (int argc,
- const char **argv,
- unsigned int *platform,
- cl_device_type *type)
- {
- int c;
- static struct option options[] = {
- { "ocl-platform", required_argument, NULL, 'p' },
- { "ocl-type", required_argument, NULL, 't' },
- { "help", no_argument, NULL, 'h' },
- { NULL, 0, NULL, 0 }
- };
- while (1) {
- int index = 0;
- c = getopt_long (argc, (char **) argv, "p:d:t:h", options, &index);
- if (c == -1)
- break;
- switch (c) {
- case 'h':
- ocl_print_usage ();
- return -1;
- case 'p':
- *platform = atoi (optarg);
- break;
- case 't':
- {
- int n = strlen (optarg);
- n = n > 10 ? 10 : n; /* for accelerator */
- if (!strncmp (optarg, "gpu", n))
- *type = CL_DEVICE_TYPE_GPU;
- else if (!strncmp (optarg, "cpu", n))
- *type = CL_DEVICE_TYPE_CPU;
- else if (!strncmp (optarg, "accelerator", n))
- *type = CL_DEVICE_TYPE_ACCELERATOR;
- }
- break;
- default:
- abort ();
- }
- }
- return 0;
- }
- OclPlatform *
- ocl_new_from_args (int argc,
- const char **argv,
- cl_command_queue_properties queue_properties)
- {
- unsigned platform = 0;
- cl_device_type type = CL_DEVICE_TYPE_GPU;
- if (ocl_read_args (argc, argv, &platform, &type))
- return NULL;
- return ocl_new_with_queues (platform, type, queue_properties);
- }
- void
- ocl_free (OclPlatform *ocl)
- {
- if (ocl == NULL)
- return;
- if (ocl->own_queues) {
- for (cl_uint i = 0; i < ocl->num_devices; i++)
- OCL_CHECK_ERROR (clReleaseCommandQueue (ocl->cmd_queues[i]));
- free (ocl->cmd_queues);
- }
- OCL_CHECK_ERROR (clReleaseContext (ocl->context));
- free (ocl->devices);
- free (ocl);
- }
- char *
- ocl_get_platform_info (OclPlatform *ocl,
- cl_platform_info param)
- {
- size_t size;
- char *result;
- OCL_CHECK_ERROR (clGetPlatformInfo (ocl->platform, param, 0, NULL, &size));
- result = malloc (size);
- OCL_CHECK_ERROR (clGetPlatformInfo (ocl->platform, param, size, result, NULL));
- return result;
- }
- cl_program
- ocl_create_program_from_source (OclPlatform *ocl,
- const char *source,
- const char *options,
- cl_int *errcode)
- {
- cl_int tmp_err;
- cl_program program;
- program = clCreateProgramWithSource (ocl->context, 1, (const char **) &source, NULL, &tmp_err);
- if (tmp_err != CL_SUCCESS) {
- transfer_error (tmp_err, errcode);
- return NULL;
- }
- tmp_err = clBuildProgram (program, ocl->num_devices, ocl->devices, options, NULL, NULL);
- if (tmp_err != CL_SUCCESS) {
- size_t log_size;
- char* log;
- transfer_error (tmp_err, errcode);
- OCL_CHECK_ERROR (clGetProgramBuildInfo (program, ocl->devices[0], CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size));
- log = malloc (log_size * sizeof(char));
- OCL_CHECK_ERROR (clGetProgramBuildInfo (program, ocl->devices[0], CL_PROGRAM_BUILD_LOG, log_size, log, NULL));
- fprintf (stderr, "\n** Error building program. Build log:\n%s\n", log);
- free (log);
- return NULL;
- }
- *errcode = CL_SUCCESS;
- return program;
- }
- cl_program
- ocl_create_program_from_file (OclPlatform *ocl,
- const char *filename,
- const char *options,
- cl_int *errcode)
- {
- char *source;
- cl_program program;
- source = ocl_read_program (filename);
- if (source == NULL)
- return NULL;
- program = ocl_create_program_from_source (ocl, source, options, errcode);
- free(source);
- return program;
- }
- cl_context
- ocl_get_context (OclPlatform *ocl)
- {
- assert (ocl != NULL);
- return ocl->context;
- }
- int
- ocl_get_num_devices (OclPlatform *ocl)
- {
- assert (ocl != NULL);
- return ocl->num_devices;
- }
- cl_device_id *
- ocl_get_devices (OclPlatform *ocl)
- {
- assert (ocl != NULL);
- return ocl->devices;
- }
- cl_command_queue *
- ocl_get_cmd_queues (OclPlatform *ocl)
- {
- assert (ocl != NULL);
- return ocl->cmd_queues;
- }
- void
- ocl_get_event_times (cl_event event,
- cl_ulong *start,
- cl_ulong *end,
- cl_ulong *queued,
- cl_ulong *submitted)
- {
- if (queued != NULL)
- OCL_CHECK_ERROR (clGetEventProfilingInfo (event, CL_PROFILING_COMMAND_QUEUED, sizeof (cl_ulong), queued, NULL));
- if (submitted != NULL)
- OCL_CHECK_ERROR (clGetEventProfilingInfo (event, CL_PROFILING_COMMAND_SUBMIT, sizeof (cl_ulong), submitted, NULL));
- if (start != NULL)
- OCL_CHECK_ERROR (clGetEventProfilingInfo (event, CL_PROFILING_COMMAND_START, sizeof (cl_ulong), start, NULL));
- if (end != NULL)
- OCL_CHECK_ERROR (clGetEventProfilingInfo (event, CL_PROFILING_COMMAND_END, sizeof (cl_ulong), end, NULL));
- }
|