pipeline.hpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. #ifndef OPENCV_GAPI_PIPELINE_MODELING_TOOL_PIPELINE_HPP
  2. #define OPENCV_GAPI_PIPELINE_MODELING_TOOL_PIPELINE_HPP
  3. struct PerfReport {
  4. std::string name;
  5. double avg_latency = 0.0;
  6. double throughput = 0.0;
  7. int64_t first_run_latency = 0;
  8. int64_t elapsed = 0;
  9. int64_t compilation_time = 0;
  10. std::vector<int64_t> latencies;
  11. std::string toStr(bool expanded = false) const;
  12. };
  13. std::string PerfReport::toStr(bool expand) const {
  14. std::stringstream ss;
  15. ss << name << ": Compilation time: " << compilation_time << " ms; "
  16. << "Average latency: " << avg_latency << " ms; Throughput: "
  17. << throughput << " FPS; First latency: "
  18. << first_run_latency << " ms";
  19. if (expand) {
  20. ss << "\nTotal processed frames: " << latencies.size()
  21. << "\nTotal elapsed time: " << elapsed << " ms" << std::endl;
  22. for (size_t i = 0; i < latencies.size(); ++i) {
  23. ss << std::endl;
  24. ss << "Frame:" << i << "\nLatency: "
  25. << latencies[i] << " ms";
  26. }
  27. }
  28. return ss.str();
  29. }
  30. class Pipeline {
  31. public:
  32. using Ptr = std::shared_ptr<Pipeline>;
  33. Pipeline(std::string&& name,
  34. cv::GComputation&& comp,
  35. cv::gapi::wip::IStreamSource::Ptr&& src,
  36. cv::GCompileArgs&& args,
  37. const size_t num_outputs);
  38. void compile();
  39. void run(double work_time_ms);
  40. const PerfReport& report() const;
  41. const std::string& name() const { return m_name;}
  42. virtual ~Pipeline() = default;
  43. protected:
  44. struct RunPerf {
  45. int64_t elapsed = 0;
  46. std::vector<int64_t> latencies;
  47. };
  48. virtual void _compile() = 0;
  49. virtual RunPerf _run(double work_time_ms) = 0;
  50. std::string m_name;
  51. cv::GComputation m_comp;
  52. cv::gapi::wip::IStreamSource::Ptr m_src;
  53. cv::GCompileArgs m_args;
  54. size_t m_num_outputs;
  55. PerfReport m_perf;
  56. };
  57. Pipeline::Pipeline(std::string&& name,
  58. cv::GComputation&& comp,
  59. cv::gapi::wip::IStreamSource::Ptr&& src,
  60. cv::GCompileArgs&& args,
  61. const size_t num_outputs)
  62. : m_name(std::move(name)),
  63. m_comp(std::move(comp)),
  64. m_src(std::move(src)),
  65. m_args(std::move(args)),
  66. m_num_outputs(num_outputs) {
  67. m_perf.name = m_name;
  68. }
  69. void Pipeline::compile() {
  70. m_perf.compilation_time =
  71. utils::measure<std::chrono::milliseconds>([this]() {
  72. _compile();
  73. });
  74. }
  75. void Pipeline::run(double work_time_ms) {
  76. auto run_perf = _run(work_time_ms);
  77. m_perf.elapsed = run_perf.elapsed;
  78. m_perf.latencies = std::move(run_perf.latencies);
  79. m_perf.avg_latency =
  80. std::accumulate(m_perf.latencies.begin(),
  81. m_perf.latencies.end(),
  82. 0.0) / static_cast<double>(m_perf.latencies.size());
  83. m_perf.throughput =
  84. (m_perf.latencies.size() / static_cast<double>(m_perf.elapsed)) * 1000;
  85. m_perf.first_run_latency = m_perf.latencies[0];
  86. }
  87. const PerfReport& Pipeline::report() const {
  88. return m_perf;
  89. }
  90. class StreamingPipeline : public Pipeline {
  91. public:
  92. using Pipeline::Pipeline;
  93. private:
  94. void _compile() override {
  95. m_compiled =
  96. m_comp.compileStreaming({m_src->descr_of()},
  97. cv::GCompileArgs(m_args));
  98. }
  99. Pipeline::RunPerf _run(double work_time_ms) override {
  100. // NB: Setup.
  101. using namespace std::chrono;
  102. // NB: N-1 buffers + timestamp.
  103. std::vector<cv::Mat> out_mats(m_num_outputs - 1);
  104. int64_t start_ts = -1;
  105. cv::GRunArgsP pipeline_outputs;
  106. for (auto& m : out_mats) {
  107. pipeline_outputs += cv::gout(m);
  108. }
  109. pipeline_outputs += cv::gout(start_ts);
  110. m_compiled.setSource(m_src);
  111. // NB: Start execution & measure performance statistics.
  112. Pipeline::RunPerf perf;
  113. auto start = high_resolution_clock::now();
  114. m_compiled.start();
  115. while (m_compiled.pull(cv::GRunArgsP{pipeline_outputs})) {
  116. int64_t latency = utils::timestamp<milliseconds>() - start_ts;
  117. perf.latencies.push_back(latency);
  118. perf.elapsed = duration_cast<milliseconds>(
  119. high_resolution_clock::now() - start).count();
  120. if (perf.elapsed >= work_time_ms) {
  121. m_compiled.stop();
  122. break;
  123. }
  124. };
  125. return perf;
  126. }
  127. cv::GStreamingCompiled m_compiled;
  128. };
  129. class RegularPipeline : public Pipeline {
  130. public:
  131. using Pipeline::Pipeline;
  132. private:
  133. void _compile() override {
  134. m_compiled =
  135. m_comp.compile({m_src->descr_of()},
  136. cv::GCompileArgs(m_args));
  137. }
  138. Pipeline::RunPerf _run(double work_time_ms) override {
  139. // NB: Setup
  140. using namespace std::chrono;
  141. cv::gapi::wip::Data d;
  142. std::vector<cv::Mat> out_mats(m_num_outputs);
  143. cv::GRunArgsP pipeline_outputs;
  144. for (auto& m : out_mats) {
  145. pipeline_outputs += cv::gout(m);
  146. }
  147. // NB: Start execution & measure performance statistics.
  148. Pipeline::RunPerf perf;
  149. auto start = high_resolution_clock::now();
  150. while (m_src->pull(d)) {
  151. auto in_mat = cv::util::get<cv::Mat>(d);
  152. int64_t latency = utils::measure<milliseconds>([&]{
  153. m_compiled(cv::gin(in_mat), cv::GRunArgsP{pipeline_outputs});
  154. });
  155. perf.latencies.push_back(latency);
  156. perf.elapsed = duration_cast<milliseconds>(
  157. high_resolution_clock::now() - start).count();
  158. if (perf.elapsed >= work_time_ms) {
  159. break;
  160. }
  161. };
  162. return perf;
  163. }
  164. cv::GCompiled m_compiled;
  165. };
  166. enum class PLMode {
  167. REGULAR,
  168. STREAMING
  169. };
  170. #endif // OPENCV_GAPI_PIPELINE_MODELING_TOOL_PIPELINE_HPP