example on manually vectorizing numpy code (closes #27)

This commit is contained in:
Wenzel Jakob 2016-01-18 22:38:52 +01:00
parent 260bc58f57
commit 61587164ed
2 changed files with 55 additions and 1 deletions

View File

@ -473,6 +473,11 @@ follows:
Patient != 0) and ``with_custodian_and_ward_postcall`` (if Nurse/Patient == Patient != 0) and ``with_custodian_and_ward_postcall`` (if Nurse/Patient ==
0) policies from Boost.Python. 0) policies from Boost.Python.
.. seealso::
The file :file:`example/example13.cpp` contains a complete example that
demonstrates using :class:`keep_alive` in more detail.
Implicit type conversions Implicit type conversions
========================= =========================
@ -850,6 +855,55 @@ This can be done with a stateful Lambda closure:
} }
); );
In cases where the computation is too complicated to be reduced to
``vectorize``, it will be necessary to create and access the buffer contents
manually. The following snippet contains a complete example that shows how this
works (the code is somewhat contrived, since it could have been done more
simply using ``vectorize``).
.. code-block:: cpp
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
namespace py = pybind11;
py::array_t<double> add_arrays(py::array_t<double> input1, py::array_t<double> input2) {
auto buf1 = input1.request(), buf2 = input2.request();
if (buf1.ndim != 1 || buf2.ndim != 1)
throw std::runtime_error("Number of dimensions must be one");
if (buf1.shape[0] != buf2.shape[0])
throw std::runtime_error("Input shapes must match");
auto result = py::array(py::buffer_info(
nullptr, /* Pointer to data (nullptr -> ask NumPy to allocate!) */
sizeof(double), /* Size of one item */
py::format_descriptor<double>::value(), /* Buffer format */
buf1.ndim, /* How many dimensions? */
{ buf1.shape[0] }, /* Number of elements for each dimension */
{ sizeof(double) } /* Strides for each dimension */
));
auto buf3 = result.request();
double *ptr1 = (double *) buf1.ptr,
*ptr2 = (double *) buf2.ptr,
*ptr3 = (double *) buf3.ptr;
for (size_t idx = 0; idx < buf1.shape[0]; idx++)
ptr3[idx] = ptr1[idx] + ptr2[idx];
return result;
}
PYBIND11_PLUGIN(test) {
py::module m("test");
m.def("add_arrays", &add_arrays, "Add two NumPy arrays");
return m.ptr();
}
.. seealso:: .. seealso::
The file :file:`example/example10.cpp` contains a complete example that The file :file:`example/example10.cpp` contains a complete example that

View File

@ -27,7 +27,7 @@ Changelog
* Added conversions for additional exception types * Added conversions for additional exception types
* Documentation improvements (using multiple extension modules, smart pointers, * Documentation improvements (using multiple extension modules, smart pointers,
other minor clarifications) other minor clarifications)
* unified infrastructure for parsing variadic arguments in class_ and cpp_function * unified infrastructure for parsing variadic arguments in ``class_`` and cpp_function
* Fixed license text (was: ZLIB, should have been: 3-clause BSD) * Fixed license text (was: ZLIB, should have been: 3-clause BSD)
* Python 3.2 compatibility * Python 3.2 compatibility