diff --git a/README.md b/README.md index 9a2dd38..1ec0887 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ CTRACK is a powerful tool that can be seamlessly integrated into both developmen ## Features - Single header file -- No dependencies +- No dependencies (optional tbb for non msvc to use paralell result calculation) - Easy to use (just 1 line per function you want to track) - Minimal overhead (can record tens of millions events per second) - Optimized for multi-threaded environments @@ -168,6 +168,9 @@ CTRACK is a header-only library, which means you can start using it by simply in This method is straightforward and doesn't require any additional setup or build process. +Note: If you are using a compiler which needs TBB for C++ standard parallel algorithms, you need to link to -ltbb. You can always fall back to sequential result calculation by setting +CTRACK_DISABLE_EXECUTION_POLICY. The recording will be unchanged, but the printing/calculating of the stats will be a bit slower. + ### 2. CMake Package For projects using CMake, CTRACK can be installed and used as a CMake package. This method provides better integration with your build system and makes it easier to manage dependencies. @@ -191,6 +194,11 @@ To use CTRACK as a CMake package: target_link_libraries(your_target PRIVATE CTRACK::CTRACK) ``` +Note: If you are using a compiler which needs TBB for C++ standard parallel algorithms, you need to link to tbb. + ```target_link_libraries( your_target PRIVATE TBB::tbb ) ``` +You can always fall back to sequential result calculation by setting +CTRACK_DISABLE_EXECUTION_POLICY. The recording will be unchanged, but the printing/calculating of the stats will be a bit slower. + For more detailed examples of how to use CTRACK with CMake, please refer to the `examples` directory in the CTRACK repository. Choose the installation method that best fits your project's needs and structure. Both methods provide full access to CTRACK's features and capabilities. diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index c205f42..69739a7 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,3 +1,27 @@ +option(DISABLE_PAR "Disable parallel processing" OFF) +if(NOT MSVC AND NOT DISABLE_PAR) + # For other compilers, check for TBB + find_package(TBB QUIET) + if(TBB_FOUND) + message(STATUS "TBB found. Enabling parallel execution.") + else() + message(STATUS "TBB not found. Disabling parallel execution.") + set(DISABLE_PAR ON) + endif() +elseif(DISABLE_PAR) + message(STATUS "DISABLE_PAR set. Disabling parallel execution.") +endif() + + +# Function to enable parallel execution on non msvc +function(enable_parallel_execution target) + if(DISABLE_PAR) + target_compile_definitions(${target} PRIVATE CTRACK_DISABLE_EXECUTION_POLICY) + elseif(NOT MSVC) + target_link_libraries(${target} PRIVATE TBB::tbb) + endif() +endfunction() + # Create executables for each example add_executable(basic_singlethreaded basic_singlethreaded.cpp) add_executable(multithreaded_prime_counter multithreaded_prime_counter.cpp) @@ -5,6 +29,13 @@ add_executable(ctrack_overhead_test ctrack_overhead_test.cpp) add_executable(high_variance_pi_estimation high_variance_pi_estimation.cpp) add_executable(complex_multithreaded_puzzle complex_multithreaded_puzzle.cpp) +#check for paralell +enable_parallel_execution(basic_singlethreaded) +enable_parallel_execution(multithreaded_prime_counter) +enable_parallel_execution(ctrack_overhead_test) +enable_parallel_execution(high_variance_pi_estimation) +enable_parallel_execution(complex_multithreaded_puzzle) + # Link the ctrack library to each example target_link_libraries(basic_singlethreaded PRIVATE ctrack) target_link_libraries(multithreaded_prime_counter PRIVATE ctrack) diff --git a/include/ctrack.hpp b/include/ctrack.hpp index 66b4680..1794610 100644 --- a/include/ctrack.hpp +++ b/include/ctrack.hpp @@ -17,16 +17,20 @@ #include #include #include +#ifndef CTRACK_DISABLE_EXECUTION_POLICY #include +#endif #include #include #include #include #include +#include +#include #define CTRACK_VERSION_MAJOR 1 #define CTRACK_VERSION_MINOR 0 -#define CTRACK_VERSION_PATCH 0 +#define CTRACK_VERSION_PATCH 1 // Helper macro to convert a numeric value to a string #define STRINGIFY(x) #x @@ -44,14 +48,18 @@ namespace ctrack { inline namespace CTRACK_VERSION_NAMESPACE { - +#ifndef CTRACK_DISABLE_EXECUTION_POLICY constexpr auto execution_policy = std::execution::par_unseq; +#define OPT_EXEC_POLICY execution_policy, +#else +#define OPT_EXEC_POLICY +#endif template auto sum_field(const std::vector& vec, Field T::* field) { using FieldType = std::decay_t().*field)>; return std::transform_reduce( - execution_policy, + OPT_EXEC_POLICY vec.begin(), vec.end(), FieldType{}, std::plus<>(), @@ -63,7 +71,7 @@ namespace ctrack { auto sum_squared_field(const std::vector& values, Field T::* field) { using FieldType = std::decay_t().*field)>; return std::transform_reduce( - execution_policy, + OPT_EXEC_POLICY values.begin(), values.end(), FieldType{}, std::plus<>(), @@ -76,7 +84,7 @@ namespace ctrack { template double calculate_std_dev_field(std::vector& values, Field T::* field, const double mean) { double res = std::transform_reduce( - execution_policy, + OPT_EXEC_POLICY values.begin(), values.end(), 0.0, std::plus<>(), @@ -105,7 +113,7 @@ namespace ctrack { template void order_pointer_vector_by_field(std::vector& vec, MemberType StructType::* member, bool asc = true) { - std::sort(execution_policy, vec.begin(), vec.end(), + std::sort(OPT_EXEC_POLICY vec.begin(), vec.end(), [member, asc](const StructType* a, const StructType* b) { if (asc) return (a->*member) < (b->*member); @@ -117,7 +125,7 @@ namespace ctrack { template size_t countAllEvents(const std::deque>& events) { return std::transform_reduce( - execution_policy, + OPT_EXEC_POLICY events.begin(), events.end(), size_t(0), std::plus<>(), @@ -393,7 +401,7 @@ namespace ctrack { std::vector simple_events{}; simple_events.resize(events.size()); std::transform( - execution_policy, + OPT_EXEC_POLICY events.begin(), events.end(), simple_events.begin(), [](const Event& event) { @@ -409,7 +417,7 @@ namespace ctrack { std::vector simple_events{}; simple_events.resize(events.size()); std::transform( - execution_policy, + OPT_EXEC_POLICY events.begin(), events.end(), simple_events.begin(), [](const Event* event) { @@ -482,7 +490,7 @@ namespace ctrack { return; auto all_events_simple = create_simple_events(all_events); - std::sort(execution_policy, all_events_simple.begin(), all_events_simple.end(), cmp_simple_event_by_duration_asc); + std::sort(OPT_EXEC_POLICY all_events_simple.begin(), all_events_simple.end(), cmp_simple_event_by_duration_asc); all_cnt = static_cast (all_events_simple.size()); const double factor = (1.0 / static_cast(all_cnt)); @@ -540,19 +548,19 @@ namespace ctrack { auto center_child_events_simple = load_child_events_simple(center_events_simple, events_map, child_graph); - std::sort(execution_policy, center_events_simple.begin(), center_events_simple.end(), cmp_simple_event_by_start_time_asc); + std::sort(OPT_EXEC_POLICY center_events_simple.begin(), center_events_simple.end(), cmp_simple_event_by_start_time_asc); center_grouped = sorted_create_grouped_simple_events(center_events_simple); center_time_active = sum_field(center_grouped, &Simple_Event::duration); - std::sort(execution_policy, center_child_events_simple.begin(), center_child_events_simple.end(), cmp_simple_event_by_start_time_asc); + std::sort(OPT_EXEC_POLICY center_child_events_simple.begin(), center_child_events_simple.end(), cmp_simple_event_by_start_time_asc); auto center_child_events_grouped = sorted_create_grouped_simple_events(center_child_events_simple); center_time_active_exclusive = center_time_active - sum_field(center_child_events_grouped, &Simple_Event::duration); - std::sort(execution_policy, all_events_simple.begin(), all_events_simple.end(), cmp_simple_event_by_start_time_asc); + std::sort(OPT_EXEC_POLICY all_events_simple.begin(), all_events_simple.end(), cmp_simple_event_by_start_time_asc); all_grouped = sorted_create_grouped_simple_events(all_events_simple); all_time_active = sum_field(all_grouped, &Simple_Event::duration); - std::sort(execution_policy, all_child_events_simple.begin(), all_child_events_simple.end(), cmp_simple_event_by_start_time_asc); + std::sort(OPT_EXEC_POLICY all_child_events_simple.begin(), all_child_events_simple.end(), cmp_simple_event_by_start_time_asc); auto all_child_events_grouped = sorted_create_grouped_simple_events(all_child_events_simple); all_time_active_exclusive = all_time_active - sum_field(all_child_events_grouped, &Simple_Event::duration); } @@ -721,7 +729,7 @@ namespace ctrack { } } - std::sort(execution_policy, grouped_events.begin(), grouped_events.end(), cmp_simple_event_by_start_time_asc); + std::sort(OPT_EXEC_POLICY grouped_events.begin(), grouped_events.end(), cmp_simple_event_by_start_time_asc); auto all_grouped = sorted_create_grouped_simple_events(grouped_events); sum_time_active_exclusive = sum_field(all_grouped, &Simple_Event::duration);