From 8727d2e11c4584efc9c0e51a2cd965a992a84cfb Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner <inform@tiker.net> Date: Fri, 19 Aug 2011 19:32:00 +0200 Subject: [PATCH] Add nanny events. --- doc/source/misc.rst | 1 + doc/source/runtime.rst | 16 ++++++++++ src/wrapper/wrap_cl.hpp | 54 ++++++++++++++++++++++++++++------ src/wrapper/wrap_cl_part_1.cpp | 6 ++++ 4 files changed, 68 insertions(+), 9 deletions(-) diff --git a/doc/source/misc.rst b/doc/source/misc.rst index 493b285b..79614aba 100644 --- a/doc/source/misc.rst +++ b/doc/source/misc.rst @@ -85,6 +85,7 @@ Version 2011.2 functionality. * Base :mod:`pyopencl.clrandom` on `RANLUXCL <https://bitbucket.org/ivarun/ranluxcl>`_, add functionality. +* Add :class:`pyopencl.NannyEvent` objects. Version 2011.1.2 ---------------- diff --git a/doc/source/runtime.rst b/doc/source/runtime.rst index 973ae158..978f83e2 100644 --- a/doc/source/runtime.rst +++ b/doc/source/runtime.rst @@ -268,6 +268,19 @@ Command Queues and Events See :class:`command_execution_status` for possible values of *status*. +.. class:: NannyEvent + + Transfers between host and device return events of this type. They hold + a reference to the host-side buffer and wait for the transfer to complete + when they are freed. Therefore, they can safely release the reference to + the object they're guarding upon destruction. + + A subclass of :class:`Event`. + + .. versionadded:: 2011.2 + + .. method:: get_ward() + Memory ------ @@ -575,6 +588,9 @@ Transfers :arg is_blocking: Wait for completion. Defaults to *True*. (Available on any copy involving host memory) + :return: A :class:`NannyEvent` if the transfer involved a + host-side buffer, otherwise an :class:`Event`. + :class:`Buffer` ↔ host transfers: :arg device_offset: offset in bytes (optional) diff --git a/src/wrapper/wrap_cl.hpp b/src/wrapper/wrap_cl.hpp index 1a94c850..9eef8ab0 100644 --- a/src/wrapper/wrap_cl.hpp +++ b/src/wrapper/wrap_cl.hpp @@ -221,14 +221,25 @@ py::extract<event &>(evt)().data(); \ } -#define PYOPENCL_RETURN_NEW_EVENT(EVT) \ +#define PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, obj) \ try \ { \ - return new event(EVT, false); \ + return new nanny_event(evt, false, obj); \ } \ catch (...) \ { \ - clReleaseEvent(EVT); \ + clReleaseEvent(evt); \ + throw; \ + } + +#define PYOPENCL_RETURN_NEW_EVENT(evt) \ + try \ + { \ + return new event(evt, false); \ + } \ + catch (...) \ + { \ + clReleaseEvent(evt); \ throw; \ } @@ -1051,6 +1062,31 @@ namespace pyopencl } }; + class nanny_event : public event + { + // In addition to everything an event does, the nanny event holds a reference + // to a Python object and waits for its completion + + protected: + py::object m_ward; + + public: + + nanny_event(cl_event evt, bool retain, py::object ward) + : event(evt, retain), m_ward(ward) + { } + + nanny_event(nanny_event const &src) + : event(src), m_ward(src.m_ward) + { } + + ~nanny_event() + { wait(); } + + py::object get_ward() const + { return m_ward; } + }; + @@ -1467,7 +1503,7 @@ namespace pyopencl device_offset, len, buf, num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt )); - PYOPENCL_RETURN_NEW_EVENT(evt); + PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); } @@ -1506,7 +1542,7 @@ namespace pyopencl device_offset, len, buf, num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt )); - PYOPENCL_RETURN_NEW_EVENT(evt); + PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); } @@ -1586,7 +1622,7 @@ namespace pyopencl buf, num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt )); - PYOPENCL_RETURN_NEW_EVENT(evt); + PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); } @@ -1630,7 +1666,7 @@ namespace pyopencl buf, num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt )); - PYOPENCL_RETURN_NEW_EVENT(evt); + PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); } @@ -1973,7 +2009,7 @@ namespace pyopencl origin, region, row_pitch, slice_pitch, buf, num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt )); - PYOPENCL_RETURN_NEW_EVENT(evt); + PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); } @@ -2015,7 +2051,7 @@ namespace pyopencl origin, region, row_pitch, slice_pitch, buf, num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt )); - PYOPENCL_RETURN_NEW_EVENT(evt); + PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); } diff --git a/src/wrapper/wrap_cl_part_1.cpp b/src/wrapper/wrap_cl_part_1.cpp index 08f71f56..3ea37094 100644 --- a/src/wrapper/wrap_cl_part_1.cpp +++ b/src/wrapper/wrap_cl_part_1.cpp @@ -103,6 +103,12 @@ void pyopencl_expose_part_1() .def("__hash__", &cls::hash) ; } + { + typedef nanny_event cls; + py::class_<cls, boost::noncopyable, py::bases<event> >("NannyEvent", py::no_init) + .DEF_SIMPLE_METHOD(get_ward) + ; + } DEF_SIMPLE_FUNCTION(wait_for_events); py::def("enqueue_marker", enqueue_marker, -- GitLab