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:
- Only one sanitizer can be active at once
- 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
......
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 <iostream>
#include <pls/internal/helpers/profiler.h>
#include <easy/profiler.h>
#include <iostream>
static pls::static_scheduler_memory<8, 2 << 14> my_scheduler_memory;
......@@ -33,17 +33,19 @@ long fib(long n) {
}
int main() {
EASY_PROFILER_ENABLE;
PROFILE_ENABLE
pls::scheduler scheduler{&my_scheduler_memory, 8};
long result;
scheduler.perform_work([&] {
EASY_MAIN_THREAD;
PROFILE_MAIN_THREAD
// Call looks just the same, only requirement is
// the enclosure in the perform_work lambda.
result = fib(30);
for (int i = 0; i < 10; i++) {
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)
if(EASY_PROFILER)
if(easy_profiler_FOUND)
# Optional external dependencies
find_package(easy_profiler)
if(easy_profiler_FOUND)
# Do nothing, add definitions below
else()
message(WARNING "EasyProfiler dependency not found on system, DISABLING it!")
set(EASY_PROFILER OFF)
endif()
endif()
if(NOT EASY_PROFILER)
if(EASY_PROFILER)
add_definitions(-DENABLE_EASY_PROFILER)
else()
add_definitions(-DDISABLE_EASY_PROFILER)
endif()
......
......@@ -3,7 +3,7 @@ add_library(pls STATIC
src/pls.cpp include/pls/pls.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
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/scheduler.cpp include/pls/internal/scheduling/scheduler.h
src/internal/scheduling/thread_state.cpp include/pls/internal/scheduling/thread_state.h
......@@ -16,7 +16,8 @@ add_library(pls STATIC
src/internal/base/deque.cpp include/pls/internal/base/deque.h
src/algorithms/invoke_parallel.cpp include/pls/algorithms/invoke_parallel.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
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 @@
#ifndef 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/deque.h"
......@@ -86,7 +86,7 @@ namespace pls {
last_stolen_{nullptr} {};
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
my_stack_ = base::this_thread::state<thread_state>()->task_stack_;
......@@ -102,7 +102,7 @@ namespace pls {
template<typename T>
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!");
T* new_task = tbb_task_->my_stack_->push(task);
......
......@@ -2,12 +2,13 @@
#ifndef PLS_ROOT_MASTER_TASK_H
#define PLS_ROOT_MASTER_TASK_H
#include <easy/profiler.h>
#include <mutex>
#include "abstract_task.h"
#include "pls/internal/helpers/profiler.h"
#include "pls/internal/base/spin_lock.h"
#include "abstract_task.h"
namespace pls {
namespace internal {
namespace scheduling {
......@@ -30,7 +31,7 @@ namespace pls {
}
void execute() override {
EASY_BLOCK("execute root_task", profiler::colors::LightGreen);
PROFILE_WORK_BLOCK("execute root_task");
function_();
finished_ = 1;
}
......@@ -54,7 +55,7 @@ namespace pls {
master_task_{master_task} {}
void execute() override {
EASY_BLOCK("execute root_task", profiler::colors::LightGreen);
PROFILE_WORK_BLOCK("execute root_task");
do {
steal_work();
} while (!master_task_->finished());
......
......@@ -2,10 +2,11 @@
#ifndef PLS_SCHEDULER_H
#define PLS_SCHEDULER_H
#include <easy/profiler.h>
#include <array>
#include <iostream>
#include "pls/internal/helpers/profiler.h"
#include "pls/internal/base/aligned_stack.h"
#include "pls/internal/base/thread.h"
#include "pls/internal/base/barrier.h"
......@@ -34,7 +35,7 @@ namespace pls {
template<typename Function>
void perform_work(Function work_section) {
EASY_FUNCTION();
PROFILE_WORK_BLOCK("scheduler::perform_work")
root_task<Function> master{work_section};
// 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/abstract_task.h"
......@@ -8,7 +8,7 @@ namespace pls {
namespace internal {
namespace scheduling {
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_scheduler = my_state->scheduler_;
......@@ -18,19 +18,19 @@ namespace pls {
auto target_state = my_scheduler->thread_state_for(target);
// TODO: Cleaner Locking Using std::guarded_lock
EASY_BLOCK("Acquire Thread Lock", profiler::colors::Red)
PROFILE_LOCK("Acquire Thread Lock")
target_state->lock_.lock();
EASY_END_BLOCK;
PROFILE_END_BLOCK
// 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_;
while (current_task != nullptr && current_task->depth() < depth()) {
current_task = current_task->child_task_;
}
EASY_END_BLOCK;
PROFILE_END_BLOCK
EASY_BLOCK("Internal Steal")
PROFILE_STEALING("Internal Steal")
if (current_task != nullptr) {
// See if it equals our type and depth of task
if (current_task->unique_id_ == unique_id_ &&
......@@ -45,12 +45,12 @@ namespace pls {
current_task = current_task->child_task_;
}
}
EASY_END_BLOCK;
PROFILE_END_BLOCK;
// Execute 'top level task steal' if possible
// (only try deeper tasks to keep depth restricted stealing)
EASY_BLOCK("Top Level Steal")
PROFILE_STEALING("Top Level Steal")
while (current_task != nullptr) {
auto lock = &target_state->lock_;
if (current_task->split_task(lock)) {
......@@ -60,7 +60,7 @@ namespace pls {
current_task = current_task->child_task_;
}
EASY_END_BLOCK;
PROFILE_END_BLOCK;
target_state->lock_.unlock();
}
......
#include <easy/profiler.h>
#include "pls/internal/helpers/profiler.h"
#include "pls/internal/scheduling/scheduler.h"
#include "pls/internal/scheduling/fork_join_task.h"
......@@ -21,11 +21,11 @@ namespace pls {
stack_state_{nullptr} {}
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;
execute_internal();
tbb_task_->currently_executing_ = nullptr;
EASY_END_BLOCK;
PROFILE_END_BLOCK
wait_for_all();
if (parent_ != nullptr) {
......@@ -47,17 +47,17 @@ namespace pls {
void fork_join_sub_task::wait_for_all() {
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();
EASY_END_BLOCK
PROFILE_END_BLOCK
if (local_task != nullptr) {
local_task->execute();
} else {
// Try to steal work.
// 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();
EASY_END_BLOCK
PROFILE_END_BLOCK
if (internal_steal_success) {
tbb_task_->last_stolen_->execute();
}
......@@ -75,7 +75,7 @@ namespace pls {
}
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 stolen_sub_task = cast_other_task->get_stolen_sub_task();
......@@ -93,7 +93,7 @@ namespace pls {
}
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();
if (stolen_sub_task == nullptr) {
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