diff --git a/doc/make_constants.py b/doc/make_constants.py index 5bb8186f265dbeb090b9c9654f7d156b1593e086..5357f237ae9bf52546db3fbabe2ac01bef9f5a46 100644 --- a/doc/make_constants.py +++ b/doc/make_constants.py @@ -237,7 +237,7 @@ const_ext_lookup = { "PARTITION_BY_NAMES_LIST_END": cl_12, }, - cl.affinity_domain: { + cl.device_affinity_domain: { "NUMA": cl_12, "L4_CACHE": cl_12, "L3_CACHE": cl_12, diff --git a/doc/source/misc.rst b/doc/source/misc.rst index 8e71234c2fbcadaba3ba215feb9efb8eff88def5..5e8cf1714e27f086486a189fe0a1c01d58e3a2e5 100644 --- a/doc/source/misc.rst +++ b/doc/source/misc.rst @@ -91,8 +91,15 @@ Version 2011.2 * Add :mod:`pyopencl.characterize`. * Ensure compatibility with OS X Lion. * Add :func:`pyopencl.tools.register_dtype` to enable scan/reduction on struct types. - -.. * Beta support for OpenCL 1.2. +* :func:`pyopencl.enqueue_migrate_mem_object` was renamed + :func:`pyopencl.enqueue_migrate_mem_object_ext`. + :func:`pyopencl.enqueue_migrate_mem_object` now refers to the OpenCL 1.2 function + of this name, if available. +* :func:`pyopencl.create_sub_devices` was renamed + :func:`pyopencl.create_sub_devices_ext`. + :func:`pyopencl.create_sub_devices` now refers to the OpenCL 1.2 function + of this name, if available. +* Alpha support for OpenCL 1.2. Version 2011.1.2 ---------------- diff --git a/doc/source/runtime.rst b/doc/source/runtime.rst index 779acd83ae21fb311b557dab374ec5fe702881e2..f398c276ffc8c090184612728cf38a934e5560fb 100644 --- a/doc/source/runtime.rst +++ b/doc/source/runtime.rst @@ -151,6 +151,24 @@ Platforms, Devices and Contexts .. method:: create_sub_devices(properties) + *properties* is an array of one (or more) of the forms:: + + [ dpp.EQUALLY, 8] + [ dpp.BY_COUNTS, 5, 7, 9, dpp.PARTITION_BY_COUNTS_LIST_END] + [ dpp.BY_NAMES, 5, 7, 9, dpp.PARTITION_BY_NAMES_LIST_END] + [ dpp.BY_AFFINITY_DOMAIN, dad.L1_CACHE] + + where `dpp` represents :class:`device_partition_property` + and `dad` represent :class:`device_affinity_domain`. + + `PROPERTIES_LIST_END_EXT` is added automatically. + + Only available with CL 1.2. + + .. versionadded:: 2011.2 + + .. method:: create_sub_devices_ext(properties) + *properties* is an array of one (or more) of the forms:: [ dppe.EQUALLY, 8] @@ -244,19 +262,27 @@ Command Queues and Events .. function:: wait_for_events(events) -.. function:: enqueue_marker(queue) - - Returns an :class:`Event`. - -.. function:: enqueue_wait_for_events(queue, events) - -.. function:: enqueue_barrier(queue) +.. function:: enqueue_barrier(queue, wait_for=None) Enqueues a barrier operation. which ensures that all queued commands in command_queue have finished execution. This command is a synchronization point. .. versionadded:: 0.91.5 + .. versionchanged:: 2011.2 + Takes *wait_for* and returns an :class:`Event` + +.. function:: enqueue_marker(queue, wait_for=None) + + Returns an :class:`Event`. + + .. versionchanged:: 2011.2 + Takes *wait_for*. + +.. function:: enqueue_wait_for_events(queue, events) + + **Note:** This function is deprecated as of PyOpenCL 2011.2. + Use :func:`enqueue_marker` instead. .. class:: UserEvent(context) @@ -313,7 +339,15 @@ Memory |comparable| -.. function:: enqueue_migrate_mem_object(queue, mem_objects, flags=0, wait_for=None) +.. function:: enqueue_migrate_mem_objects(queue, mem_objects, flags=0, wait_for=None) + + :param flags: from :class:`migrate_mem_object_flags` + + .. versionadded:: 2011.2 + + Only available with CL 1.2. + +.. function:: enqueue_migrate_mem_object_ext(queue, mem_objects, flags=0, wait_for=None) :param flags: from :class:`migrate_mem_object_flags_ext` @@ -760,6 +794,9 @@ Programs and Kernels Returns a list of all :class:`Kernel` objects in the :class:`Program`. +.. function:: unload_platform_compiler(platform) + + .. versionadded:: 2011.2 .. class:: Kernel(program, name) @@ -777,6 +814,12 @@ Programs and Kernels See :class:`kernel_work_group_info` for values of *param*. + .. method:: get_arg_info(arg_index, param) + + See :class:`kernel_arg_info` for values of *param*. + + Only available in OpenCL 1.2 and newer. + .. method:: set_arg(self, index, arg) *arg* may be @@ -951,10 +994,15 @@ with GL support. See :func:`have_gl`. *mem_objects* is a list of :class:`MemoryObject` instances. |std-enqueue-blurb| -.. function:: get_gl_context_info_khr(properties, param_name) +.. function:: get_gl_context_info_khr(properties, param_name, platform=None) Get information on which CL device corresponds to a given GL/EGL/WGL/CGL device. See the :class:`Context` constructor for the meaning of *properties* and :class:`gl_context_info` for *param_name*. + + + .. versionchanged:: 2011.2 + Accepts the *platform* argument. Use *platform* equal to None is + deprecated as of PyOpenCL 2011.2. diff --git a/src/wrapper/wrap_cl.hpp b/src/wrapper/wrap_cl.hpp index 6f69d0f19f9849db2c6160c7b17b8492e27aa1da..791bbe5db23149fbaa88dafd96259ac0f5d0c9b3 100644 --- a/src/wrapper/wrap_cl.hpp +++ b/src/wrapper/wrap_cl.hpp @@ -1,8 +1,14 @@ #ifndef _AFJHAYYTA_PYOPENCL_HEADER_SEEN_CL_HPP #define _AFJHAYYTA_PYOPENCL_HEADER_SEEN_CL_HPP +// CL 1.2 TODO: cl{Compile,Link}Program, clEnqueueFill{Buffer, Image} +// new-style image creation +// clSetPrintfCallback, Python interface for built-in kernels // {{{ includes + +#define CL_USE_DEPRECATED_OPENCL_1_1_APIS + #ifdef __APPLE__ // Mac ------------------------------------------------------------------------ @@ -77,7 +83,20 @@ EXTRA_MSG); \ } -#define PYOPENCL_GET_EXT_FUN(NAME, VAR) \ +#ifdef CL_VERSION_1_2 + +#define PYOPENCL_GET_EXT_FUN(PLATFORM, NAME, VAR) \ + NAME##_fn VAR \ + = (NAME##_fn) \ + clGetExtensionFunctionAddressForPlatform(PLATFORM, #NAME); \ + \ + if (!VAR) \ + throw error(#NAME, CL_INVALID_VALUE, #NAME \ + "not available"); + +#else + +#define PYOPENCL_GET_EXT_FUN(PLATFORM, NAME, VAR) \ NAME##_fn VAR \ = (NAME##_fn) \ clGetExtensionFunctionAddress(#NAME); \ @@ -86,6 +105,7 @@ throw error(#NAME, CL_INVALID_VALUE, #NAME \ "not available"); +#endif // }}} @@ -221,6 +241,9 @@ py::extract(evt)().data(); \ } +#define PYOPENCL_WAITLIST_ARGS \ + num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front() + #define PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, obj) \ try \ { \ @@ -378,46 +401,83 @@ namespace pyopencl // {{{ device class device : boost::noncopyable { + public: + enum reference_type_t { + REF_NOT_OWNABLE, + REF_FISSION_EXT, +#ifdef CL_VERSION_1_2 + REF_CL_1_2, +#endif + }; private: cl_device_id m_device; - bool m_ownable_reference; + reference_type_t m_ref_type; public: device(cl_device_id did) - : m_device(did), m_ownable_reference(false) + : m_device(did), m_ref_type(REF_NOT_OWNABLE) { } - device(cl_device_id did, bool retain, bool ownable_reference=false) - : m_device(did), m_ownable_reference(ownable_reference) + device(cl_device_id did, bool retain, reference_type_t ref_type=REF_NOT_OWNABLE) + : m_device(did), m_ref_type(ref_type) { - if (ownable_reference) + if (retain && ref_type != REF_NOT_OWNABLE) { -#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION) - if (retain) + if (false) + { } +#if (defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION)) + else if (ref_type == REF_FISSION_EXT) { - PYOPENCL_GET_EXT_FUN( +#ifdef CL_VERSION_1_2 + cl_platform_id plat; + PYOPENCL_CALL_GUARDED(clGetDeviceInfo, (m_device, CL_DEVICE_PLATFORM, + sizeof(plat), &plat, NULL)); +#endif + + PYOPENCL_GET_EXT_FUN(plat, clRetainDeviceEXT, retain_func); PYOPENCL_CALL_GUARDED(retain_func, (did)); } -#else - throw error("Device", CL_INVALID_VALUE, - "cannot own references to devices when device fission is not available"); #endif + +#ifdef CL_VERSION_1_2 + else if (ref_type == REF_CL_1_2) + { + PYOPENCL_CALL_GUARDED(clRetainDevice, (did)); + } +#endif + + else + throw error("Device", CL_INVALID_VALUE, + "cannot own references to devices when device fission or CL 1.2 is not available"); } } ~device() { + if (false) + { } #if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION) - if (m_ownable_reference) + else if (m_ref_type == REF_FISSION_EXT) { - PYOPENCL_GET_EXT_FUN( +#ifdef CL_VERSION_1_2 + cl_platform_id plat; + PYOPENCL_CALL_GUARDED(clGetDeviceInfo, (m_device, CL_DEVICE_PLATFORM, + sizeof(plat), &plat, NULL)); +#endif + + PYOPENCL_GET_EXT_FUN(plat, clReleaseDeviceEXT, release_func); PYOPENCL_CALL_GUARDED_CLEANUP(release_func, (m_device)); } #endif + +#ifdef CL_VERSION_1_2 + else if (m_ref_type == REF_CL_1_2) + PYOPENCL_CALL_GUARDED(clReleaseDevice, (m_device)); +#endif } cl_device_id data() const @@ -549,18 +609,80 @@ namespace pyopencl } case CL_DEVICE_REFERENCE_COUNT_EXT: DEV_GET_INT_INF(cl_uint); #endif +#ifdef CL_VERSION_1_2 + case CL_DEVICE_LINKER_AVAILABLE: DEV_GET_INT_INF(cl_bool); + case CL_DEVICE_BUILT_IN_KERNELS: + PYOPENCL_GET_STR_INFO(Device, m_device, param_name); + case CL_DEVICE_IMAGE_MAX_BUFFER_SIZE: DEV_GET_INT_INF(size_t); + case CL_DEVICE_IMAGE_MAX_ARRAY_SIZE: DEV_GET_INT_INF(size_t); + case CL_DEVICE_PARENT_DEVICE: + PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_device_id, device); + case CL_DEVICE_PARTITION_MAX_SUB_DEVICES: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_PARTITION_TYPE: + case CL_DEVICE_PARTITION_PROPERTIES: + { + std::vector result; + PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); + PYOPENCL_RETURN_VECTOR(cl_device_partition_property, result); + } + case CL_DEVICE_PARTITION_AFFINITY_DOMAIN: + { + std::vector result; + PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); + PYOPENCL_RETURN_VECTOR(cl_device_affinity_domain, result); + } + case CL_DEVICE_REFERENCE_COUNT: DEV_GET_INT_INF(cl_uint); + case CL_DEVICE_PREFERRED_INTEROP_USER_SYNC: DEV_GET_INT_INF(cl_bool); + case CL_DEVICE_PRINTF_BUFFER_SIZE: DEV_GET_INT_INF(cl_bool); +#endif default: throw error("Device.get_info", CL_INVALID_VALUE); } } -#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION) +#ifdef CL_VERSION_1_2 py::list create_sub_devices(py::object py_properties) + { + std::vector properties; + + COPY_PY_LIST(cl_device_partition_property, properties); + properties.push_back(0); + + cl_device_partition_property *props_ptr + = properties.empty( ) ? NULL : &properties.front(); + + cl_uint num_entries; + PYOPENCL_CALL_GUARDED(clCreateSubDevices, + (m_device, props_ptr, 0, NULL, &num_entries)); + + std::vector result; + result.resize(num_entries); + + PYOPENCL_CALL_GUARDED(clCreateSubDevices, + (m_device, props_ptr, num_entries, &result.front(), NULL)); + + py::list py_result; + BOOST_FOREACH(cl_device_id did, result) + py_result.append(handle_from_new_ptr( + new pyopencl::device(did, /*retain*/true, + device::REF_CL_1_2))); + return py_result; + } +#endif + +#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION) + py::list create_sub_devices_ext(py::object py_properties) { std::vector properties; - PYOPENCL_GET_EXT_FUN(clCreateSubDevicesEXT, create_sub_dev); +#ifdef CL_VERSION_1_2 + cl_platform_id plat; + PYOPENCL_CALL_GUARDED(clGetDeviceInfo, (m_device, CL_DEVICE_PLATFORM, + sizeof(plat), &plat, NULL)); +#endif + + PYOPENCL_GET_EXT_FUN(plat, clCreateSubDevicesEXT, create_sub_dev); COPY_PY_LIST(cl_device_partition_property_ext, properties); properties.push_back(CL_PROPERTIES_LIST_END_EXT); @@ -581,10 +703,12 @@ namespace pyopencl py::list py_result; BOOST_FOREACH(cl_device_id did, result) py_result.append(handle_from_new_ptr( - new pyopencl::device(did, /*retain*/false, /*ownable*/true))); + new pyopencl::device(did, /*retain*/true, + device::REF_FISSION_EXT))); return py_result; } #endif + }; @@ -1114,18 +1238,31 @@ namespace pyopencl py::extract(evt)().data(); PYOPENCL_CALL_GUARDED_THREADED(clWaitForEvents, ( - num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front())); + PYOPENCL_WAITLIST_ARGS)); } inline - event *enqueue_marker(command_queue &cq) + event *enqueue_marker(command_queue &cq, + py::object py_wait_for) { + PYOPENCL_PARSE_WAIT_FOR; cl_event evt; + +#ifdef CL_VERSION_1_2 + PYOPENCL_CALL_GUARDED(clEnqueueMarkerWithWaitList, ( + cq.data(), PYOPENCL_WAITLIST_ARGS, &evt)); +#else + if (num_events_in_wait_list) + { + PYOPENCL_CALL_GUARDED(clEnqueueWaitForEvents, ( + cq.data(), PYOPENCL_WAITLIST_ARGS)); + } PYOPENCL_CALL_GUARDED(clEnqueueMarker, ( cq.data(), &evt)); +#endif PYOPENCL_RETURN_NEW_EVENT(evt); } @@ -1134,9 +1271,41 @@ namespace pyopencl + inline + event *enqueue_barrier(command_queue &cq, + py::object py_wait_for) + { + PYOPENCL_PARSE_WAIT_FOR; + cl_event evt; + +#ifdef CL_VERSION_1_2 + PYOPENCL_CALL_GUARDED(clEnqueueBarrierWithWaitList, + (cq.data(), PYOPENCL_WAITLIST_ARGS, &evt)); + +#else + if (num_events_in_wait_list) + { + PYOPENCL_CALL_GUARDED(clEnqueueWaitForEvents, ( + cq.data(), PYOPENCL_WAITLIST_ARGS)); + } + + PYOPENCL_CALL_GUARDED(clEnqueueBarrier, (cq.data())); + + PYOPENCL_CALL_GUARDED(clEnqueueMarker, ( + cq.data(), &evt)); +#endif + + PYOPENCL_RETURN_NEW_EVENT(evt); + } + + + + inline void enqueue_wait_for_events(command_queue &cq, py::object py_events) { + PYOPENCL_DEPRECATED("enqueue_wait_for_events", "2013.1", ); + cl_uint num_events = 0; std::vector event_list(len(py_events)); @@ -1151,15 +1320,6 @@ namespace pyopencl - inline - void enqueue_barrier(command_queue &cq) - { - PYOPENCL_CALL_GUARDED(clEnqueueBarrier, (cq.data())); - } - - - - #ifdef CL_VERSION_1_1 class user_event : public event { @@ -1204,6 +1364,8 @@ namespace pyopencl // {{{ memory_object + py::object create_mem_object_wrapper(cl_mem mem); + class memory_object_holder { public: @@ -1283,16 +1445,53 @@ namespace pyopencl }; +#ifdef CL_VERSION_1_2 + inline + event *enqueue_migrate_mem_objects( + command_queue &cq, + py::object py_mem_objects, + cl_mem_migration_flags flags, + py::object py_wait_for) + { + PYOPENCL_PARSE_WAIT_FOR; + + std::vector mem_objects; + PYTHON_FOREACH(mo, py_mem_objects) + mem_objects.push_back(py::extract(mo)().data()); + + cl_event evt; + PYOPENCL_CALL_GUARDED(clEnqueueMigrateMemObjects, ( + cq.data(), + mem_objects.size(), mem_objects.empty( ) ? NULL : &mem_objects.front(), + flags, + PYOPENCL_WAITLIST_ARGS, &evt + )); + PYOPENCL_RETURN_NEW_EVENT(evt); + } +#endif + #ifdef cl_ext_migrate_memobject inline - event *enqueue_migrate_mem_object( + event *enqueue_migrate_mem_object_ext( command_queue &cq, py::object py_mem_objects, cl_mem_migration_flags_ext flags, py::object py_wait_for) { PYOPENCL_PARSE_WAIT_FOR; - PYOPENCL_GET_EXT_FUN( + +#ifdef CL_VERSION_1_2 + // {{{ get platform + cl_device_id dev; + PYOPENCL_CALL_GUARDED(clGetCommandQueueInfo, (cq.data(), CL_QUEUE_DEVICE, + sizeof(dev), &dev, NULL)); + cl_platform_id plat; + PYOPENCL_CALL_GUARDED(clGetDeviceInfo, (cq.data(), CL_DEVICE_PLATFORM, + sizeof(plat), &plat, NULL)); + // }}} +#endif + + PYOPENCL_GET_EXT_FUN(plat, clEnqueueMigrateMemObjectEXT, enqueue_migrate_fn); std::vector mem_objects; @@ -1304,7 +1503,7 @@ namespace pyopencl cq.data(), mem_objects.size(), mem_objects.empty( ) ? NULL : &mem_objects.front(), flags, - num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt + PYOPENCL_WAITLIST_ARGS, &evt )); PYOPENCL_RETURN_NEW_EVENT(evt); } @@ -1514,7 +1713,7 @@ namespace pyopencl mem.data(), PYOPENCL_CAST_BOOL(is_blocking), device_offset, len, buf, - num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt + PYOPENCL_WAITLIST_ARGS, &evt )); PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); } @@ -1553,7 +1752,7 @@ namespace pyopencl mem.data(), PYOPENCL_CAST_BOOL(is_blocking), device_offset, len, buf, - num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt + PYOPENCL_WAITLIST_ARGS, &evt )); PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); } @@ -1585,8 +1784,7 @@ namespace pyopencl src.data(), dst.data(), src_offset, dst_offset, byte_count, - num_events_in_wait_list, - event_wait_list.empty( ) ? NULL : &event_wait_list.front(), + PYOPENCL_WAITLIST_ARGS, &evt )); @@ -1633,7 +1831,7 @@ namespace pyopencl buffer_pitches[0], buffer_pitches[1], host_pitches[0], host_pitches[1], buf, - num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt + PYOPENCL_WAITLIST_ARGS, &evt )); PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); } @@ -1677,7 +1875,7 @@ namespace pyopencl buffer_pitches[0], buffer_pitches[1], host_pitches[0], host_pitches[1], buf, - num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt + PYOPENCL_WAITLIST_ARGS, &evt )); PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); } @@ -1711,8 +1909,7 @@ namespace pyopencl src_origin, dst_origin, region, src_pitches[0], src_pitches[1], dst_pitches[0], dst_pitches[1], - num_events_in_wait_list, - event_wait_list.empty( ) ? NULL : &event_wait_list.front(), + PYOPENCL_WAITLIST_ARGS, &evt )); @@ -1749,8 +1946,31 @@ namespace pyopencl case CL_IMAGE_WIDTH: case CL_IMAGE_HEIGHT: case CL_IMAGE_DEPTH: +#ifdef CL_VERSION_1_2 + case CL_IMAGE_ARRAY_SIZE: +#endif PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, size_t); +#ifdef CL_VERSION_1_2 + case CL_IMAGE_BUFFER: + { + cl_mem param_value; + PYOPENCL_CALL_GUARDED(clGetImageInfo, \ + (data(), param_name, sizeof(param_value), ¶m_value, 0)); + if (param_value == 0) + { + // no associated memory object? no problem. + return py::object(); + } + + return create_mem_object_wrapper(param_value); + } + + case CL_IMAGE_NUM_MIP_LEVELS: + case CL_IMAGE_NUM_SAMPLES: + PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, cl_uint); +#endif + default: throw error("MemoryObject.get_image_info", CL_INVALID_VALUE); } @@ -2020,7 +2240,7 @@ namespace pyopencl img.data(), PYOPENCL_CAST_BOOL(is_blocking), origin, region, row_pitch, slice_pitch, buf, - num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt + PYOPENCL_WAITLIST_ARGS, &evt )); PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); } @@ -2062,7 +2282,7 @@ namespace pyopencl img.data(), PYOPENCL_CAST_BOOL(is_blocking), origin, region, row_pitch, slice_pitch, buf, - num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt + PYOPENCL_WAITLIST_ARGS, &evt )); PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); } @@ -2090,7 +2310,7 @@ namespace pyopencl PYOPENCL_CALL_GUARDED(clEnqueueCopyImage, ( cq.data(), src.data(), dest.data(), src_origin, dest_origin, region, - num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt + PYOPENCL_WAITLIST_ARGS, &evt )); PYOPENCL_RETURN_NEW_EVENT(evt); } @@ -2117,7 +2337,7 @@ namespace pyopencl PYOPENCL_CALL_GUARDED(clEnqueueCopyImageToBuffer, ( cq.data(), src.data(), dest.data(), origin, region, offset, - num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt + PYOPENCL_WAITLIST_ARGS, &evt )); PYOPENCL_RETURN_NEW_EVENT(evt); } @@ -2144,7 +2364,7 @@ namespace pyopencl PYOPENCL_CALL_GUARDED(clEnqueueCopyBufferToImage, ( cq.data(), src.data(), dest.data(), offset, origin, region, - num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt + PYOPENCL_WAITLIST_ARGS, &evt )); PYOPENCL_RETURN_NEW_EVENT(evt); } @@ -2184,7 +2404,7 @@ namespace pyopencl cl_event evt; PYOPENCL_CALL_GUARDED(clEnqueueUnmapMemObject, ( cq->data(), m_mem.data(), m_ptr, - num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt + PYOPENCL_WAITLIST_ARGS, &evt )); m_valid = false; @@ -2223,7 +2443,7 @@ namespace pyopencl cq.data(), buf.data(), PYOPENCL_CAST_BOOL(is_blocking), flags, offset, size_in_bytes, - num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt, + PYOPENCL_WAITLIST_ARGS, &evt, &status_code); if (status_code != CL_SUCCESS) throw pyopencl::error("clEnqueueMapBuffer", status_code); @@ -2288,7 +2508,7 @@ namespace pyopencl cq.data(), img.data(), PYOPENCL_CAST_BOOL(is_blocking), flags, origin, region, &row_pitch, &slice_pitch, - num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt, + PYOPENCL_WAITLIST_ARGS, &evt, &status_code); if (status_code != CL_SUCCESS) throw pyopencl::error("clEnqueueMapImage", status_code); @@ -2395,7 +2615,7 @@ namespace pyopencl class program : boost::noncopyable { public: - enum program_kind_type { KND_UNKNOWN, KND_SOURCE, KND_BINARY }; + enum program_kind_type { KND_UNKNOWN, KND_SOURCE, KND_BINARY, KND_BUILT_IN }; private: cl_program m_program; @@ -2464,6 +2684,7 @@ namespace pyopencl PYOPENCL_RETURN_VECTOR(size_t, result); } case CL_PROGRAM_BINARIES: + // {{{ { std::vector sizes; PYOPENCL_GET_VEC_INFO(Program, m_program, CL_PROGRAM_BINARY_SIZES, sizes); @@ -2503,6 +2724,14 @@ namespace pyopencl } return py_result; } + // }}} +#ifdef CL_VERSION_1_2 + case CL_PROGRAM_NUM_KERNELS: + PYOPENCL_GET_INTEGRAL_INFO(Program, m_program, param_name, + size_t); + case CL_PROGRAM_KERNEL_NAMES: + PYOPENCL_GET_STR_INFO(Program, m_program, param_name); +#endif default: throw error("Program.get_info", CL_INVALID_VALUE); @@ -2524,6 +2753,12 @@ namespace pyopencl case CL_PROGRAM_BUILD_LOG: PYOPENCL_GET_STR_INFO(ProgramBuild, PYOPENCL_FIRST_ARG, param_name); +#ifdef CL_VERSION_1_2 + case CL_PROGRAM_BINARY_TYPE: + PYOPENCL_GET_INTEGRAL_INFO(ProgramBuild, + PYOPENCL_FIRST_ARG, param_name, + cl_program_binary_type); +#endif #undef PYOPENCL_FIRST_ARG default: @@ -2646,12 +2881,61 @@ namespace pyopencl } + +#ifdef CL_VERSION_1_2 + inline + program *create_program_with_built_in_kernels( + context &ctx, + py::object py_devices, + std::string const &kernel_names) + { + std::vector devices; + + int num_devices = len(py_devices); + for (int i = 0; i < num_devices; ++i) + { + devices.push_back( + py::extract(py_devices[i])().data()); + } + + cl_int status_code; + cl_program result = clCreateProgramWithBuiltInKernels( + ctx.data(), num_devices, + devices.empty( ) ? NULL : &devices.front(), + kernel_names.c_str(), &status_code); + PYOPENCL_PRINT_CALL_TRACE("clCreateProgramWithBuiltInKernels"); + if (status_code != CL_SUCCESS) + throw pyopencl::error("clCreateProgramWithBuiltInKernels", status_code); + + try + { + return new program(result, false, program::KND_BUILT_IN); + } + catch (...) + { + clReleaseProgram(result); + throw; + } + } +#endif + + inline void unload_compiler() { + PYOPENCL_DEPRECATED("unload_compiler", "2013.1", ); + PYOPENCL_CALL_GUARDED(clUnloadCompiler, ()); } +#ifdef CL_VERSION_1_2 + inline + void unload_platform_compiler(platform &plat) + { + PYOPENCL_CALL_GUARDED(clUnloadPlatformCompiler, (plat.data())); + } +#endif + // }}} // {{{ kernel @@ -2804,6 +3088,10 @@ namespace pyopencl case CL_KERNEL_PROGRAM: PYOPENCL_GET_OPAQUE_INFO(Kernel, m_kernel, param_name, cl_program, program); +#ifdef CL_VERSION_1_2 + case CL_KERNEL_ATTRIBUTES: + PYOPENCL_GET_STR_INFO(Kernel, m_kernel, param_name); +#endif default: throw error("Kernel.get_info", CL_INVALID_VALUE); } @@ -2848,6 +3136,35 @@ namespace pyopencl #undef PYOPENCL_FIRST_ARG } } + +#ifdef CL_VERSION_1_2 + py::object get_arg_info( + cl_uint arg_index, + cl_kernel_arg_info param_name + ) const + { + switch (param_name) + { +#define PYOPENCL_FIRST_ARG m_kernel, arg_index // hackety hack + case CL_KERNEL_ARG_ADDRESS_QUALIFIER: + PYOPENCL_GET_INTEGRAL_INFO(KernelArg, + PYOPENCL_FIRST_ARG, param_name, + cl_kernel_arg_address_qualifier); + + case CL_KERNEL_ARG_ACCESS_QUALIFIER: + PYOPENCL_GET_INTEGRAL_INFO(KernelArg, + PYOPENCL_FIRST_ARG, param_name, + cl_kernel_arg_access_qualifier); + + case CL_KERNEL_ARG_TYPE_NAME: + case CL_KERNEL_ARG_NAME: + PYOPENCL_GET_STR_INFO(KernelArg, PYOPENCL_FIRST_ARG, param_name); +#undef PYOPENCL_FIRST_ARG + default: + throw error("Kernel.get_arg_info", CL_INVALID_VALUE); + } + } +#endif }; @@ -2943,7 +3260,7 @@ namespace pyopencl global_work_offset_ptr, global_work_size.empty( ) ? NULL : &global_work_size.front(), local_work_size_ptr, - num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt + PYOPENCL_WAITLIST_ARGS, &evt )); PYOPENCL_RETURN_NEW_EVENT(evt); @@ -2966,7 +3283,7 @@ namespace pyopencl PYOPENCL_CALL_GUARDED(clEnqueueTask, ( cq.data(), knl.data(), - num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt + PYOPENCL_WAITLIST_ARGS, &evt )); PYOPENCL_RETURN_NEW_EVENT(evt); @@ -3140,7 +3457,7 @@ namespace pyopencl PYOPENCL_CALL_GUARDED(clEnqueue##What##GLObjects, ( \ cq.data(), \ mem_objects.size(), mem_objects.empty( ) ? NULL : &mem_objects.front(), \ - num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt \ + PYOPENCL_WAITLIST_ARGS, &evt \ )); \ \ PYOPENCL_RETURN_NEW_EVENT(evt); \ @@ -3157,7 +3474,8 @@ namespace pyopencl inline py::object get_gl_context_info_khr( py::object py_properties, - cl_gl_context_info param_name + cl_gl_context_info param_name, + py::object py_platform ) { std::vector props @@ -3170,9 +3488,28 @@ namespace pyopencl void * /* param_value */, size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; - func_ptr_type func_ptr - = (func_ptr_type) clGetExtensionFunctionAddress( + func_ptr_type func_ptr; + +#ifdef CL_VERSION_1_2 + if (py_platform.ptr() != Py_None) + { + platform &plat = py::extract(py_platform); + + func_ptr = (func_ptr_type) clGetExtensionFunctionAddressForPlatform( + plat.data(), "clGetGLContextInfoKHR"); + } + else + { + PYOPENCL_DEPRECATED("get_gl_context_info_khr with platform=None", "2013.1", ); + + func_ptr = (func_ptr_type) clGetExtensionFunctionAddress( + "clGetGLContextInfoKHR"); + } +#else + func_ptr = (func_ptr_type) clGetExtensionFunctionAddress( "clGetGLContextInfoKHR"); +#endif + if (!func_ptr) throw error("Context.get_info", CL_INVALID_PLATFORM, diff --git a/src/wrapper/wrap_cl_part_1.cpp b/src/wrapper/wrap_cl_part_1.cpp index eaa62ae65646d022ad664062f476590c42c76053..8c22898964dec2495d2df772263a4885100f493e 100644 --- a/src/wrapper/wrap_cl_part_1.cpp +++ b/src/wrapper/wrap_cl_part_1.cpp @@ -40,6 +40,9 @@ void pyopencl_expose_part_1() .def(py::self != py::self) .def("__hash__", &cls::hash) #if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION) + .DEF_SIMPLE_METHOD(create_sub_devices_ext) +#endif +#ifdef CL_VERSION_1_2 .DEF_SIMPLE_METHOD(create_sub_devices) #endif ; @@ -113,9 +116,13 @@ void pyopencl_expose_part_1() DEF_SIMPLE_FUNCTION(wait_for_events); py::def("enqueue_marker", enqueue_marker, + (py::arg("queue"), py::arg("wait_for")=py::object()), + py::return_value_policy()); + py::def("enqueue_barrier", enqueue_barrier, + (py::arg("queue"), py::arg("wait_for")=py::object()), py::return_value_policy()); + DEF_SIMPLE_FUNCTION(enqueue_wait_for_events); - DEF_SIMPLE_FUNCTION(enqueue_barrier); #ifdef CL_VERSION_1_1 { @@ -157,8 +164,17 @@ void pyopencl_expose_part_1() ; } +#ifdef CL_VERSION_1_2 + py::def("enqueue_migrate_mem_objects", enqueue_migrate_mem_objects, + (py::args("queue", "mem_objects"), + py::arg("flags")=0, + py::arg("wait_for")=py::object() + ), + py::return_value_policy()); +#endif + #ifdef cl_ext_migrate_memobject - py::def("enqueue_migrate_mem_object", enqueue_migrate_mem_object, + py::def("enqueue_migrate_mem_object_ext", enqueue_migrate_mem_object_ext, (py::args("queue", "mem_objects"), py::arg("flags")=0, py::arg("wait_for")=py::object() diff --git a/src/wrapper/wrap_cl_part_2.cpp b/src/wrapper/wrap_cl_part_2.cpp index c053e3df92bacc4dc45a66dcd632960f51d042cf..fad9900bc4b624265295ed65c336aca467112c08 100644 --- a/src/wrapper/wrap_cl_part_2.cpp +++ b/src/wrapper/wrap_cl_part_2.cpp @@ -122,6 +122,7 @@ void pyopencl_expose_part_2() .value("UNKNOWN", cls::KND_UNKNOWN) .value("SOURCE", cls::KND_SOURCE) .value("BINARY", cls::KND_BINARY) + .value("BUILT_IN", cls::KND_BUILT_IN) ; py::class_("_Program", py::no_init) @@ -133,6 +134,13 @@ void pyopencl_expose_part_2() create_program_with_binary, py::default_call_policies(), py::args("context", "devices", "binaries"))) +#ifdef CL_VERSION_1_2 + .def("create_with_built_in_kernels", + create_program_with_built_in_kernels, + py::args("context", "devices", "kernel_names"), + py::return_value_policy()) + .staticmethod("create_with_built_in_kernels") +#endif .DEF_SIMPLE_METHOD(kind) .DEF_SIMPLE_METHOD(get_info) .DEF_SIMPLE_METHOD(get_build_info) @@ -147,6 +155,13 @@ void pyopencl_expose_part_2() } py::def("unload_compiler", unload_compiler); +#ifdef CL_VERSION_1_2 + py::def("unload_platform_compiler", unload_platform_compiler); +#endif + + // }}} + + // {{{ kernel { typedef kernel cls; @@ -155,6 +170,9 @@ void pyopencl_expose_part_2() .DEF_SIMPLE_METHOD(get_info) .DEF_SIMPLE_METHOD(get_work_group_info) .DEF_SIMPLE_METHOD(set_arg) +#ifdef CL_VERSION_1_2 + .DEF_SIMPLE_METHOD(get_arg_info) +#endif .add_property("obj_ptr", &cls::obj_ptr) .def(py::self == py::self) .def(py::self != py::self) @@ -247,7 +265,7 @@ void pyopencl_expose_part_2() #if defined(cl_khr_gl_sharing) && (cl_khr_gl_sharing >= 1) py::def("get_gl_context_info_khr", get_gl_context_info_khr, - py::args("properties", "param_name")); + (py::args("properties", "param_name"), py::arg("platform")=py::object())); #endif #endif diff --git a/src/wrapper/wrap_constants.cpp b/src/wrapper/wrap_constants.cpp index 2e2813c756c667ffd272dd0eee0abc1990108b55..ef44728e66cf530f802a150fb817717fdf481092 100644 --- a/src/wrapper/wrap_constants.cpp +++ b/src/wrapper/wrap_constants.cpp @@ -75,7 +75,7 @@ namespace class mem_migration_flags { }; class device_partition_property { }; - class affinity_domain { }; + class device_affinity_domain { }; class device_partition_property_ext { }; class affinity_domain_ext { }; @@ -619,7 +619,7 @@ void pyopencl_expose_constants() ADD_ATTR(KERNEL_ARG_, ADDRESS_QUALIFIER); ADD_ATTR(KERNEL_ARG_, ACCESS_QUALIFIER); ADD_ATTR(KERNEL_ARG_, TYPE_NAME); - ADD_ATTR(KERNEL_ARG_, ARG_NAME); + ADD_ATTR(KERNEL_ARG_, NAME); #endif } @@ -778,14 +778,14 @@ void pyopencl_expose_constants() } { - py::class_ cls("affinity_domain", py::no_init); + py::class_ cls("device_affinity_domain", py::no_init); #ifdef CL_VERSION_1_2 - ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, NUMA, _EXT); - ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, L4_CACHE, _EXT); - ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, L3_CACHE, _EXT); - ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, L2_CACHE, _EXT); - ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, L1_CACHE, _EXT); - ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, NEXT_PARTITIONABLE, _EXT); + ADD_ATTR(DEVICE_AFFINITY_DOMAIN_, NUMA); + ADD_ATTR(DEVICE_AFFINITY_DOMAIN_, L4_CACHE); + ADD_ATTR(DEVICE_AFFINITY_DOMAIN_, L3_CACHE); + ADD_ATTR(DEVICE_AFFINITY_DOMAIN_, L2_CACHE); + ADD_ATTR(DEVICE_AFFINITY_DOMAIN_, L1_CACHE); + ADD_ATTR(DEVICE_AFFINITY_DOMAIN_, NEXT_PARTITIONABLE); #endif }