Skip to content

Commit

Permalink
fix: Require TBB to be found by cmake (acts-project#3507)
Browse files Browse the repository at this point in the history
Previously, the configuration could trun through even if TBB is not present on the system.
  • Loading branch information
benjaminhuth authored Oct 30, 2024
1 parent 0c57839 commit e2789b6
Show file tree
Hide file tree
Showing 5 changed files with 13 additions and 100 deletions.
1 change: 0 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ option(ACTS_BUILD_EXAMPLES_HEPMC3 "Build HepMC3-based code in the examples" OFF)
option(ACTS_BUILD_EXAMPLES_HASHING "Build Hashing-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 @@ -46,30 +46,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
}

explicit scoped_lock(queuing_mutex& ACTS_EXAMPLES_WITH_TBB(m)) {
#ifndef ACTS_EXAMPLES_NO_TBB
explicit 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
1 change: 0 additions & 1 deletion docs/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,6 @@ components.
| ACTS_BUILD_EXAMPLES_HASHING | Build Hashing-based code in the examples<br> type: `bool`, default: `OFF` |
| ACTS_BUILD_EXAMPLES_PYTHIA8 | Build Pythia8-based code in the examples<br> type: `bool`, default: `OFF` |
| ACTS_BUILD_EXAMPLES_PYTHON_BINDINGS | Build python bindings for the examples<br> type: `bool`, default: `OFF` |
| ACTS_USE_EXAMPLES_TBB | Use Threading Building Blocks library in<br>the examples<br> type: `bool`, default: `ON` |
| ACTS_BUILD_ANALYSIS_APPS | Build Analysis applications in the<br>examples<br> type: `bool`, default: `OFF` |
| ACTS_BUILD_BENCHMARKS | Build benchmarks<br> type: `bool`, default: `OFF` |
| ACTS_BUILD_INTEGRATIONTESTS | Build integration tests<br> type: `bool`, default: `OFF` |
Expand Down

0 comments on commit e2789b6

Please sign in to comment.