diff --git a/doc/source/misc.rst b/doc/source/misc.rst index 3bdc94318829b5221b7a14d714c9627f0b4ecafa..ab349c4c8bddae5f9b430340f7d6857883fb0b58 100644 --- a/doc/source/misc.rst +++ b/doc/source/misc.rst @@ -84,8 +84,9 @@ Version 2011.1 :func:`pyopencl.enqueue_write_image`, :func:`pyopencl.enqueue_map_buffer`, :func:`pyopencl.enqueue_map_image`. -* Add :mod:`pycuda.reduction`. +* Add :mod:`pyopencl.reduction`. * Add :ref:`reductions`. +* Add :meth:`MemoryObject.get_host_array`. Version 0.92 ------------ diff --git a/doc/source/runtime.rst b/doc/source/runtime.rst index 0359c6ddce3a8319a431449f379bc1284f47108c..dd7fd91a9a853e641f996e36cf995e5869c05acb 100644 --- a/doc/source/runtime.rst +++ b/doc/source/runtime.rst @@ -256,16 +256,19 @@ Memory may be used as attributes on instances of this class to directly query info attributes. + .. attribute:: hostbuf + .. method:: get_info(param) See :class:`mem_info` for values of *param*. - .. attribute:: hostbuf + .. method:: release() - Contains the *hostbuf* parameter if the MemoryObject was constructed - with :attr:`mem_flags.USE_HOST_PTR`. + .. method:: get_host_array(shape, dtype, order="C") - .. method:: release() + Return the memory object's associated host memory + area as a :class:`numpy.ndarray` of the given *shape*, + *dtype* and *order*. |comparable| diff --git a/src/wrapper/wrap_cl.hpp b/src/wrapper/wrap_cl.hpp index 510ad6694fb9782279732d1285149f097745d654..719655f9a9c7b89c382dc1201a3fd8ffb7427153 100644 --- a/src/wrapper/wrap_cl.hpp +++ b/src/wrapper/wrap_cl.hpp @@ -2957,7 +2957,8 @@ namespace pyopencl PYOPENCL_GET_INTEGRAL_INFO(MemObject, m_mem, param_name, size_t); case CL_MEM_HOST_PTR: - return m_hostbuf; + 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, m_mem, param_name, cl_uint); @@ -3008,6 +3009,65 @@ namespace pyopencl } } + inline + py::handle<> get_mem_obj_host_array( + py::object mem_obj_py, + py::object shape, py::object dtype, + py::object order_py) + { + memory_object const &mem_obj = + py::extract<memory_object const &>(mem_obj_py); + PyArray_Descr *tp_descr; + if (PyArray_DescrConverter(dtype.ptr(), &tp_descr) != NPY_SUCCEED) + throw py::error_already_set(); + + py::extract<npy_intp> shape_as_int(shape); + std::vector<npy_intp> dims; + + if (shape_as_int.check()) + dims.push_back(shape_as_int()); + else + std::copy( + py::stl_input_iterator<npy_intp>(shape), + py::stl_input_iterator<npy_intp>(), + back_inserter(dims)); + + NPY_ORDER order = PyArray_CORDER; + PyArray_OrderConverter(order_py.ptr(), &order); + + int ary_flags = 0; + if (order == PyArray_FORTRANORDER) + ary_flags |= NPY_FARRAY; + else if (order == PyArray_CORDER) + ary_flags |= NPY_CARRAY; + else + throw std::runtime_error("unrecognized order specifier"); + + void *host_ptr; + size_t mem_obj_size; + PYOPENCL_CALL_GUARDED(clGetMemObjectInfo, + (mem_obj.data(), CL_MEM_HOST_PTR, sizeof(host_ptr), + &host_ptr, 0)); + PYOPENCL_CALL_GUARDED(clGetMemObjectInfo, + (mem_obj.data(), CL_MEM_SIZE, sizeof(mem_obj_size), + &mem_obj_size, 0)); + + py::handle<> result = py::handle<>(PyArray_NewFromDescr( + &PyArray_Type, tp_descr, + dims.size(), &dims.front(), /*strides*/ NULL, + host_ptr, ary_flags, /*obj*/NULL)); + + if (PyArray_NBYTES(result.get()) > mem_obj_size) + throw pyopencl::error("MemoryObject.get_host_array", + CL_INVALID_VALUE, + "Resulting array is larger than memory object."); + + PyArray_BASE(result.get()) = mem_obj_py.ptr(); + Py_INCREF(mem_obj_py.ptr()); + + return result; + } + // }}} } diff --git a/src/wrapper/wrap_cl_part_1.cpp b/src/wrapper/wrap_cl_part_1.cpp index 495d7af8b283c6b62d0bea83ba46ca2ce637b7f5..233f7db05f6131f1e2dac132adce66cf310ce15b 100644 --- a/src/wrapper/wrap_cl_part_1.cpp +++ b/src/wrapper/wrap_cl_part_1.cpp @@ -121,6 +121,8 @@ void pyopencl_expose_part_1() py::class_<cls, boost::noncopyable>("MemoryObject", py::no_init) .DEF_SIMPLE_METHOD(get_info) .DEF_SIMPLE_METHOD(release) + .def("get_host_array", get_mem_obj_host_array, + (py::arg("shape"), py::arg("dtype"), py::arg("order")="C")) .add_property("obj_ptr", &cls::obj_ptr) .add_property("hostbuf", &cls::hostbuf) .def(py::self == py::self)