From 471b40040a304e92bbe4a3a53e81b56dd00b2c1a Mon Sep 17 00:00:00 2001 From: anton-potapov Date: Mon, 21 Oct 2019 22:33:18 +0300 Subject: [PATCH] Merge pull request #15735 from anton-potapov:gapi_async_documentaion * G-API: Doxygen documentatation for Async API * G-API: Doxygen documentatation for Async API - renamed local variable (reading parameter async) async -> asyncNumReq in object_detection DNN sample to avoid Doxygen erroneous linking the sample to cv::gapi::wip::async documentation --- .../include/opencv2/gapi/gasync_context.hpp | 20 +++++++- .../include/opencv2/gapi/gcompiled_async.hpp | 46 ++++++++++++++++--- .../opencv2/gapi/gcomputation_async.hpp | 42 +++++++++++++---- samples/dnn/object_detection.cpp | 10 ++-- 4 files changed, 97 insertions(+), 21 deletions(-) diff --git a/modules/gapi/include/opencv2/gapi/gasync_context.hpp b/modules/gapi/include/opencv2/gapi/gasync_context.hpp index 3e01577bb5..69ce530fc9 100644 --- a/modules/gapi/include/opencv2/gapi/gasync_context.hpp +++ b/modules/gapi/include/opencv2/gapi/gasync_context.hpp @@ -19,11 +19,29 @@ namespace cv { namespace gapi{ namespace wip { +/** + * @brief A class to group async requests to cancel them in a single shot. + * + * GAsyncContext is passed as an argument to async() and async_apply() functions + */ + class GAPI_EXPORTS GAsyncContext{ std::atomic cancelation_requested = {false}; public: - //returns true if it was a first request to cancel the context + /** + * @brief Start cancellation process for an associated request. + * + * User still has to wait for each individual request (either via callback or according std::future object) to make sure it actually canceled. + * + * @return true if it was a first request to cancel the context + */ bool cancel(); + + /** + * @brief Returns true if cancellation was requested for this context. + * + * @return true if cancellation was requested for this context + */ bool isCanceled() const; }; diff --git a/modules/gapi/include/opencv2/gapi/gcompiled_async.hpp b/modules/gapi/include/opencv2/gapi/gcompiled_async.hpp index d515314e59..a0c2917d6a 100644 --- a/modules/gapi/include/opencv2/gapi/gcompiled_async.hpp +++ b/modules/gapi/include/opencv2/gapi/gcompiled_async.hpp @@ -21,18 +21,50 @@ namespace cv { namespace gapi{ namespace wip { class GAsyncContext; - //These functions asynchronously (i.e. probably on a separate thread of execution) call operator() member function of their first argument with copies of rest of arguments (except callback) passed in. - //The difference between the function is the way to get the completion notification (via callback or a waiting on std::future object) - //If exception is occurred during execution of apply it is transferred to the callback (via function parameter) or passed to future (and will be thrown on call to std::future::get) + /** + These functions asynchronously (i.e. probably on a separate thread of execution) call GCompiled::operator() member function of their first argument with copies of rest of arguments (except callback) passed in. + The difference between the function is the way to get the completion notification (via callback or a waiting on std::future object) + If exception is occurred during execution of apply it is transferred to the callback (via function parameter) or passed to future (and will be thrown on call to std::future::get) - //N.B. : - //Input arguments are copied on call to async function (actually on call to cv::gin) and thus do not have to outlive the actual completion of asynchronous activity. - //While Output arguments are "captured" by reference(pointer) and therefore _must_ outlive the asynchronous activity - //(i.e. live at least until callback is called or future is unblocked) + N.B. : + Input arguments are copied on call to async function (actually on call to cv::gin) and thus do not have to outlive the actual completion of asynchronous activity. + While output arguments are "captured" by reference(pointer) and therefore _must_ outlive the asynchronous activity + (i.e. live at least until callback is called or future is unblocked) + + @param gcmpld Compiled computation (graph) to start asynchronously + @param callback Callback to be called when execution of gcmpld is done + @param ins Input parameters for gcmpld + @param outs Output parameters for gcmpld + */ GAPI_EXPORTS void async(GCompiled& gcmpld, std::function&& callback, GRunArgs &&ins, GRunArgsP &&outs); + + /** @overload + @param gcmpld Compiled computation (graph) to run asynchronously + @param callback Callback to be called when execution of gcmpld is done + @param ins Input parameters for gcmpld + @param outs Output parameters for gcmpld + @param ctx Context this request belongs to + @see async GAsyncContext + */ GAPI_EXPORTS void async(GCompiled& gcmpld, std::function&& callback, GRunArgs &&ins, GRunArgsP &&outs, GAsyncContext& ctx); + /** @overload + @param gcmpld Compiled computation (graph) to run asynchronously + @param ins Input parameters for gcmpld + @param outs Output parameters for gcmpld + @return std::future object to wait for completion of async operation + @see async + */ GAPI_EXPORTS std::future async(GCompiled& gcmpld, GRunArgs &&ins, GRunArgsP &&outs); + + /** + @param gcmpld Compiled computation (graph) to run asynchronously + @param ins Input parameters for gcmpld + @param outs Output parameters for gcmpld + @param ctx Context this request belongs to + @return std::future object to wait for completion of async operation + @see async GAsyncContext + */ GAPI_EXPORTS std::future async(GCompiled& gcmpld, GRunArgs &&ins, GRunArgsP &&outs, GAsyncContext& ctx); } // namespace wip } // namespace gapi diff --git a/modules/gapi/include/opencv2/gapi/gcomputation_async.hpp b/modules/gapi/include/opencv2/gapi/gcomputation_async.hpp index 27576c889f..8af603efea 100644 --- a/modules/gapi/include/opencv2/gapi/gcomputation_async.hpp +++ b/modules/gapi/include/opencv2/gapi/gcomputation_async.hpp @@ -22,18 +22,44 @@ namespace cv { namespace gapi { namespace wip { class GAsyncContext; - //These functions asynchronously (i.e. probably on a separate thread of execution) call apply member function of their first argument with copies of rest of arguments (except callback) passed in. - //The difference between the function is the way to get the completion notification (via callback or a waiting on std::future object) - //If exception is occurred during execution of apply it is transferred to the callback (via function parameter) or passed to future (and will be thrown on call to std::future::get) + /** In contrast to async() functions, these do call GComputation::apply() member function of the GComputation passed in. - //N.B. : - //Input arguments are copied on call to async function (actually on call to cv::gin) and thus do not have to outlive the actual completion of asynchronous activity. - //While Output arguments are "captured" by reference(pointer) and therefore _must_ outlive the asynchronous activity - //(i.e. live at least until callback is called or future is unblocked) + @param gcomp Computation (graph) to run asynchronously + @param callback Callback to be called when execution of gcomp is done + @param ins Input parameters for gcomp + @param outs Output parameters for gcomp + @param args Compile arguments to pass to GComputation::apply() + @see async + */ GAPI_EXPORTS void async_apply(GComputation& gcomp, std::function&& callback, GRunArgs &&ins, GRunArgsP &&outs, GCompileArgs &&args = {}); + /** @overload + @param gcomp Computation (graph) to run asynchronously + @param callback Callback to be called when execution of gcomp is done + @param ins Input parameters for gcomp + @param outs Output parameters for gcomp + @param args Compile arguments to pass to GComputation::apply() + @param ctx Context this request belongs to + @see async_apply async GAsyncContext + */ GAPI_EXPORTS void async_apply(GComputation& gcomp, std::function&& callback, GRunArgs &&ins, GRunArgsP &&outs, GCompileArgs &&args, GAsyncContext& ctx); - + /** @overload + @param gcomp Computation (graph) to run asynchronously + @param ins Input parameters for gcomp + @param outs Output parameters for gcomp + @param args Compile arguments to pass to GComputation::apply() + @return std::future object to wait for completion of async operation + @see async_apply async + */ GAPI_EXPORTS std::future async_apply(GComputation& gcomp, GRunArgs &&ins, GRunArgsP &&outs, GCompileArgs &&args = {}); + /** @overload + @param gcomp Computation (graph) to run asynchronously + @param ins Input parameters for gcomp + @param outs Output parameters for gcomp + @param args Compile arguments to pass to GComputation::apply() + @param ctx Context this request belongs to + @return std::future object to wait for completion of async operation + @see async_apply async GAsyncContext + */ GAPI_EXPORTS std::future async_apply(GComputation& gcomp, GRunArgs &&ins, GRunArgsP &&outs, GCompileArgs &&args, GAsyncContext& ctx); } // namespace wip } // namespace gapi diff --git a/samples/dnn/object_detection.cpp b/samples/dnn/object_detection.cpp index 83ed10db5d..d48b7cfba8 100644 --- a/samples/dnn/object_detection.cpp +++ b/samples/dnn/object_detection.cpp @@ -127,7 +127,7 @@ int main(int argc, char** argv) bool swapRB = parser.get("rgb"); int inpWidth = parser.get("width"); int inpHeight = parser.get("height"); - size_t async = parser.get("async"); + size_t asyncNumReq = parser.get("async"); CV_Assert(parser.has("model")); std::string modelPath = findFile(parser.get("model")); std::string configPath = findFile(parser.get("config")); @@ -196,9 +196,9 @@ int main(int argc, char** argv) if (!framesQueue.empty()) { frame = framesQueue.get(); - if (async) + if (asyncNumReq) { - if (futureOutputs.size() == async) + if (futureOutputs.size() == asyncNumReq) frame = Mat(); } else @@ -212,7 +212,7 @@ int main(int argc, char** argv) preprocess(frame, net, Size(inpWidth, inpHeight), scale, mean, swapRB); processedFramesQueue.push(frame); - if (async) + if (asyncNumReq) { futureOutputs.push(net.forwardAsync()); } @@ -266,7 +266,7 @@ int main(int argc, char** argv) processingThread.join(); #else // CV_CXX11 - if (async) + if (asyncNumReq) CV_Error(Error::StsNotImplemented, "Asynchronous forward is supported only with Inference Engine backend."); // Process frames.