diff --git a/doc/make_constants.py b/doc/make_constants.py index 0f96b34850f5ac845579f9fe6977a53c366f7fc2..439847830d7aa16379bb9313d75f0539cfd1fe84 100644 --- a/doc/make_constants.py +++ b/doc/make_constants.py @@ -11,6 +11,8 @@ evi = cl.event_info memi = cl.mem_info ctype = cl.command_type memf = cl.mem_flags +dppe = cl.device_partition_property_ext +ade = cl.affinity_domain_ext def get_extra_lines(tup): ext_name, pyopencl_ver = tup @@ -66,6 +68,17 @@ const_ext_lookup = { getattr(devi, "PROFILING_TIMER_OFFSET_AMD", None): ("cl_amd_device_attribute_query", "2011.1"), + + getattr(devi, "PARENT_DEVICE_EXT", None): + ("cl_ext_device_fission", "2011.1"), + getattr(devi, "PARTITION_TYPES_EXT", None): + ("cl_ext_device_fission", "2011.1"), + getattr(devi, "AFFINITY_DOMAINS_EXT", None): + ("cl_ext_device_fission", "2011.1"), + getattr(devi, "REFERENCE_COUNT_EXT", None): + ("cl_ext_device_fission", "2011.1"), + getattr(devi, "PARTITION_STYLE_EXT", None): + ("cl_ext_device_fission", "2011.1"), }, ctxp: { @@ -121,6 +134,24 @@ const_ext_lookup = { memf: { getattr(memf, "USE_PERSISTENT_MEM_AMD", None): ("cl_amd_device_memory_flags", "2011.1"), + }, + dppe: { + getattr(dppe, "EQUALLY", None): ("cl_ext_device_fission", "2011.1"), + getattr(dppe, "BY_COUNTS", None): ("cl_ext_device_fission", "2011.1"), + getattr(dppe, "BY_NAMES", None): ("cl_ext_device_fission", "2011.1"), + getattr(dppe, "BY_AFFINITY_DOMAIN", None): ("cl_ext_device_fission", "2011.1"), + + getattr(dppe, "PROPERTIES_LIST_END", None): ("cl_ext_device_fission", "2011.1"), + getattr(dppe, "PARTITION_BY_COUNTS_LIST_END", None): ("cl_ext_device_fission", "2011.1"), + getattr(dppe, "PARTITION_BY_NAMES_LIST_END", None): ("cl_ext_device_fission", "2011.1"), + }, + ade: { + getattr(ade, "L1_CACHE", None): ("cl_ext_device_fission", "2011.1"), + getattr(ade, "L2_CACHE", None): ("cl_ext_device_fission", "2011.1"), + getattr(ade, "L3_CACHE", None): ("cl_ext_device_fission", "2011.1"), + getattr(ade, "L4_CACHE", None): ("cl_ext_device_fission", "2011.1"), + getattr(ade, "NUMA", None): ("cl_ext_device_fission", "2011.1"), + getattr(ade, "NEXT_FISSIONABLE", None): ("cl_ext_device_fission", "2011.1"), } } try: diff --git a/doc/source/misc.rst b/doc/source/misc.rst index 7edfff082751739d90c54be5607448790ba4149e..20a248ece84d3b11efa1f75360263765ffbd6182 100644 --- a/doc/source/misc.rst +++ b/doc/source/misc.rst @@ -98,6 +98,7 @@ Version 2011.1 * Add :attr:`pyopencl.array.Array.strides`, :attr:`pyopencl.array.Array.flags`. Allow the creation of arrys in C and Fortran order. * Add :func:`pyopencl.enqueue_copy`. Deprecate all other transfer functions. +* Add support for numerous extensions, among them device fission. Version 0.92 ------------ diff --git a/doc/source/runtime.rst b/doc/source/runtime.rst index 189323fbb0856fc415aaa7f77631a670e4ed789e..509df45b182ea6aa8effced4bac6356a4b4e8337 100644 --- a/doc/source/runtime.rst +++ b/doc/source/runtime.rst @@ -147,6 +147,24 @@ Platforms, Devices and Contexts See :class:`context_info` for values of *param*. + .. method:: create_sub_devices(properties) + + *properties* is an array of one (or more) of the forms:: + + [ dppe.EQUALLY, 8] + [ dppe.BY_COUNTS, 5, 7, 9, dppe.PARTITION_BY_COUNTS_LIST_END] + [ dppe.BY_NAMES, 5, 7, 9, dppe.PARTITION_BY_NAMES_LIST_END] + [ dppe.BY_AFFINITY_DOMAIN, ad.L1_CACHE] + + where `dppe` represents :class:`device_partition_property_ext` + and `ad` represent :class:`affinity_domain_ext`. + + `PROPERTIES_LIST_END_EXT` is added automatically. + + Only available with the `cl_ext_device_fission` extension. + + .. versionadded:: 2011.1 + |comparable| .. function:: create_some_context(interactive=True) diff --git a/src/wrapper/wrap_cl.hpp b/src/wrapper/wrap_cl.hpp index 1b1580a870df5b867eb550965bf98df75cc3ad10..45865d455c7c3d233a40b5a91cf26c0c729e03eb 100644 --- a/src/wrapper/wrap_cl.hpp +++ b/src/wrapper/wrap_cl.hpp @@ -151,8 +151,11 @@ CL_TYPE param_value; \ PYOPENCL_CALL_GUARDED(clGet##WHAT##Info, \ (FIRST_ARG, SECOND_ARG, sizeof(param_value), ¶m_value, 0)); \ - return py::object(handle_from_new_ptr( \ - new TYPE(param_value, /*retain*/ true))); \ + if (param_value) \ + return py::object(handle_from_new_ptr( \ + new TYPE(param_value, /*retain*/ true))); \ + else \ + return py::object(); \ } #define PYOPENCL_GET_VEC_INFO(WHAT, FIRST_ARG, SECOND_ARG, RES_VEC) \ @@ -342,6 +345,12 @@ namespace pyopencl case CL_INVALID_GLOBAL_WORK_SIZE: return "invalid global work size"; #endif +#ifdef cl_ext_device_fission + case CL_DEVICE_PARTITION_FAILED_EXT: return "device partition failed"; + case CL_INVALID_PARTITION_COUNT_EXT: return "invalid partition count"; + case CL_INVALID_PARTITION_NAME_EXT: return "invalid partition name"; +#endif + default: return "invalid/unknown error code"; } } @@ -435,15 +444,55 @@ namespace pyopencl { private: cl_device_id m_device; + bool m_ownable_reference; public: device(cl_device_id did) - : m_device(did) + : m_device(did), m_ownable_reference(false) { } - device(cl_device_id did, bool /*retain (ignored)*/) - : m_device(did) - { } + device(cl_device_id did, bool retain, bool ownable_reference=false) + : m_device(did), m_ownable_reference(ownable_reference) + { + if (ownable_reference) + { +#ifdef cl_ext_device_fission + if (retain) + { + clRetainDeviceEXT_fn cl_retain_device + = (clRetainDeviceEXT_fn) + clGetExtensionFunctionAddress("clRetainDeviceEXT"); + + if (!cl_retain_device) + throw error("Device", CL_INVALID_VALUE, + "clRetainDeviceEXT not available"); + + PYOPENCL_CALL_GUARDED(cl_retain_device, (did)); + } +#else + throw error("Device", CL_INVALID_VALUE, + "cannot own references to devices when device fission is not available"); +#endif + } + } + + ~device() + { +#ifdef cl_ext_device_fission + if (m_ownable_reference) + { + clReleaseDeviceEXT_fn cl_release_device + = (clReleaseDeviceEXT_fn) + clGetExtensionFunctionAddress("clReleaseDeviceEXT"); + + if (!cl_release_device) + throw error("Device", CL_INVALID_VALUE, + "clReleaseDeviceEXT not available"); + + PYOPENCL_CALL_GUARDED_CLEANUP(cl_release_device, (m_device)); + } +#endif + } cl_device_id data() const { @@ -561,11 +610,61 @@ namespace pyopencl case CL_DEVICE_INTEGRATED_MEMORY_NV: DEV_GET_INT_INF(cl_bool); #endif +#ifdef cl_ext_device_fission + case CL_DEVICE_PARENT_DEVICE_EXT: + PYOPENCL_GET_OPAQUE_INFO(Device, m_device, param_name, cl_device_id, device); + case CL_DEVICE_PARTITION_TYPES_EXT: + case CL_DEVICE_AFFINITY_DOMAINS_EXT: + case CL_DEVICE_PARTITION_STYLE_EXT: + { + std::vector result; + PYOPENCL_GET_VEC_INFO(Device, m_device, param_name, result); + PYOPENCL_RETURN_VECTOR(cl_device_partition_property_ext, result); + } + case CL_DEVICE_REFERENCE_COUNT_EXT: DEV_GET_INT_INF(cl_uint); +#endif default: throw error("Device.get_info", CL_INVALID_VALUE); } } + +#ifdef cl_ext_device_fission + py::list create_sub_devices(py::object py_properties) + { + std::vector properties; + + clCreateSubDevicesEXT_fn cl_create_sub_devices + = (clCreateSubDevicesEXT_fn) + clGetExtensionFunctionAddress("clCreateSubDevicesEXT"); + + if (!cl_create_sub_devices) + throw error("Device.create_sub_devices", CL_INVALID_VALUE, + "clCreateSubDevicesEXT not available"); + + COPY_PY_LIST(cl_device_partition_property_ext, properties); + properties.push_back(CL_PROPERTIES_LIST_END_EXT); + + cl_device_partition_property_ext *props_ptr + = properties.empty( ) ? NULL : &properties.front(); + + cl_uint num_entries; + PYOPENCL_CALL_GUARDED(cl_create_sub_devices, + (m_device, props_ptr, 0, NULL, &num_entries)); + + std::vector result; + result.resize(num_entries); + + PYOPENCL_CALL_GUARDED(cl_create_sub_devices, + (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*/false, /*ownable*/true))); + return py_result; + } +#endif }; diff --git a/src/wrapper/wrap_cl_part_1.cpp b/src/wrapper/wrap_cl_part_1.cpp index f7a7dddbf9a4d0f0191bca9f3f6dc9d6d7011d1c..7121fb7cee5500618869be7e79a0eb0394bd5be4 100644 --- a/src/wrapper/wrap_cl_part_1.cpp +++ b/src/wrapper/wrap_cl_part_1.cpp @@ -37,6 +37,9 @@ void pyopencl_expose_part_1() .add_property("obj_ptr", &cls::obj_ptr) .def(py::self == py::self) .def(py::self != py::self) +#ifdef cl_ext_device_fission + .DEF_SIMPLE_METHOD(create_sub_devices) +#endif ; } diff --git a/src/wrapper/wrap_constants.cpp b/src/wrapper/wrap_constants.cpp index a86ac0036fd04542d325f2a0a92ee441743285a7..0a602af4245235a043de1dd75a455afdd3f8436e 100644 --- a/src/wrapper/wrap_constants.cpp +++ b/src/wrapper/wrap_constants.cpp @@ -68,6 +68,9 @@ namespace class profiling_info { }; class buffer_create_type { }; + class device_partition_property_ext { }; + class affinity_domain_ext { }; + class gl_object_type { }; class gl_texture_info { }; // }}} @@ -99,6 +102,8 @@ void pyopencl_expose_constants() // {{{ constants #define ADD_ATTR(PREFIX, NAME) \ cls.attr(#NAME) = CL_##PREFIX##NAME +#define ADD_ATTR_SUFFIX(PREFIX, NAME, SUFFIX) \ + cls.attr(#NAME) = CL_##PREFIX##NAME##SUFFIX { py::class_ cls("platform_info", py::no_init); @@ -204,6 +209,13 @@ void pyopencl_expose_constants() // cl_amd_device_attribute_query #ifdef CL_DEVICE_PROFILING_TIMER_OFFSET_AMD ADD_ATTR(DEVICE_, PROFILING_TIMER_OFFSET_AMD); +#endif +#ifdef cl_ext_device_fission + ADD_ATTR(DEVICE_, PARENT_DEVICE_EXT); + ADD_ATTR(DEVICE_, PARTITION_TYPES_EXT); + ADD_ATTR(DEVICE_, AFFINITY_DOMAINS_EXT); + ADD_ATTR(DEVICE_, REFERENCE_COUNT_EXT); + ADD_ATTR(DEVICE_, PARTITION_STYLE_EXT); #endif } @@ -252,10 +264,6 @@ void pyopencl_expose_constants() ADD_ATTR(CONTEXT_, PROPERTIES); #ifdef CL_VERSION_1_1 ADD_ATTR(CONTEXT_, NUM_DEVICES); -#endif -// cl_amd_offline_devices -#ifdef CL_CONTEXT_OFFLINE_DEVICES_AMD - ADD_ATTR(CONTEXT_, OFFLINE_DEVICES_AMD); #endif } @@ -280,6 +288,10 @@ void pyopencl_expose_constants() #if defined(__APPLE__) && defined(HAVE_GL) ADD_ATTR( ,CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE); #endif /* __APPLE__ */ +// cl_amd_offline_devices +#ifdef CL_CONTEXT_OFFLINE_DEVICES_AMD + ADD_ATTR(CONTEXT_, OFFLINE_DEVICES_AMD); +#endif } { @@ -505,6 +517,31 @@ void pyopencl_expose_constants() } #endif */ + { + py::class_ cls( + "device_partition_property_ext", py::no_init); +#ifdef cl_ext_device_fission + ADD_ATTR_SUFFIX(DEVICE_PARTITION_, EQUALLY, _EXT); + ADD_ATTR_SUFFIX(DEVICE_PARTITION_, BY_COUNTS, _EXT); + ADD_ATTR_SUFFIX(DEVICE_PARTITION_, BY_NAMES, _EXT); + ADD_ATTR_SUFFIX(DEVICE_PARTITION_, BY_AFFINITY_DOMAIN, _EXT); + ADD_ATTR_SUFFIX(, PROPERTIES_LIST_END, _EXT); + ADD_ATTR_SUFFIX(, PARTITION_BY_COUNTS_LIST_END, _EXT); + ADD_ATTR_SUFFIX(, PARTITION_BY_NAMES_LIST_END, _EXT); +#endif + } + + { + py::class_ cls("affinity_domain_ext", py::no_init); +#ifdef cl_ext_device_fission + ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, L1_CACHE, _EXT); + ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, L2_CACHE, _EXT); + ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, L3_CACHE, _EXT); + ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, L4_CACHE, _EXT); + ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, NUMA, _EXT); + ADD_ATTR_SUFFIX(AFFINITY_DOMAIN_, NEXT_FISSIONABLE, _EXT); +#endif + } #ifdef HAVE_GL {