oneTBB

Intel Threading Building Blocks - C++ Template Library for Parallel Programming

Overview

oneTBB (formerly Intel Threading Building Blocks) is a C++ template library for parallel programming that provides high-level abstractions for task-based parallelism. It offers a rich set of parallel algorithms, concurrent data structures, and synchronization primitives that enable efficient utilization of multi-core processors.

Key features:

  • Task-based parallelism with automatic load balancing
  • Parallel algorithms: parallel_for, parallel_reduce, parallel_scan, parallel_sort, and more
  • Concurrent containers: Thread-safe queues, hash maps, vectors, and other data structures
  • Pipeline parallelism for efficient data flow processing
  • NUMA awareness: Optional HWLOC support for NUMA-optimized scheduling (tbbbind)
  • High-performance scalable memory allocator (tbbmalloc)

Available versions

To view available oneTBB versions:

$ module avail onetbb

Build recipes and configuration details are maintained in our GitLab repository:

Compiler support

Warning

This oneTBB installation is compiled against libc++ (LLVM’s C++ standard library). Your code must also use libc++ when linking against this installation. Mixing libc++ and libstdc++ in the same application can cause ABI incompatibilities and runtime errors.

Note

We compile oneTBB from source to avoid the complexity of using Intel oneAPI installations that provide oneTBB compiled against libstdc++. This ensures consistency and compatibility with our LLVM-based toolchain.

Important

The llvm-rt module must be loaded in advance, as oneTBB is linked against libc++, which is provided by the llvm-rt module. However, if the llvm module is already loaded, there is no need to load llvm-rt separately, as the llvm module includes the runtime libraries. Load either llvm or llvm-rt before loading the onetbb module.

Supported builds:

$ module avail onetbb    # LLVM build (recommended, uses libc++)

Linking your code against oneTBB installation

Warning

You must use libc++ when compiling your code, since this oneTBB installation is linked against libc++. Use the -stdlib=libc++ flag with clang++.

When compiling code that uses oneTBB, load the appropriate modules and link with -ltbb (and optionally -ltbbmalloc for the scalable memory allocator):

# Option 1: If using llvm module (includes runtime)
$ module load llvm/<version>
$ module load onetbb/<version>
$ clang++ -std=c++17 -stdlib=libc++ your_code.cpp -ltbb -ltbbmalloc

# Option 2: If only runtime is needed (llvm module not loaded)
$ module load llvm-rt/<version>    # Provides libc++ that oneTBB is linked against
$ module load onetbb/<version>
$ clang++ -std=c++17 -stdlib=libc++ your_code.cpp -ltbb -ltbbmalloc

Example usage:

#include <oneapi/tbb/parallel_for.h>
#include <oneapi/tbb/blocked_range.h>
#include <vector>

int main() {
    std::vector<int> data(1000000);

    tbb::parallel_for(
        tbb::blocked_range<size_t>(0, data.size()),
        [&](const tbb::blocked_range<size_t>& r) {
            for (size_t i = r.begin(); i < r.end(); ++i) {
                data[i] = i * 2;
            }
        }
    );

    return 0;
}

Note

Remember to load either the llvm module (which includes runtime) or the llvm-rt module (runtime only) before loading onetbb, as they provide libc++ that oneTBB is linked against. Then compile with -stdlib=libc++ to match the oneTBB library’s C++ standard library. Failure to do so may result in ABI mismatches and runtime errors.

Note

When linking, both dynamic and static linking are supported. The actual linking method depends on your compilation configuration.

oneTBB vs OpenMP: When to Use Which?

Use OpenMP when:

  • You have simple loop parallelism (data parallelism)
  • You want minimal code changes (just add pragmas)
  • You’re working with regular, predictable workloads
  • You need quick parallelization of existing sequential code
  • You’re doing scientific computing with regular loops

Use oneTBB when:

  • You need complex parallel algorithms (task graphs, pipelines)
  • You require concurrent data structures (queues, hash maps)
  • You have irregular or dynamic workloads
  • You need nested parallelism that scales well
  • You’re building recursive parallel algorithms
  • You want better load balancing for heterogeneous workloads

Note

Many projects use both: OpenMP for simple data parallelism and oneTBB for complex parallel algorithms, task dependencies, and concurrent data structures.

Exception Handling with libc++ Build

Warning

When using this libc++ build, you cannot catch oneTBB exceptions by their specific types across library boundaries. Instead, catch by base types.

Example of correct exception handling:

try {
    // oneTBB code
} catch (const std::runtime_error& e) {  // Catches tbb::unsafe_wait, etc.
    // Handle runtime errors
} catch (const std::bad_alloc& e) {      // Catches tbb::bad_last_alloc
    // Handle allocation errors
} catch (const std::exception& e) {      // Catches other oneTBB exceptions
    // Handle other exceptions
}

See detailed information about this limitation and workarounds for more details.

Getting Help