diff --git a/doc/source/reference.rst b/doc/source/reference.rst index 30bb4417b3655aeb182dc23421d72bc265cf0b8e..3f608bbb23980e293062e92be3c2c39e7669a6ad 100644 --- a/doc/source/reference.rst +++ b/doc/source/reference.rst @@ -93,10 +93,16 @@ Platforms, Devices and Contexts Two instances of this class may be compared using *=="* and *"!="*. -.. class:: Context(devices, properties=None) +.. class:: Context(devices, properties=None, dev_type=None) Create a new context. *properties* is a list of key-value tuples, where each key must be one of :class:`context_properties`. + Exactly one of *devices* and *dev_type* must be not `None`, where + *devices* is a list of :class:`Device` instances, and + *dev_type* is one of the :class:`device_type` constants. + + .. versionchanged:: 0.91.2 + Constructor arguments *dev_type* added. .. attribute:: info @@ -110,8 +116,6 @@ Platforms, Devices and Contexts |comparable| -.. function:: create_context_from_type(dev_type, properties=[]) - Command Queues and Events ------------------------- diff --git a/examples/demo.py b/examples/demo.py index 863588d3684ac7085ae8151b17a53aed8c2482ea..f93054f8a1a371b84fc8a82c05b64925781edd1f 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -5,7 +5,7 @@ import numpy.linalg as la a = numpy.random.rand(50000).astype(numpy.float32) b = numpy.random.rand(50000).astype(numpy.float32) -ctx = cl.create_context_from_type(cl.device_type.ALL) +ctx = cl.Context(dev_type=cl.device_type.ALL) queue = cl.CommandQueue(ctx) mf = cl.mem_flags diff --git a/examples/narray.py b/examples/narray.py index 3f333fe5d23ef133764920bf707693408a830ce4..a91a4597c9b1d172c7acf760711fdbf8c18f242c 100644 --- a/examples/narray.py +++ b/examples/narray.py @@ -3,7 +3,7 @@ import pyopencl as cl import numpy as np demo_r = np.empty( (500,5), dtype=np.uint32) -ctx = cl.create_context_from_type(cl.device_type.GPU) +ctx = cl.Context(dev_type=cl.device_type.ALL) queue = cl.CommandQueue(ctx) mf = cl.mem_flags diff --git a/pyopencl/__init__.py b/pyopencl/__init__.py index 5f85dfa5109401b992a854f1517fa21de0de0c90..e9864132294e0016b8ba7603b55ff9db1a4a839e 100644 --- a/pyopencl/__init__.py +++ b/pyopencl/__init__.py @@ -16,7 +16,7 @@ def _add_functionality(): ], _cl.Device: [ (_cl.Device.get_info, _cl.device_info) - ], + ], _cl.Context: [ (_cl.Context.get_info, _cl.context_info), ], @@ -30,7 +30,7 @@ def _add_functionality(): (MemoryObject.get_info,_cl.mem_info), ], _cl.Image: [ - (Image.get_image_info, _cl.image_info), + (Image.get_image_info, _cl.image_info), (MemoryObject.get_info,_cl.mem_info), ], _cl.Kernel: [ @@ -57,7 +57,7 @@ def _add_functionality(): name_to_info = dict( (intern(info_name.lower()), (info_method, info_value)) for info_method, info_class in info_classes[::-1] - for info_name, info_value in + for info_name, info_value in info_class.__dict__.iteritems() if info_name != "to_string" and not info_name.startswith("_") ) @@ -90,7 +90,7 @@ def _add_functionality(): # Context ----------------------------------------------------------------- def context_repr(self): - return "" % (self.obj_ptr, + return "" % (self.obj_ptr, ", ".join(repr(dev) for dev in self.devices)) Context.__repr__ = context_repr @@ -208,6 +208,12 @@ _add_functionality() # backward compatibility ------------------------------------------------------ +def create_context_from_type(dev_type, properties=None): + from warnings import warn + warn("create_context_from_type is deprecated. Use the Context() constructor instead.", + DeprecationWarning) + return Context(dev_type=dev_type, properties=properties) + def create_image_2d(context, flags, format, width, height, pitch=0, host_buffer=None): from warnings import warn warn("create_image_2d is deprecated. Use the Image() constructor instead.", @@ -219,7 +225,7 @@ def create_image_3d(context, flags, format, width, height, depth, from warnings import warn warn("create_image_3d is deprecated. Use the Image() constructor instead.", DeprecationWarning) - return Image(context, flags, format, (width, height, depth), + return Image(context, flags, format, (width, height, depth), (row_pitch, slice_pitch), host_buffer) def create_program_with_source(context, source): diff --git a/src/wrapper/wrap_cl.cpp b/src/wrapper/wrap_cl.cpp index 2c3932c34560e5a99af0c95b17064b206c115f43..00cb6ad60032bf4ad3b97ac2d47271684e4c9659 100644 --- a/src/wrapper/wrap_cl.cpp +++ b/src/wrapper/wrap_cl.cpp @@ -427,8 +427,13 @@ BOOST_PYTHON_MODULE(_cl) { typedef context cls; - py::class_("Context", - py::init >()) + py::class_("Context", py::no_init) + .def("__init__", make_constructor(create_context, + py::default_call_policies(), + (py::arg("devices")=py::object(), + py::arg("properties")=py::object(), + py::arg("dev_type")=py::object() + ))) .DEF_SIMPLE_METHOD(get_info) .add_property("obj_ptr", &cls::obj_ptr) .def(py::self == py::self) @@ -436,10 +441,6 @@ BOOST_PYTHON_MODULE(_cl) ; } - py::def("create_context_from_type", create_context_from_type, - (py::arg("dev_type"), py::arg("properties")=py::object()), - py::return_value_policy()); - { typedef command_queue cls; py::class_("CommandQueue", diff --git a/src/wrapper/wrap_cl.hpp b/src/wrapper/wrap_cl.hpp index adaa128545a29a12ad6fca8030cd05343dd1f6c0..c50695c5996349b0fb45e5381aa0b1cbb1852a0a 100644 --- a/src/wrapper/wrap_cl.hpp +++ b/src/wrapper/wrap_cl.hpp @@ -526,36 +526,6 @@ namespace pyopencl // context ------------------------------------------------------------------ -#define PYOPENCL_PARSE_CONTEXT_PROPERTIES \ - cl_context_properties *props_ptr = 0; \ - std::vector props; \ - \ - if (py_properties.ptr() != Py_None) \ - { \ - PYTHON_FOREACH(prop_tuple, py_properties) \ - { \ - if (len(prop_tuple) != 2) \ - throw error("Context", CL_INVALID_VALUE, "property tuple must have length 2"); \ - cl_context_properties prop = \ - py::extract(prop_tuple[0]); \ - props.push_back(prop); \ - \ - if (prop == CL_CONTEXT_PLATFORM) \ - { \ - py::extract value(prop_tuple[1]); \ - props.push_back( \ - reinterpret_cast(value().data())); \ - } \ - else \ - throw error("Context", CL_INVALID_VALUE, "invalid context property"); \ - } \ - props.push_back(0); \ - props_ptr = &props.front(); \ - } - - - - class context : public boost::noncopyable { private: @@ -569,30 +539,6 @@ namespace pyopencl PYOPENCL_CALL_GUARDED(clRetainContext, (ctx)); } - context( - py::list py_devices, - py::object py_properties=py::object()) - { - PYOPENCL_PARSE_CONTEXT_PROPERTIES; - - std::vector devices; - PYTHON_FOREACH(py_dev, py_devices) - { - py::extract dev(py_dev); - devices.push_back(dev().data()); - } - - cl_int status_code; - m_context = clCreateContext( - props_ptr, - devices.size(), - &devices.front(), - 0, 0, &status_code); - - PYOPENCL_PRINT_CALL_TRACE("clCreateContext"); - if (status_code != CL_SUCCESS) - throw pyopencl::error("Context", status_code); - } ~context() { @@ -672,21 +618,78 @@ namespace pyopencl - context *create_context_from_type( - cl_device_type dev_type, - py::object py_properties) + context *create_context(py::object py_devices, py::object py_properties, + py::object py_dev_type) { - PYOPENCL_PARSE_CONTEXT_PROPERTIES; + // parse context properties + cl_context_properties *props_ptr = 0; + std::vector props; + + if (py_properties.ptr() != Py_None) + { + PYTHON_FOREACH(prop_tuple, py_properties) + { + if (len(prop_tuple) != 2) + throw error("Context", CL_INVALID_VALUE, "property tuple must have length 2"); + cl_context_properties prop = + py::extract(prop_tuple[0]); + props.push_back(prop); + + if (prop == CL_CONTEXT_PLATFORM) + { + py::extract value(prop_tuple[1]); + props.push_back( + reinterpret_cast(value().data())); + } + else + throw error("Context", CL_INVALID_VALUE, "invalid context property"); + } + props.push_back(0); + props_ptr = &props.front(); + } cl_int status_code; - cl_context ctx = clCreateContextFromType( - props_ptr, - dev_type, - 0, 0, &status_code); - PYOPENCL_PRINT_CALL_TRACE("clCreateContextFromType"); + cl_context ctx; + + // from device list + if (py_devices.ptr() != Py_None) + { + if (py_dev_type.ptr() != Py_None) + throw error("Context", CL_INVALID_VALUE, + "one of 'devices' or 'dev_type' must be None"); + + std::vector devices; + PYTHON_FOREACH(py_dev, py_devices) + { + py::extract dev(py_dev); + devices.push_back(dev().data()); + } + + ctx = clCreateContext( + props_ptr, + devices.size(), + &devices.front(), + 0, 0, &status_code); + + PYOPENCL_PRINT_CALL_TRACE("clCreateContext"); + } + // from dev_type + else if (py_dev_type.ptr() != Py_None) + { + py::extract dev_type(py_dev_type); + ctx = clCreateContextFromType( + props_ptr, dev_type, + 0, 0, &status_code); + + PYOPENCL_PRINT_CALL_TRACE("clCreateContextFromType"); + } + else + throw error("Context", CL_INVALID_VALUE, + "one of 'devices' or 'dev_type' must be not None"); + if (status_code != CL_SUCCESS) - throw pyopencl::error("clCreateContextFromType", status_code); + throw pyopencl::error("Context", status_code); try { @@ -694,13 +697,14 @@ namespace pyopencl } catch (...) { - PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseContext, (ctx)); + PYOPENCL_CALL_GUARDED(clReleaseContext, (ctx)); throw; } } + // command_queue ------------------------------------------------------------ class command_queue { @@ -2063,7 +2067,6 @@ namespace pyopencl - py::list create_kernels_in_program(program &pgm) { py::list result; @@ -2083,8 +2086,6 @@ namespace pyopencl - - event *enqueue_nd_range_kernel( command_queue &cq, kernel &knl,