diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 17c30b34a..86058753b 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -332,9 +332,9 @@ jobs: PPC_NUM_PROC: 1 PPC_ASAN_RUN: 1 gcc-build-codecov: - needs: - - gcc-test-extended - - clang-test-extended +# needs: +# - gcc-test-extended +# - clang-test-extended runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 diff --git a/modules/performance/include/performance.hpp b/modules/performance/include/performance.hpp index eaafc5378..3b185ef11 100644 --- a/modules/performance/include/performance.hpp +++ b/modules/performance/include/performance.hpp @@ -11,112 +11,196 @@ #include "task/include/task.hpp" +using namespace ppc::task; + namespace ppc::performance { +/** + * @brief Default timer function used for performance measurement. + * @return A fake time value (-1.0). + */ inline double DefaultTimer() { return -1.0; } +/** + * @brief Attributes used to configure performance measurement. + */ struct PerfAttr { - /// @brief Number of times the task is run for performance evaluation. + /** + * @brief Number of repetitions of the task for averaging performance. + */ uint64_t num_running = 5; - /// @brief Timer function returning current time in seconds. - /// @cond + + /** + * @brief Timer function returning current time in seconds. + * Default is a fake function returning -1.0. + */ std::function current_timer = DefaultTimer; - /// @endcond }; +/** + * @brief Stores the results of a performance test. + */ struct PerfResults { - /// @brief Measured execution time in seconds. + /** + * @brief Measured execution time in seconds (average over runs). + */ double time_sec = 0.0; - enum TypeOfRunning : uint8_t { kPipeline, kTaskRun, kNone } type_of_running = kNone; + + /** + * @brief Type of performance test performed. + */ + enum TypeOfRunning : uint8_t { + kPipeline, ///< Full pipeline: Validation → PreProcessing → Run → PostProcessing + kTaskRun, ///< Only Run() function is measured + kNone ///< No performance test was executed + } type_of_running = kNone; + + /** + * @brief Maximum allowed execution time in seconds. + */ constexpr static double kMaxTime = 10.0; }; +/** + * @brief Converts a TypeOfRunning enum value to its string representation. + * @param type_of_running Enum value indicating which performance type was run. + * @return String name corresponding to the enum. + */ +inline std::string GetStringParamName(PerfResults::TypeOfRunning type_of_running) { + if (type_of_running == PerfResults::kTaskRun) { + return "task_run"; + } + if (type_of_running == PerfResults::kPipeline) { + return "pipeline"; + } + return "none"; +} + +/** + * @brief Measures performance of a given task using configured attributes. + * @tparam InType Input type of the task. + * @tparam OutType Output type of the task. + */ template class Perf { public: - // Init performance analysis with an initialized task and initialized data - explicit Perf(const ppc::task::TaskPtr& task_ptr) : task_(task_ptr) { - task_ptr->GetStateOfTesting() = ppc::task::StateOfTesting::kPerf; + /** + * @brief Constructs a performance tester for the given task. + * @param task_ptr Shared pointer to a task object. + */ + explicit Perf(const ::TaskPtr& task_ptr) : task_(task_ptr) { + task_ptr->GetStateOfTesting() = ::StateOfTesting::kPerf; } - // Check performance of full task's pipeline: PreProcessing() -> - // Validation() -> Run() -> PostProcessing() + + /** + * @brief Runs the full task pipeline and measures its performance. + * The full pipeline includes: Validation → PreProcessing → Run → PostProcessing. + * @param perf_attr Performance measurement configuration. + */ void PipelineRun(const PerfAttr& perf_attr) { - perf_results_.type_of_running = PerfResults::TypeOfRunning::kPipeline; - - CommonRun(perf_attr, [&] { - task_->Validation(); - task_->PreProcessing(); - task_->Run(); - task_->PostProcessing(); - }, perf_results_); + perf_results_.type_of_running = PerfResults::kPipeline; + CommonRun(perf_attr, RunFullPipeline<::Task>); } - // Check performance of task's Run() function + + /** + * @brief Measures only the Run() part of the task. + * Pre- / Post-processing and validation are still invoked before and after. + * @param perf_attr Performance measurement configuration. + */ void TaskRun(const PerfAttr& perf_attr) { - perf_results_.type_of_running = PerfResults::TypeOfRunning::kTaskRun; + perf_results_.type_of_running = PerfResults::kTaskRun; task_->Validation(); task_->PreProcessing(); - CommonRun(perf_attr, [&] { task_->Run(); }, perf_results_); + CommonRun(perf_attr, RunOnly<::Task>); task_->PostProcessing(); + // Ensure correctness after a performance run task_->Validation(); task_->PreProcessing(); task_->Run(); task_->PostProcessing(); } - // Pint results for automation checkers + + /** + * @brief Prints formatted performance results or throws if too slow. + * Prints output in format: test_id:type:time_in_seconds + * @param test_id Identifier for the current test (e.g., "omp_4_threads"). + * @throws std::runtime_error if execution time exceeds allowed maximum. + */ void PrintPerfStatistic(const std::string& test_id) const { - std::string type_test_name; - if (perf_results_.type_of_running == PerfResults::TypeOfRunning::kTaskRun) { - type_test_name = "task_run"; - } else if (perf_results_.type_of_running == PerfResults::TypeOfRunning::kPipeline) { - type_test_name = "pipeline"; - } else { - std::stringstream err_msg; - err_msg << '\n' << "The type of performance check for the task was not selected.\n"; - throw std::runtime_error(err_msg.str().c_str()); + const auto& type = perf_results_.type_of_running; + const std::string type_name = GetStringParamName(type); + + if (type == PerfResults::kNone) { + throw std::runtime_error("The type of performance check for the task was not selected.\n"); } - auto time_secs = perf_results_.time_sec; - std::stringstream perf_res_str; + std::stringstream ss; + double time_secs = perf_results_.time_sec; + if (time_secs < PerfResults::kMaxTime) { - perf_res_str << std::fixed << std::setprecision(10) << time_secs; - std::cout << test_id << ":" << type_test_name << ":" << perf_res_str.str() << '\n'; + ss << std::fixed << std::setprecision(10) << time_secs; } else { - std::stringstream err_msg; - err_msg << '\n' << "Task execute time need to be: "; - err_msg << "time < " << PerfResults::kMaxTime << " secs." << '\n'; - err_msg << "Original time in secs: " << time_secs << '\n'; - perf_res_str << std::fixed << std::setprecision(10) << -1.0; - std::cout << test_id << ":" << type_test_name << ":" << perf_res_str.str() << '\n'; - throw std::runtime_error(err_msg.str().c_str()); + ss << std::fixed << std::setprecision(10) << -1.0; + std::stringstream err; + err << "Task execute time need to be: time < " << PerfResults::kMaxTime + << " secs.\nOriginal time in secs: " << time_secs << '\n'; + std::cout << test_id << ":" << type_name << ":" << ss.str() << '\n'; + throw std::runtime_error(err.str()); } + + std::cout << test_id << ":" << type_name << ":" << ss.str() << '\n'; } - /// @brief Retrieves the performance test results. - /// @return The latest PerfResults structure. + + /** + * @brief Retrieves performance test results. + * @return Struct containing latest performance data. + */ [[nodiscard]] PerfResults GetPerfResults() const { return perf_results_; } private: - PerfResults perf_results_; - std::shared_ptr> task_; - static void CommonRun(const PerfAttr& perf_attr, const std::function& pipeline, PerfResults& perf_results) { - auto begin = perf_attr.current_timer(); - for (uint64_t i = 0; i < perf_attr.num_running; i++) { - pipeline(); - } - auto end = perf_attr.current_timer(); - perf_results.time_sec = (end - begin) / static_cast(perf_attr.num_running); + PerfResults perf_results_; ///< Stores measurement results and mode. + std::shared_ptr<::Task> task_; ///< Pointer to task being tested. + + /** + * @brief Executes the full pipeline for the given task. + * @tparam TaskType Type of the task. + * @param task Shared pointer to the task instance. + */ + template + static void RunFullPipeline(const std::shared_ptr& task) { + task->Validation(); + task->PreProcessing(); + task->Run(); + task->PostProcessing(); } -}; -inline std::string GetStringParamName(PerfResults::TypeOfRunning type_of_running) { - if (type_of_running == PerfResults::kTaskRun) { - return "task_run"; + /** + * @brief Executes only the Run() method of the given task. + * @tparam TaskType Type of the task. + * @param task Shared pointer to the task instance. + */ + template + static void RunOnly(const std::shared_ptr& task) { + task->Run(); } - if (type_of_running == PerfResults::kPipeline) { - return "pipeline"; + + /** + * @brief Measures execution time of a given function over multiple runs. + * @tparam Func Type of callable taking shared_ptr to task. + * @param perf_attr Attributes controlling the number of runs and timer. + * @param func Callable that invokes the desired part of the task. + */ + template + void CommonRun(const PerfAttr& perf_attr, Func func) { + double begin = perf_attr.current_timer(); + for (uint64_t i = 0; i < perf_attr.num_running; ++i) { + func(task_); + } + double end = perf_attr.current_timer(); + perf_results_.time_sec = (end - begin) / static_cast(perf_attr.num_running); } - return "none"; -} +}; } // namespace ppc::performance