Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Require TBB to be found by cmake #3507

Merged
merged 12 commits into from
Oct 30, 2024
1 change: 0 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ option(ACTS_BUILD_EXAMPLES_GEANT4 "Build Geant4-based code in the examples" OFF)
option(ACTS_BUILD_EXAMPLES_HEPMC3 "Build HepMC3-based code in the examples" OFF)
option(ACTS_BUILD_EXAMPLES_PYTHIA8 "Build Pythia8-based code in the examples" OFF)
option(ACTS_BUILD_EXAMPLES_PYTHON_BINDINGS "Build python bindings for the examples" OFF)
option(ACTS_USE_EXAMPLES_TBB "Use Threading Building Blocks library in the examples" ON)
option(ACTS_BUILD_ANALYSIS_APPS "Build Analysis applications in the examples" OFF)
# test related options
option(ACTS_BUILD_BENCHMARKS "Build benchmarks" OFF)
Expand Down
31 changes: 8 additions & 23 deletions Examples/Framework/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,30 +44,15 @@ target_compile_definitions(
PRIVATE BOOST_FILESYSTEM_NO_DEPRECATED
)

if(ACTS_USE_EXAMPLES_TBB)
# newer DD4hep version require TBB and search internally for TBB in
# config-only mode. to avoid mismatches we explicitly search using
# config-only mode first to be sure that we find the same version.
find_package(TBB ${_acts_tbb_version} CONFIG)
if(NOT TBB_FOUND)
# no version check possible when using the find module
find_package(TBB ${_acts_tbb_version} MODULE)
endif()
else()
set(TBB_FOUND FALSE)
endif()
if(TBB_FOUND)
target_link_libraries(ActsExamplesFramework PUBLIC TBB::tbb)
else()
message(
STATUS
"disable TBB for Examples/Framework - only single-threaded running will be supported"
)
target_compile_definitions(
ActsExamplesFramework
PUBLIC -DACTS_EXAMPLES_NO_TBB
)
# newer DD4hep version require TBB and search internally for TBB in
# config-only mode. to avoid mismatches we explicitly search using
# config-only mode first to be sure that we find the same version.
find_package(TBB ${_acts_tbb_version} CONFIG)
if(NOT TBB_FOUND)
# no version check possible when using the find module
find_package(TBB ${_acts_tbb_version} MODULE REQUIRED)
endif()
target_link_libraries(ActsExamplesFramework PUBLIC TBB::tbb)

install(
TARGETS ActsExamplesFramework
Expand Down
70 changes: 4 additions & 66 deletions Examples/Framework/include/ActsExamples/Utilities/tbbWrap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,11 @@

#pragma once

// uncomment to remove all use of tbb library.
// #define ACTS_EXAMPLES_NO_TBB

#ifdef ACTS_EXAMPLES_NO_TBB
#define ACTS_EXAMPLES_WITH_TBB(a)
#include <stdexcept>
#else
#define ACTS_EXAMPLES_WITH_TBB(a) a
#include <optional>

#include <tbb/parallel_for.h>
#include <tbb/queuing_mutex.h>
#include <tbb/task_arena.h>
#endif

/// Wrapper for most of the tbb functions that we use in Sequencer.
///
Expand All @@ -30,34 +21,9 @@
/// tbb::blocked_range (which doesn't require any thread setup) is still taken
/// from the tbb library.
///
/// However, if ACTS_EXAMPLES_NO_TBB is defined, then don't use tbb library at
/// all (requires nthreads=1 or -1). This allows the ACTS Examples to be built
/// without the tbb library (and reduces the dependency on ROOT).
/// In this case, we provide our own minimal implementation of
/// tbb::blocked_range.
///
/// Based on an idea from
/// https://stackoverflow.com/questions/59736661/how-to-completely-switch-off-threading-in-tbb-code

#ifdef ACTS_EXAMPLES_NO_TBB
namespace ActsExamples::tbb {
namespace task_arena {
constexpr int automatic = -1;
} // namespace task_arena

template <typename Value>
struct blocked_range {
blocked_range(Value begin_, Value end_) : my_end(end_), my_begin(begin_) {}
Value begin() const { return my_begin; }
Value end() const { return my_end; }

private:
Value my_end;
Value my_begin;
};
} // namespace ActsExamples::tbb
#endif

namespace ActsExamples::tbbWrap {
/// enableTBB keeps a record of whether we are multi-threaded (nthreads!=1) or
/// not. This is set once in task_arena and stored globally.
Expand All @@ -67,17 +33,10 @@ namespace ActsExamples::tbbWrap {
static bool enableTBB(int nthreads = -99) {
static bool setting = false;
if (nthreads != -99) {
#ifdef ACTS_EXAMPLES_NO_TBB
if (nthreads > 1) {
throw std::runtime_error(
"tbb is not available, so can't do multi-threading.");
}
#else
bool newSetting = (nthreads != 1);
if (!setting && newSetting) {
setting = newSetting;
}
#endif
}
return setting;
}
Expand All @@ -87,28 +46,20 @@ static bool enableTBB(int nthreads = -99) {
/// That should be fine because the task_arena is initialised before spawning
/// any threads.
class task_arena {
#ifndef ACTS_EXAMPLES_NO_TBB
std::optional<tbb::task_arena> tbb;
#endif

public:
task_arena(int nthreads = tbb::task_arena::automatic,
unsigned ACTS_EXAMPLES_WITH_TBB(res) = 1) {
task_arena(int nthreads = tbb::task_arena::automatic, unsigned res = 1) {
if (enableTBB(nthreads)) {
#ifndef ACTS_EXAMPLES_NO_TBB
tbb.emplace(nthreads, res);
#endif
}
}

template <typename F>
void execute(const F& f) {
#ifndef ACTS_EXAMPLES_NO_TBB
if (tbb) {
tbb->execute(f);
} else
#endif
{
} else {
f();
}
}
Expand All @@ -119,12 +70,9 @@ class parallel_for {
public:
template <typename R, typename F>
parallel_for(const R& r, const F& f) {
#ifndef ACTS_EXAMPLES_NO_TBB
if (enableTBB()) {
tbb::parallel_for(r, f);
} else
#endif
{
} else {
for (auto i = r.begin(); i != r.end(); ++i) { // use default grainsize=1
f(R(i, i + 1));
}
Expand All @@ -134,39 +82,29 @@ class parallel_for {

/// Small wrapper for tbb::queuing_mutex and tbb::queuing_mutex::scoped_lock.
class queuing_mutex {
#ifndef ACTS_EXAMPLES_NO_TBB
std::optional<tbb::queuing_mutex> tbb;
#endif

public:
queuing_mutex() {
#ifndef ACTS_EXAMPLES_NO_TBB
if (enableTBB()) {
tbb.emplace();
}
#endif
}

class scoped_lock {
#ifndef ACTS_EXAMPLES_NO_TBB
std::optional<tbb::queuing_mutex::scoped_lock> tbb;
#endif

public:
scoped_lock() {
#ifndef ACTS_EXAMPLES_NO_TBB
if (enableTBB()) {
tbb.emplace();
}
#endif
}

scoped_lock(queuing_mutex& ACTS_EXAMPLES_WITH_TBB(m)) {
#ifndef ACTS_EXAMPLES_NO_TBB
scoped_lock(queuing_mutex& m) {
if (enableTBB()) {
tbb.emplace(*m.tbb);
}
#endif
}
};
};
Expand Down
10 changes: 1 addition & 9 deletions Examples/Framework/src/Framework/Sequencer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,11 @@
#include <string_view>
#include <typeinfo>

#include <boost/stacktrace/stacktrace.hpp>

#ifndef ACTS_EXAMPLES_NO_TBB
#include <TROOT.h>
#endif

#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/core/demangle.hpp>
#include <boost/stacktrace/stacktrace.hpp>

namespace ActsExamples {

Expand Down Expand Up @@ -108,16 +104,12 @@ Sequencer::Sequencer(const Sequencer::Config& cfg)
m_taskArena((m_cfg.numThreads < 0) ? tbb::task_arena::automatic
: m_cfg.numThreads),
m_logger(Acts::getDefaultLogger("Sequencer", m_cfg.logLevel)) {
#ifndef ACTS_EXAMPLES_NO_TBB
if (m_cfg.numThreads == 1) {
#endif
ACTS_INFO("Create Sequencer (single-threaded)");
#ifndef ACTS_EXAMPLES_NO_TBB
} else {
ROOT::EnableThreadSafety();
ACTS_INFO("Create Sequencer with " << m_cfg.numThreads << " threads");
}
#endif

const char* envvar = std::getenv("ACTS_SEQUENCER_DISABLE_FPEMON");
if (envvar != nullptr) {
Expand Down
Loading