diff --git a/pyopencl/__init__.py b/pyopencl/__init__.py index dccf5b415fb889c4ebf9c1d60ac2cc98f461394f..e5a20a50090afe9cf1208490017c1325f7d5e41e 100644 --- a/pyopencl/__init__.py +++ b/pyopencl/__init__.py @@ -312,8 +312,10 @@ def _add_functionality(): # {{{ Context def context_repr(self): - return "<pyopencl.Context at 0x%x on %s>" % (self.obj_ptr, - ", ".join(repr(dev) for dev in self.devices)) + return 'TODO' + #return "<pyopencl.Context at TODO on %s>" % (", ".join(repr(dev) for dev in self.devices)) + # return "<pyopencl.Context at 0x%x on %s>" % (self.obj_ptr, + # ", ".join(repr(dev) for dev in self.devices)) def context_get_cl_version(self): import re diff --git a/pyopencl/cffi_cl.py b/pyopencl/cffi_cl.py index a9a432a7d63c923c1d75c85f5f0f218713c4dcc4..f42b9329aa29e834dcb3f0ce96b79758d44ccff2 100644 --- a/pyopencl/cffi_cl.py +++ b/pyopencl/cffi_cl.py @@ -164,7 +164,9 @@ def _handle_error(error): klass = RuntimeError else: klass = Error - raise klass(_ffi.string(error.routine), error.code, _ffi.string(error.msg)) + e = klass(_ffi.string(error.routine), error.code, _ffi.string(error.msg)) + _lib._free(error) + raise e # }}} class _Common(object): @@ -200,8 +202,6 @@ class Device(_Common): # todo: __del__ def get_info(self, param): - if param == 4145: - return self.__dict__["platform"] # TODO HACK return super(Device, self).get_info(param) def _parse_context_properties(properties): @@ -369,6 +369,22 @@ def _generic_info_to_python(info): ret = _ffi.string(_ffi.cast(type_, info.value)) elif type_.endswith(']'): ret = list(_ffi.cast(type_, info.value)) + elif type_ == 'cl_platform_id': + return _create_instance(Platform, _ffi.cast('void *', info.value)) + elif type_ == 'cl_device_id': + return _create_instance(Device, _ffi.cast('void *', info.value)) + elif type_ == 'cl_kernel': + return _create_instance(Kernel, _ffi.cast('void *', info.value)) + elif type_ == 'cl_context': + return _create_instance(Context, _ffi.cast('void *', info.value)) + elif type_ == 'cl_buffer': + return _create_instance(Buffer, _ffi.cast('void *', info.value)) + elif type_ == 'cl_program': + return _create_instance(Program, _ffi.cast('void *', info.value)) + elif type_ == 'cl_event': + return _create_instance(Event, _ffi.cast('void *', info.value)) + elif type_ == 'cl_command_queue': + return _create_instance(CommandQueue, _ffi.cast('void *', info.value)) else: ret = _ffi.cast('%s*' % type_, info.value)[0] _lib._free(info.value) diff --git a/src/c_wrapper/Makefile b/src/c_wrapper/Makefile index 2e1cc6d78fbba79480aec1dbf50bc415bdfb5f16..10dbd9d07f14a28af23923711cd5319caf314242 100644 --- a/src/c_wrapper/Makefile +++ b/src/c_wrapper/Makefile @@ -1,5 +1,5 @@ all: g++ -c -Wall -DPYOPENCL_PRETEND_CL_VERSION=4112 -Werror -fpic wrap_cl.cpp wrap_constants.cpp - g++ -shared -o libwrapcl.so wrap_cl.o wrap_constants.o + g++ -shared -o libwrapcl.so wrap_cl.o wrap_constants.o cp libwrapcl.so ../../pyopencl/ cp wrap_cl_core.h ../../pyopencl/wrap_cl_core.h diff --git a/src/c_wrapper/wrap_cl.cpp b/src/c_wrapper/wrap_cl.cpp index f5e6eec4f39fe7256f9f4d716610be5f3d2c6f4d..8511823059955c028d2c6876a7f21465a8c830c1 100644 --- a/src/c_wrapper/wrap_cl.cpp +++ b/src/c_wrapper/wrap_cl.cpp @@ -53,6 +53,10 @@ // }}} + +#define PYOPENCL_WAITLIST_ARGS \ + num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front() + #define PYOPENCL_GET_VEC_INFO(WHAT, FIRST_ARG, SECOND_ARG, RES_VEC) \ { \ size_t size; \ @@ -66,8 +70,19 @@ RES_VEC.empty( ) ? NULL : &RES_VEC.front(), &size)); \ } -#define PYOPENCL_WAITLIST_ARGS \ - num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front() +#define PYOPENCL_GET_OPAQUE_INFO(WHAT, FIRST_ARG, SECOND_ARG, CL_TYPE, TYPE) \ + { \ + CL_TYPE param_value; \ + PYOPENCL_CALL_GUARDED(clGet##WHAT##Info, \ + (FIRST_ARG, SECOND_ARG, sizeof(param_value), ¶m_value, 0)); \ + generic_info info; \ + info.type = #CL_TYPE; \ + if (param_value) \ + info.value = (void*)(new TYPE(param_value, /*retain*/ true)); \ + else \ + info.value = NULL; \ + return info; \ + } #define PYOPENCL_GET_STR_INFO(WHAT, FIRST_ARG, SECOND_ARG) \ @@ -97,13 +112,13 @@ return info; \ } -#define PYOPENCL_GET_ARRAY_INFO(TYPE, VEC) \ - { \ - MALLOC(TYPE, ar, VEC.size()); \ - for(uint32_t i = 0; i < VEC.size(); ++i) { \ - ar[i] = VEC[i]; \ - } \ - generic_info info; \ +#define PYOPENCL_GET_ARRAY_INFO(TYPE, VEC) \ + { \ + MALLOC(TYPE, ar, VEC.size()); \ + for(uint32_t i = 0; i < VEC.size(); ++i) { \ + ar[i] = VEC[i]; \ + } \ + generic_info info; \ info.type = _copy_str(std::string(#TYPE"[") + tostring(VEC.size()) + "]"); \ info.value = (void*)ar; \ return info; \ @@ -202,17 +217,6 @@ run_python_gc(); \ default: throw pyopencl::error("unknown class", CL_INVALID_VALUE); \ } - -#define FORALLCLASSES(OPERATION) \ - OPERATION(PLATFORM, platform) \ - OPERATION(DEVICE, device) \ - OPERATION(KERNEL, kernel) \ - OPERATION(CONTEXT, context) \ - OPERATION(COMMAND_QUEUE, command_queue) \ - OPERATION(BUFFER, buffer) \ - OPERATION(PROGRAM, program) \ - OPERATION(EVENT, event) - #define PYOPENCL_CL_PLATFORM cl_platform_id #define PYOPENCL_CL_DEVICE cl_device_id #define PYOPENCL_CL_KERNEL cl_kernel @@ -224,9 +228,6 @@ run_python_gc(); \ - int get_cl_version(void) { - return PYOPENCL_CL_VERSION; - } template<class T> std::string tostring(const T& v) { @@ -243,8 +244,6 @@ namespace pyopencl strcpy(cstr, str.c_str()); return cstr; } - - // {{{ error class error : public std::runtime_error @@ -284,87 +283,6 @@ namespace pyopencl class _common { }; - // {{{ event/synchronization - class event : public _common // : boost::noncopyable - { - private: - cl_event m_event; - - public: - event(cl_event event, bool retain) - : m_event(event) - { - if (retain) - PYOPENCL_CALL_GUARDED(clRetainEvent, (event)); - } - - event(event const &src) - : m_event(src.m_event) - { PYOPENCL_CALL_GUARDED(clRetainEvent, (m_event)); } - - virtual ~event() - { - // todo - // PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseEvent, - // (m_event)); - } - - const cl_event data() const - { return m_event; } - - PYOPENCL_EQUALITY_TESTS(event); - - generic_info get_info(cl_event_info param_name) const - { - switch (param_name) - { - // case CL_EVENT_COMMAND_QUEUE: - // PYOPENCL_GET_OPAQUE_INFO(Event, m_event, param_name, - // cl_command_queue, command_queue); - // case CL_EVENT_COMMAND_TYPE: - // PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name, - // cl_command_type); - // case CL_EVENT_COMMAND_EXECUTION_STATUS: - // PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name, - // cl_int); - // case CL_EVENT_REFERENCE_COUNT: - // PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name, - // cl_uint); - // #if PYOPENCL_CL_VERSION >= 0x1010 - // case CL_EVENT_CONTEXT: - // PYOPENCL_GET_OPAQUE_INFO(Event, m_event, param_name, - // cl_context, context); - // #endif - - default: - throw error("Event.get_info", CL_INVALID_VALUE); - } - } - - // py::object get_profiling_info(cl_profiling_info param_name) const - // { - // switch (param_name) - // { - // case CL_PROFILING_COMMAND_QUEUED: - // case CL_PROFILING_COMMAND_SUBMIT: - // case CL_PROFILING_COMMAND_START: - // case CL_PROFILING_COMMAND_END: - // PYOPENCL_GET_INTEGRAL_INFO(EventProfiling, m_event, param_name, - // cl_ulong); - // default: - // throw error("Event.get_profiling_info", CL_INVALID_VALUE); - // } - // } - - virtual void wait() - { - PYOPENCL_CALL_GUARDED_THREADED(clWaitForEvents, (1, &m_event)); - } - }; - - // }}} - - // {{{ platform class platform : public _common @@ -588,9 +506,9 @@ namespace pyopencl case CL_DEVICE_VERSION: case CL_DEVICE_EXTENSIONS: PYOPENCL_GET_STR_INFO(Device, m_device, param_name); - - // case CL_DEVICE_PLATFORM: - // PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_platform_id, platform); + + case CL_DEVICE_PLATFORM: + PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_platform_id, platform); // #if PYOPENCL_CL_VERSION >= 0x1010 // case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF: DEV_GET_INT_INF(cl_uint); @@ -970,19 +888,18 @@ namespace pyopencl { switch (param_name) { - // case CL_QUEUE_CONTEXT: - // PYOPENCL_GET_OPAQUE_INFO(CommandQueue, m_queue, param_name, - // cl_context, context); - // case CL_QUEUE_DEVICE: - // PYOPENCL_GET_OPAQUE_INFO(CommandQueue, m_queue, param_name, - // cl_device_id, device); - // case CL_QUEUE_REFERENCE_COUNT: - // PYOPENCL_GET_INTEGRAL_INFO(CommandQueue, m_queue, param_name, - // cl_uint); - // case CL_QUEUE_PROPERTIES: - // PYOPENCL_GET_INTEGRAL_INFO(CommandQueue, m_queue, param_name, - // cl_command_queue_properties); - + case CL_QUEUE_CONTEXT: + PYOPENCL_GET_OPAQUE_INFO(CommandQueue, m_queue, param_name, + cl_context, context); + case CL_QUEUE_DEVICE: + PYOPENCL_GET_OPAQUE_INFO(CommandQueue, m_queue, param_name, + cl_device_id, device); + case CL_QUEUE_REFERENCE_COUNT: + PYOPENCL_GET_INTEGRAL_INFO(CommandQueue, m_queue, param_name, + cl_uint); + case CL_QUEUE_PROPERTIES: + PYOPENCL_GET_INTEGRAL_INFO(CommandQueue, m_queue, param_name, + cl_command_queue_properties); default: throw error("CommandQueue.get_info", CL_INVALID_VALUE); } @@ -1021,6 +938,87 @@ namespace pyopencl // }}} + // {{{ event/synchronization + class event : public _common // : boost::noncopyable + { + private: + cl_event m_event; + + public: + event(cl_event event, bool retain) + : m_event(event) + { + if (retain) + PYOPENCL_CALL_GUARDED(clRetainEvent, (event)); + } + + event(event const &src) + : m_event(src.m_event) + { PYOPENCL_CALL_GUARDED(clRetainEvent, (m_event)); } + + virtual ~event() + { + // todo + // PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseEvent, + // (m_event)); + } + + const cl_event data() const + { return m_event; } + + PYOPENCL_EQUALITY_TESTS(event); + + generic_info get_info(cl_event_info param_name) const + { + switch (param_name) + { + case CL_EVENT_COMMAND_QUEUE: + PYOPENCL_GET_OPAQUE_INFO(Event, m_event, param_name, + cl_command_queue, command_queue); + case CL_EVENT_COMMAND_TYPE: + PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name, + cl_command_type); + case CL_EVENT_COMMAND_EXECUTION_STATUS: + PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name, + cl_int); + case CL_EVENT_REFERENCE_COUNT: + PYOPENCL_GET_INTEGRAL_INFO(Event, m_event, param_name, + cl_uint); +#if PYOPENCL_CL_VERSION >= 0x1010 + case CL_EVENT_CONTEXT: + PYOPENCL_GET_OPAQUE_INFO(Event, m_event, param_name, + cl_context, context); +#endif + + default: + throw error("Event.get_info", CL_INVALID_VALUE); + } + } + + // py::object get_profiling_info(cl_profiling_info param_name) const + // { + // switch (param_name) + // { + // case CL_PROFILING_COMMAND_QUEUED: + // case CL_PROFILING_COMMAND_SUBMIT: + // case CL_PROFILING_COMMAND_START: + // case CL_PROFILING_COMMAND_END: + // PYOPENCL_GET_INTEGRAL_INFO(EventProfiling, m_event, param_name, + // cl_ulong); + // default: + // throw error("Event.get_profiling_info", CL_INVALID_VALUE); + // } + // } + + virtual void wait() + { + PYOPENCL_CALL_GUARDED_THREADED(clWaitForEvents, (1, &m_event)); + } + }; + + // }}} + + // {{{ memory_object //py::object create_mem_object_wrapper(cl_mem mem); @@ -1045,26 +1043,26 @@ namespace pyopencl case CL_MEM_TYPE: PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, cl_mem_object_type); - // case CL_MEM_FLAGS: - // PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, - // cl_mem_flags); - // case CL_MEM_SIZE: - // PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, - // size_t); - // case CL_MEM_HOST_PTR: - // throw pyopencl::error("MemoryObject.get_info", CL_INVALID_VALUE, - // "Use MemoryObject.get_host_array to get host pointer."); - // case CL_MEM_MAP_COUNT: - // PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, - // cl_uint); - // case CL_MEM_REFERENCE_COUNT: - // PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, - // cl_uint); - // case CL_MEM_CONTEXT: - // PYOPENCL_GET_OPAQUE_INFO(MemObject, data(), param_name, - // cl_context, context); - - // #if PYOPENCL_CL_VERSION >= 0x1010 + case CL_MEM_FLAGS: + PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, + cl_mem_flags); + case CL_MEM_SIZE: + PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, + size_t); + case CL_MEM_HOST_PTR: + throw pyopencl::error("MemoryObject.get_info", CL_INVALID_VALUE, + "Use MemoryObject.get_host_array to get host pointer."); + case CL_MEM_MAP_COUNT: + PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, + cl_uint); + case CL_MEM_REFERENCE_COUNT: + PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, + cl_uint); + case CL_MEM_CONTEXT: + PYOPENCL_GET_OPAQUE_INFO(MemObject, data(), param_name, + cl_context, context); + +#if PYOPENCL_CL_VERSION >= 0x1010 // case CL_MEM_ASSOCIATED_MEMOBJECT: // { // cl_mem param_value; @@ -1077,10 +1075,10 @@ namespace pyopencl // return create_mem_object_wrapper(param_value); // } - // case CL_MEM_OFFSET: - // PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, - // size_t); - // #endif + case CL_MEM_OFFSET: + PYOPENCL_GET_INTEGRAL_INFO(MemObject, data(), param_name, + size_t); +#endif default: throw error("MemoryObjectHolder.get_info", CL_INVALID_VALUE); @@ -1438,9 +1436,9 @@ namespace pyopencl case CL_PROGRAM_REFERENCE_COUNT: PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name, cl_uint); - // case CL_PROGRAM_CONTEXT: - // PYOPENCL_GET_OPAQUE_INFO(Program, m_program, param_name, - // cl_context, context); + case CL_PROGRAM_CONTEXT: + PYOPENCL_GET_OPAQUE_INFO(Program, m_program, param_name, + cl_context, context); case CL_PROGRAM_NUM_DEVICES: PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name, cl_uint); @@ -1733,22 +1731,22 @@ namespace pyopencl { switch (param_name) { - // case CL_KERNEL_FUNCTION_NAME: - // PYOPENCL_GET_STR_INFO(Kernel, m_kernel, param_name); + case CL_KERNEL_FUNCTION_NAME: + PYOPENCL_GET_STR_INFO(Kernel, m_kernel, param_name); case CL_KERNEL_NUM_ARGS: case CL_KERNEL_REFERENCE_COUNT: PYOPENCL_GET_INTEGRAL_INFO(Kernel, m_kernel, param_name, cl_uint); - // case CL_KERNEL_CONTEXT: - // PYOPENCL_GET_OPAQUE_INFO(Kernel, m_kernel, param_name, - // cl_context, context); - // case CL_KERNEL_PROGRAM: - // PYOPENCL_GET_OPAQUE_INFO(Kernel, m_kernel, param_name, - // cl_program, program); - // #if PYOPENCL_CL_VERSION >= 0x1020 - // case CL_KERNEL_ATTRIBUTES: - // PYOPENCL_GET_STR_INFO(Kernel, m_kernel, param_name); - // #endif + case CL_KERNEL_CONTEXT: + PYOPENCL_GET_OPAQUE_INFO(Kernel, m_kernel, param_name, + cl_context, context); + case CL_KERNEL_PROGRAM: + PYOPENCL_GET_OPAQUE_INFO(Kernel, m_kernel, param_name, + cl_program, program); +#if PYOPENCL_CL_VERSION >= 0x1020 + case CL_KERNEL_ATTRIBUTES: + PYOPENCL_GET_STR_INFO(Kernel, m_kernel, param_name); +#endif default: throw error("Kernel.get_info", CL_INVALID_VALUE); } @@ -2218,8 +2216,9 @@ namespace pyopencl return 0; } - - + int get_cl_version(void) { + return PYOPENCL_CL_VERSION; + } }