Commit 1be69449 by FritzFlorian

Fix: make easy_profiler not a required dependency on the system.

We do so by pulling out the profiling macros in our own iclude file. In the future we might even be able to use this to build up further visualisations of the executing programm.
parent d2eff7da
Pipeline #1134 failed with stages
in 36 seconds
...@@ -42,6 +42,10 @@ Available Settings: ...@@ -42,6 +42,10 @@ Available Settings:
- Only one sanitizer can be active at once - Only one sanitizer can be active at once
- Enabling has a performance hit (do not use in releases) - Enabling has a performance hit (do not use in releases)
commit | fft(1) | fft(2)
--- | --- | ---
[d2eff7da](https://lab.las3.de/gitlab/las3/development/scheduling/predictable_parallel_patterns/commit/d2eff7dafcd822a4da662c2b4606d504b8545483) | 12.5ms <span style="color:green">-5.3%</span> | 6.5ms <span style="color:green">-5.3%</span>
### Testing ### Testing
......
add_executable(invoke_parallel main.cpp) add_executable(invoke_parallel main.cpp)
target_link_libraries(invoke_parallel pls easy_profiler) target_link_libraries(invoke_parallel pls)
if(EASY_PROFILER)
target_link_libraries(invoke_parallel easy_profiler)
endif()
#include <pls/pls.h> #include <pls/pls.h>
#include <iostream> #include <pls/internal/helpers/profiler.h>
#include <easy/profiler.h> #include <iostream>
static pls::static_scheduler_memory<8, 2 << 14> my_scheduler_memory; static pls::static_scheduler_memory<8, 2 << 14> my_scheduler_memory;
...@@ -33,17 +33,19 @@ long fib(long n) { ...@@ -33,17 +33,19 @@ long fib(long n) {
} }
int main() { int main() {
EASY_PROFILER_ENABLE; PROFILE_ENABLE
pls::scheduler scheduler{&my_scheduler_memory, 8}; pls::scheduler scheduler{&my_scheduler_memory, 8};
long result; long result;
scheduler.perform_work([&] { scheduler.perform_work([&] {
EASY_MAIN_THREAD; PROFILE_MAIN_THREAD
// Call looks just the same, only requirement is // Call looks just the same, only requirement is
// the enclosure in the perform_work lambda. // the enclosure in the perform_work lambda.
for (int i = 0; i < 10; i++) {
result = fib(30); result = fib(30);
});
std::cout << "Fib(30)=" << result << std::endl; std::cout << "Fib(30)=" << result << std::endl;
}
});
profiler::dumpBlocksToFile("test_profile.prof"); PROFILE_SAVE("test_profile.prof")
} }
# Optional external dependencies
find_package(easy_profiler)
option(EASY_PROFILER "Enable the profiler" OFF) option(EASY_PROFILER "Enable the profiler" OFF)
if(EASY_PROFILER) if(EASY_PROFILER)
if(easy_profiler_FOUND) # Optional external dependencies
find_package(easy_profiler)
if(easy_profiler_FOUND)
# Do nothing, add definitions below
else() else()
message(WARNING "EasyProfiler dependency not found on system, DISABLING it!") message(WARNING "EasyProfiler dependency not found on system, DISABLING it!")
set(EASY_PROFILER OFF) set(EASY_PROFILER OFF)
endif() endif()
endif() endif()
if(NOT EASY_PROFILER) if(EASY_PROFILER)
add_definitions(-DENABLE_EASY_PROFILER)
else()
add_definitions(-DDISABLE_EASY_PROFILER) add_definitions(-DDISABLE_EASY_PROFILER)
endif() endif()
......
...@@ -3,7 +3,7 @@ add_library(pls STATIC ...@@ -3,7 +3,7 @@ add_library(pls STATIC
src/pls.cpp include/pls/pls.h src/pls.cpp include/pls/pls.h
src/internal/base/spin_lock.cpp include/pls/internal/base/spin_lock.h src/internal/base/spin_lock.cpp include/pls/internal/base/spin_lock.h
src/internal/base/thread.cpp include/pls/internal/base/thread.h src/internal/base/thread.cpp include/pls/internal/base/thread.h
include/pls/internal/base/prohibit_new.h include/pls/internal/helpers/prohibit_new.h
src/internal/scheduling/abstract_task.cpp include/pls/internal/scheduling/abstract_task.h src/internal/scheduling/abstract_task.cpp include/pls/internal/scheduling/abstract_task.h
src/internal/scheduling/scheduler.cpp include/pls/internal/scheduling/scheduler.h src/internal/scheduling/scheduler.cpp include/pls/internal/scheduling/scheduler.h
src/internal/scheduling/thread_state.cpp include/pls/internal/scheduling/thread_state.h src/internal/scheduling/thread_state.cpp include/pls/internal/scheduling/thread_state.h
...@@ -16,7 +16,8 @@ add_library(pls STATIC ...@@ -16,7 +16,8 @@ add_library(pls STATIC
src/internal/base/deque.cpp include/pls/internal/base/deque.h src/internal/base/deque.cpp include/pls/internal/base/deque.h
src/algorithms/invoke_parallel.cpp include/pls/algorithms/invoke_parallel.h src/algorithms/invoke_parallel.cpp include/pls/algorithms/invoke_parallel.h
include/pls/internal/base/error_handling.h include/pls/internal/base/error_handling.h
include/pls/internal/scheduling/scheduler_memory.h src/internal/scheduling/scheduler_memory.cpp) include/pls/internal/scheduling/scheduler_memory.h src/internal/scheduling/scheduler_memory.cpp
include/pls/internal/helpers/profiler.h)
# Add everything in `./include` to be in the include path of this project # Add everything in `./include` to be in the include path of this project
target_include_directories(pls target_include_directories(pls
......
#ifndef PLS_PROFILER_H
#define PLS_PROFILER_H
#ifdef ENABLE_EASY_PROFILER
#include <easy/profiler.h>
#define PROFILE_WORK_BLOCK(msg) EASY_BLOCK(msg, profiler::colors::LightGreen)
#define PROFILE_FORK_JOIN_STEALING(msg) EASY_BLOCK(msg, profiler::colors::LightBlue)
#define PROFILE_STEALING(msg) EASY_BLOCK(msg, profiler::colors::Blue)
#define PROFILE_LOCK(msg) EASY_BLOCK(msg, profiler::colors::Red)
#define PROFILE_END_BLOCK EASY_END_BLOCK
#define PROFILE_SAVE(filename) profiler::dumpBlocksToFile(filename);
#define PROFILE_ENABLE EASY_PROFILER_ENABLE
#define PROFILE_MAIN_THREAD EASY_MAIN_THREAD
#else //ENABLE_EASY_PROFILER
#define PROFILE_WORK_BLOCK(msg)
#define PROFILE_FORK_JOIN_STEALING(msg)
#define PROFILE_STEALING(msg)
#define PROFILE_LOCK(msg)
#define PROFILE_END_BLOCK
#define PROFILE_SAVE(filename)
#define PROFILE_ENABLE
#define PROFILE_MAIN_THREAD
#endif //ENABLE_EASY_PROFILER
#endif //PLS_PROFILER_H
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#ifndef PLS_TBB_LIKE_TASK_H #ifndef PLS_TBB_LIKE_TASK_H
#define PLS_TBB_LIKE_TASK_H #define PLS_TBB_LIKE_TASK_H
#include <easy/profiler.h> #include "pls/internal/helpers/profiler.h"
#include "pls/internal/base/aligned_stack.h" #include "pls/internal/base/aligned_stack.h"
#include "pls/internal/base/deque.h" #include "pls/internal/base/deque.h"
...@@ -86,7 +86,7 @@ namespace pls { ...@@ -86,7 +86,7 @@ namespace pls {
last_stolen_{nullptr} {}; last_stolen_{nullptr} {};
void execute() override { void execute() override {
EASY_BLOCK("execute fork_join_task", profiler::colors::LightGreen); PROFILE_WORK_BLOCK("execute fork_join_task");
// Bind this instance to our OS thread // Bind this instance to our OS thread
my_stack_ = base::this_thread::state<thread_state>()->task_stack_; my_stack_ = base::this_thread::state<thread_state>()->task_stack_;
...@@ -102,7 +102,7 @@ namespace pls { ...@@ -102,7 +102,7 @@ namespace pls {
template<typename T> template<typename T>
void fork_join_sub_task::spawn_child(const T& task) { void fork_join_sub_task::spawn_child(const T& task) {
EASY_FUNCTION(profiler::colors::Blue) PROFILE_FORK_JOIN_STEALING("spawn_child")
static_assert(std::is_base_of<fork_join_sub_task, T>::value, "Only pass fork_join_sub_task subclasses!"); static_assert(std::is_base_of<fork_join_sub_task, T>::value, "Only pass fork_join_sub_task subclasses!");
T* new_task = tbb_task_->my_stack_->push(task); T* new_task = tbb_task_->my_stack_->push(task);
......
...@@ -2,12 +2,13 @@ ...@@ -2,12 +2,13 @@
#ifndef PLS_ROOT_MASTER_TASK_H #ifndef PLS_ROOT_MASTER_TASK_H
#define PLS_ROOT_MASTER_TASK_H #define PLS_ROOT_MASTER_TASK_H
#include <easy/profiler.h>
#include <mutex> #include <mutex>
#include "abstract_task.h" #include "pls/internal/helpers/profiler.h"
#include "pls/internal/base/spin_lock.h" #include "pls/internal/base/spin_lock.h"
#include "abstract_task.h"
namespace pls { namespace pls {
namespace internal { namespace internal {
namespace scheduling { namespace scheduling {
...@@ -30,7 +31,7 @@ namespace pls { ...@@ -30,7 +31,7 @@ namespace pls {
} }
void execute() override { void execute() override {
EASY_BLOCK("execute root_task", profiler::colors::LightGreen); PROFILE_WORK_BLOCK("execute root_task");
function_(); function_();
finished_ = 1; finished_ = 1;
} }
...@@ -54,7 +55,7 @@ namespace pls { ...@@ -54,7 +55,7 @@ namespace pls {
master_task_{master_task} {} master_task_{master_task} {}
void execute() override { void execute() override {
EASY_BLOCK("execute root_task", profiler::colors::LightGreen); PROFILE_WORK_BLOCK("execute root_task");
do { do {
steal_work(); steal_work();
} while (!master_task_->finished()); } while (!master_task_->finished());
......
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
#ifndef PLS_SCHEDULER_H #ifndef PLS_SCHEDULER_H
#define PLS_SCHEDULER_H #define PLS_SCHEDULER_H
#include <easy/profiler.h>
#include <array> #include <array>
#include <iostream> #include <iostream>
#include "pls/internal/helpers/profiler.h"
#include "pls/internal/base/aligned_stack.h" #include "pls/internal/base/aligned_stack.h"
#include "pls/internal/base/thread.h" #include "pls/internal/base/thread.h"
#include "pls/internal/base/barrier.h" #include "pls/internal/base/barrier.h"
...@@ -34,7 +35,7 @@ namespace pls { ...@@ -34,7 +35,7 @@ namespace pls {
template<typename Function> template<typename Function>
void perform_work(Function work_section) { void perform_work(Function work_section) {
EASY_FUNCTION(); PROFILE_WORK_BLOCK("scheduler::perform_work")
root_task<Function> master{work_section}; root_task<Function> master{work_section};
// Push root task on stacks // Push root task on stacks
......
#include <easy/profiler.h> #include "pls/internal/helpers/profiler.h"
#include "pls/internal/scheduling/thread_state.h" #include "pls/internal/scheduling/thread_state.h"
#include "pls/internal/scheduling/abstract_task.h" #include "pls/internal/scheduling/abstract_task.h"
...@@ -8,7 +8,7 @@ namespace pls { ...@@ -8,7 +8,7 @@ namespace pls {
namespace internal { namespace internal {
namespace scheduling { namespace scheduling {
bool abstract_task::steal_work() { bool abstract_task::steal_work() {
EASY_FUNCTION(profiler::colors::Orange); PROFILE_STEALING("abstract_task::steal_work")
auto my_state = base::this_thread::state<thread_state>(); auto my_state = base::this_thread::state<thread_state>();
auto my_scheduler = my_state->scheduler_; auto my_scheduler = my_state->scheduler_;
...@@ -18,19 +18,19 @@ namespace pls { ...@@ -18,19 +18,19 @@ namespace pls {
auto target_state = my_scheduler->thread_state_for(target); auto target_state = my_scheduler->thread_state_for(target);
// TODO: Cleaner Locking Using std::guarded_lock // TODO: Cleaner Locking Using std::guarded_lock
EASY_BLOCK("Acquire Thread Lock", profiler::colors::Red) PROFILE_LOCK("Acquire Thread Lock")
target_state->lock_.lock(); target_state->lock_.lock();
EASY_END_BLOCK; PROFILE_END_BLOCK
// Dig down to our level // Dig down to our level
EASY_BLOCK("Go to our level") PROFILE_STEALING("Go to our level")
abstract_task* current_task = target_state->root_task_; abstract_task* current_task = target_state->root_task_;
while (current_task != nullptr && current_task->depth() < depth()) { while (current_task != nullptr && current_task->depth() < depth()) {
current_task = current_task->child_task_; current_task = current_task->child_task_;
} }
EASY_END_BLOCK; PROFILE_END_BLOCK
EASY_BLOCK("Internal Steal") PROFILE_STEALING("Internal Steal")
if (current_task != nullptr) { if (current_task != nullptr) {
// See if it equals our type and depth of task // See if it equals our type and depth of task
if (current_task->unique_id_ == unique_id_ && if (current_task->unique_id_ == unique_id_ &&
...@@ -45,12 +45,12 @@ namespace pls { ...@@ -45,12 +45,12 @@ namespace pls {
current_task = current_task->child_task_; current_task = current_task->child_task_;
} }
} }
EASY_END_BLOCK; PROFILE_END_BLOCK;
// Execute 'top level task steal' if possible // Execute 'top level task steal' if possible
// (only try deeper tasks to keep depth restricted stealing) // (only try deeper tasks to keep depth restricted stealing)
EASY_BLOCK("Top Level Steal") PROFILE_STEALING("Top Level Steal")
while (current_task != nullptr) { while (current_task != nullptr) {
auto lock = &target_state->lock_; auto lock = &target_state->lock_;
if (current_task->split_task(lock)) { if (current_task->split_task(lock)) {
...@@ -60,7 +60,7 @@ namespace pls { ...@@ -60,7 +60,7 @@ namespace pls {
current_task = current_task->child_task_; current_task = current_task->child_task_;
} }
EASY_END_BLOCK; PROFILE_END_BLOCK;
target_state->lock_.unlock(); target_state->lock_.unlock();
} }
......
#include <easy/profiler.h> #include "pls/internal/helpers/profiler.h"
#include "pls/internal/scheduling/scheduler.h" #include "pls/internal/scheduling/scheduler.h"
#include "pls/internal/scheduling/fork_join_task.h" #include "pls/internal/scheduling/fork_join_task.h"
...@@ -21,11 +21,11 @@ namespace pls { ...@@ -21,11 +21,11 @@ namespace pls {
stack_state_{nullptr} {} stack_state_{nullptr} {}
void fork_join_sub_task::execute() { void fork_join_sub_task::execute() {
EASY_BLOCK("execute sub_task", profiler::colors::Green); PROFILE_WORK_BLOCK("execute sub_task")
tbb_task_->currently_executing_ = this; tbb_task_->currently_executing_ = this;
execute_internal(); execute_internal();
tbb_task_->currently_executing_ = nullptr; tbb_task_->currently_executing_ = nullptr;
EASY_END_BLOCK; PROFILE_END_BLOCK
wait_for_all(); wait_for_all();
if (parent_ != nullptr) { if (parent_ != nullptr) {
...@@ -47,17 +47,17 @@ namespace pls { ...@@ -47,17 +47,17 @@ namespace pls {
void fork_join_sub_task::wait_for_all() { void fork_join_sub_task::wait_for_all() {
while (ref_count_ > 0) { while (ref_count_ > 0) {
EASY_BLOCK("get local sub task", profiler::colors::Blue) PROFILE_STEALING("get local sub task")
fork_join_sub_task* local_task = tbb_task_->get_local_sub_task(); fork_join_sub_task* local_task = tbb_task_->get_local_sub_task();
EASY_END_BLOCK PROFILE_END_BLOCK
if (local_task != nullptr) { if (local_task != nullptr) {
local_task->execute(); local_task->execute();
} else { } else {
// Try to steal work. // Try to steal work.
// External steal will be executed implicitly if success // External steal will be executed implicitly if success
EASY_BLOCK("steal work", profiler::colors::Blue) PROFILE_STEALING("steal work")
bool internal_steal_success = tbb_task_->steal_work(); bool internal_steal_success = tbb_task_->steal_work();
EASY_END_BLOCK PROFILE_END_BLOCK
if (internal_steal_success) { if (internal_steal_success) {
tbb_task_->last_stolen_->execute(); tbb_task_->last_stolen_->execute();
} }
...@@ -75,7 +75,7 @@ namespace pls { ...@@ -75,7 +75,7 @@ namespace pls {
} }
bool fork_join_task::internal_stealing(abstract_task* other_task) { bool fork_join_task::internal_stealing(abstract_task* other_task) {
EASY_FUNCTION(profiler::colors::Blue); PROFILE_STEALING("fork_join_task::internal_stealin")
auto cast_other_task = reinterpret_cast<fork_join_task*>(other_task); auto cast_other_task = reinterpret_cast<fork_join_task*>(other_task);
auto stolen_sub_task = cast_other_task->get_stolen_sub_task(); auto stolen_sub_task = cast_other_task->get_stolen_sub_task();
...@@ -93,7 +93,7 @@ namespace pls { ...@@ -93,7 +93,7 @@ namespace pls {
} }
bool fork_join_task::split_task(base::spin_lock* lock) { bool fork_join_task::split_task(base::spin_lock* lock) {
EASY_FUNCTION(profiler::colors::Blue); PROFILE_STEALING("fork_join_task::split_task")
fork_join_sub_task* stolen_sub_task = get_stolen_sub_task(); fork_join_sub_task* stolen_sub_task = get_stolen_sub_task();
if (stolen_sub_task == nullptr) { if (stolen_sub_task == nullptr) {
return false; return false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment