diff --git a/pyopencl/__init__.py b/pyopencl/__init__.py index e5a20a50090afe9cf1208490017c1325f7d5e41e..b5c5687535adb65790810d76cda4ca12c0af60f4 100644 --- a/pyopencl/__init__.py +++ b/pyopencl/__init__.py @@ -152,17 +152,14 @@ class Program(object): if os.environ.get("PYOPENCL_NO_CACHE") and self._prg is None: self._prg = _cl._Program(self._context, self._source) - if self._prg is not None: # uncached - self._build_and_catch_errors( lambda: self._prg.build(" ".join(options), devices), options=options) else: # cached - from pyopencl.cache import create_built_program_from_source_cached self._prg = self._build_and_catch_errors( lambda: create_built_program_from_source_cached( diff --git a/pyopencl/cache.py b/pyopencl/cache.py index 10ea16e03053df9292619bbdea68ccabffb858fb..349a8ec343d9c900434b841280b0e7f496f7eaa1 100644 --- a/pyopencl/cache.py +++ b/pyopencl/cache.py @@ -248,7 +248,6 @@ def get_cache_key(device, options, src): def retrieve_from_cache(cache_dir, cache_key): class _InvalidInfoFile(RuntimeError): pass - from os.path import join, isdir module_cache_dir = join(cache_dir, cache_key) if not isdir(module_cache_dir): @@ -390,7 +389,6 @@ def _create_built_program_from_source_cached(ctx, src, options, devices, cache_d result = None already_built = False - if to_be_built_indices: # defeat implementation caches: from uuid import uuid4 @@ -434,7 +432,6 @@ def _create_built_program_from_source_cached(ctx, src, options, devices, cache_d cache_key = cache_keys[i] device = devices[i] binary = binaries[i] - mod_cache_dir_m = ModuleCacheDirManager(cleanup_m, join(cache_dir, cache_key)) info_path = mod_cache_dir_m.sub("info") @@ -478,7 +475,6 @@ def create_built_program_from_source_cached(ctx, src, options=[], devices=None, already_built = False except Exception, e: - raise from pyopencl import Error if (isinstance(e, Error) and e.code == _cl.status_code.BUILD_PROGRAM_FAILURE): diff --git a/pyopencl/cffi_cl.py b/pyopencl/cffi_cl.py index 451c71e515cfb3b8c9df109366dcbe8d30587b21..5f8a3cd41ff828359f77d616808189f0f0581559 100644 --- a/pyopencl/cffi_cl.py +++ b/pyopencl/cffi_cl.py @@ -302,10 +302,18 @@ class _Program(_Common): ptr_program = _ffi.new('void **') ptr_devices = _ffi.new('void*[]', [device.ptr for device in devices]) - ptr_binaries = _ffi.new('char*[]', len(binaries)) - for i, binary in enumerate(binaries): - ptr_binaries[i] = _ffi.new('char[]', binary) - _handle_error(_lib._create_program_with_binary(ptr_program, context.ptr, len(ptr_devices), ptr_devices, len(ptr_binaries), ptr_binaries)) + ptr_binaries = [_ffi.new('char[]', binary) for binary in binaries] + binary_sizes = _ffi.new('size_t[]', map(len, binaries)) + + _handle_error(_lib._create_program_with_binary( + ptr_program, + context.ptr, + len(ptr_devices), + ptr_devices, + len(ptr_binaries), + _ffi.new('char*[]', ptr_binaries), + binary_sizes)) + self.ptr = ptr_program[0] def kind(self): @@ -314,13 +322,17 @@ class _Program(_Common): return kind[0] def _build(self, options=None, devices=None): - if devices is None: raise NotImplementedError() - # TODO: if devices is None, create them if options is None: options = "" - ptr_devices = _ffi.new('void*[]', [device.ptr for device in devices]) + #if devices is None: devices = self.get_info(0x1163) + if devices is None: + num_devices = 0 + ptr_devices = _ffi.NULL + else: + ptr_devices = _ffi.new('void*[]', [device.ptr for device in devices]) + num_devices = len(devices) - _handle_error(_lib.program__build(self.ptr, _ffi.new('char[]', options), len(ptr_devices), _ffi.cast('void**', ptr_devices))) + _handle_error(_lib.program__build(self.ptr, _ffi.new('char[]', options), num_devices, _ffi.cast('void**', ptr_devices))) def get_build_info(self, device, param): @@ -376,7 +388,12 @@ def _generic_info_to_python(info): ret = map(_ffi.string, value) _lib._free2(info.value, len(value)) elif type_.endswith(']'): - ret = list(value) + if type_.startswith('char['): + ret = ''.join(a[0] for a in value) + elif type_.startswith('generic_info['): + ret = list(map(_generic_info_to_python, value)) + else: + ret = list(value) else: ret = value[0] _lib._free(info.value) diff --git a/src/c_wrapper/wrap_cl.cpp b/src/c_wrapper/wrap_cl.cpp index bddd84e6614d2fdd8aadd94c9cf8458c169e7ba9..85021d7fe202f54dfd57cfd61634352d76d64e17 100644 --- a/src/c_wrapper/wrap_cl.cpp +++ b/src/c_wrapper/wrap_cl.cpp @@ -861,14 +861,13 @@ generic_info get_info(cl_device_info param_name) const if (py_dev) dev = py_dev->data(); else - { - // TODO - // std::vector<cl_device_id> devs; - // PYOPENCL_GET_VEC_INFO(Context, ctx.data(), CL_CONTEXT_DEVICES, devs); - // if (devs.size() == 0) - // throw pyopencl::error("CommandQueue", CL_INVALID_VALUE, - // "context doesn't have any devices? -- don't know which one to default to"); - // dev = devs[0]; + { + std::vector<cl_device_id> devs; + PYOPENCL_GET_VEC_INFO(Context, ctx.data(), CL_CONTEXT_DEVICES, devs); + if (devs.size() == 0) + throw pyopencl::error("CommandQueue", CL_INVALID_VALUE, + "context doesn't have any devices? -- don't know which one to default to"); + dev = devs[0]; } cl_int status_code; @@ -1450,16 +1449,20 @@ generic_info get_info(cl_device_info param_name) const { std::vector<size_t> sizes; PYOPENCL_GET_VEC_INFO(Program, m_program, CL_PROGRAM_BINARY_SIZES, sizes); - std::vector<char *> result_ptrs(sizes.size()); for (unsigned i = 0; i < sizes.size(); ++i) { - result_ptrs[i] = new char[sizes[i]+1]; - result_ptrs[i][sizes[i]] = '\0'; + result_ptrs[i] = new char[sizes[i]]; + } + std::vector<generic_info> gis(sizes.size()); + for(unsigned i = 0; i < sizes.size(); ++i) { + gis[i].opaque_class = CLASS_NONE; + gis[i].type = _copy_str(std::string("char[") + tostring(sizes[i]) + "]"); + gis[i].value = result_ptrs[i]; } PYOPENCL_CALL_GUARDED(clGetProgramInfo, - (m_program, CL_PROGRAM_BINARIES, sizes.size()*sizeof(char *), - &result_ptrs.front(), 0)); - PYOPENCL_GET_ARRAY_INFO(char*, result_ptrs) + (m_program, CL_PROGRAM_BINARIES, sizes.size()*sizeof(char *), + &result_ptrs.front(), 0)); + PYOPENCL_GET_ARRAY_INFO(generic_info, gis); } #if PYOPENCL_CL_VERSION >= 0x1020 @@ -1918,37 +1921,32 @@ generic_info get_info(cl_device_info param_name) const } inline - program *create_program_with_binary( - context &ctx, + program *create_program_with_binary(context &ctx, cl_uint num_devices, void **ptr_devices, cl_uint num_binaries, - char **binaries) + char **binaries, + size_t *binary_sizes) { std::vector<cl_device_id> devices; - std::vector<size_t> sizes; - std::vector<cl_int> binary_statuses; - + std::vector<cl_int> binary_statuses(num_devices); for (cl_uint i = 0; i < num_devices; ++i) { devices.push_back(static_cast<device*>(ptr_devices[i])->data()); - sizes.push_back(strlen(const_cast<const char*>(binaries[i]))); } - binary_statuses.resize(num_devices); cl_int status_code; PYOPENCL_PRINT_CALL_TRACE("clCreateProgramWithBinary"); - cl_program result = clCreateProgramWithBinary( - ctx.data(), num_devices, + cl_program result = clCreateProgramWithBinary(ctx.data(), num_devices, devices.empty( ) ? NULL : &devices.front(), - sizes.empty( ) ? NULL : &sizes.front(), - reinterpret_cast<const unsigned char**>(const_cast<const char**>(binaries)), // todo: valid cast? + binary_sizes, + reinterpret_cast<const unsigned char**>(const_cast<const char**>(binaries)), binary_statuses.empty( ) ? NULL : &binary_statuses.front(), &status_code); - if (status_code != CL_SUCCESS) - throw pyopencl::error("clCreateProgramWithBinary", status_code); - + // for (cl_uint i = 0; i < num_devices; ++i) // std::cout << i << ":" << binary_statuses[i] << std::endl; + if (status_code != CL_SUCCESS) + throw pyopencl::error("clCreateProgramWithBinary", status_code); try { @@ -2056,10 +2054,10 @@ generic_info get_info(cl_device_info param_name) const return 0; } - ::error *_create_program_with_binary(void **ptr_program, void *ptr_context, cl_uint num_devices, void **ptr_devices, cl_uint num_binaries, char **binaries) { + ::error *_create_program_with_binary(void **ptr_program, void *ptr_context, cl_uint num_devices, void **ptr_devices, cl_uint num_binaries, char **binaries, size_t *binary_sizes) { context *ctx = static_cast<context*>(ptr_context); C_HANDLE_ERROR( - *ptr_program = create_program_with_binary(*ctx, num_devices, ptr_devices, num_binaries, binaries); + *ptr_program = create_program_with_binary(*ctx, num_devices, ptr_devices, num_binaries, reinterpret_cast<char **>(binaries), binary_sizes); ) return 0; } diff --git a/src/c_wrapper/wrap_cl_core.h b/src/c_wrapper/wrap_cl_core.h index 0473ffd5ef38b23db20be5b5bb6a3f427753058f..47e18a49f49b383182c2384cf6dd18b0715392f4 100644 --- a/src/c_wrapper/wrap_cl_core.h +++ b/src/c_wrapper/wrap_cl_core.h @@ -33,7 +33,7 @@ error *_create_context(void **ptr_ctx, cl_context_properties *properties, cl_uin error *_create_command_queue(void **ptr_command_queue, void *ptr_context, void *ptr_device, cl_command_queue_properties properties); error *_create_buffer(void **ptr_buffer, void *ptr_context, cl_mem_flags flags, size_t size, void *hostbuf); error *_create_program_with_source(void **ptr_program, void *ptr_context, char *src); -error *_create_program_with_binary(void **ptr_program, void *ptr_context, cl_uint num_devices, void **ptr_devices, cl_uint num_binaries, char **binaries); +error *_create_program_with_binary(void **ptr_program, void *ptr_context, cl_uint num_devices, void **ptr_devices, cl_uint num_binaries, char **binaries, size_t *binary_sizes); error *program__build(void *ptr_program, char *options, cl_uint num_devices, void **ptr_devices); error *program__kind(void *ptr_program, int *kind); error *program__get_build_info(void *ptr_program, void *ptr_device, cl_program_build_info param, generic_info *out);