Skip to content

Latest commit

 

History

History
 
 

README.md

Using Thrust with CMake

Thrust provides configuration files that simplify using Thrust from other CMake projects. Requirements:

  • Thrust >= 1.9.10
  • CMake >= 3.18

See the Fixing Legacy FindThrust.cmake section for solutions that work on older Thrust versions.

Quick Start: Use CCCL Example

The CCCL repository contains a stand-alone example project the demonstrates how to use Thrust with any device system (CUDA, OpenMP, TBB, or CPP) from CMake using the CCCL package. The choice of device system is flexible and determined at configure-time via the CCCL_THRUST_DEVICE_SYSTEM CMake variable, which initializes the default CCCL::Thrust target's configuration.

If the default CCCL::Thrust target is not desired and your project would like more control over the Thrust configuration, set the CMake variable CCCL_ENABLE_DEFAULT_THRUST_TARGET=OFF and use the thrust_create_target function manually, as described in the following document.

Note that find_package(CCCL) internally calls find_package(Thrust). These may be used interchangeably if you're only interested in the Thrust component of CCCL.

User Guide

Default Configuration (CUDA)

Thrust is configured using a thrust_create_target CMake function that assembles a complete interface to the Thrust library:

find_package(Thrust REQUIRED CONFIG)
thrust_create_target(Thrust)
target_link_libraries(MyProgram PRIVATE Thrust)

The first argument is the name of the interface target to create, and any additional options will be used to configure the target. By default, thrust_create_target will configure its result to use CUDA acceleration.

If desired, thrust_create_target may be called multiple times to build several unique Thrust interface targets with different configurations, as detailed below.

Note: If CMake is unable to locate Thrust, specify the path to Thrust's CMake configuration directory (where this README file is located) as Thrust_DIR. If using Thrust from the CCCL sources, this would be

$ cmake . -DThrust_DIR=<CCCL git repo root>/thrust/thrust/cmake/

Large Array (64-bit offseet) Handling: DISPATCH

The DISPATCH option allows users to select the tradeoff of compile-time / binary-size vs. performance vs. scalability when given large inputs that require 64-bit offset types. This currently only applies when DEVICE=CUDA.

  • Dynamic May compile each kernel twice, once for 32-bit offsets and again for 64-bit offsets, and choose dynamically using the input size at runtime. This significantly increases compile-time and binary-size, but provides optimal performance for small input sizes while also supporting 64-bit indexed workloads.
  • Force32bit forces Thrust to use a 32 bit offset type. This improves compile time and binary size but limits the input size.
  • Force64bit forces Thrust to use a 64-bit offset type. This improves compile time and binary size and allows large input sizes. However, it may degrade runtime performance for 32-bit indexed workloads.

TBB / OpenMP

To explicitly specify host/device systems, HOST and DEVICE arguments can be passed to thrust_create_target. If an explicit system is not specified, the target will default to using CPP for host and/or CUDA for device.

thrust_create_target(ThrustTBB DEVICE TBB)
thrust_create_target(ThrustOMP HOST CPP DEVICE OMP)

will create targets ThrustTBB and ThrustOMP. Both will use the serial CPP host system, but will find and use TBB or OpenMP for the device system.

Configure Target from Cache Options

To allow a Thrust target to be configurable easily via cmake-gui or ccmake, pass the FROM_OPTIONS flag to thrust_create_target. This will add THRUST_HOST_SYSTEM, THRUST_DEVICE_SYSTEM, and THRUST_DISPATCH_TYPE options to the CMake cache that allow selection from the systems supported by this version of Thrust.

thrust_create_target(Thrust FROM_OPTIONS
  [HOST_OPTION <option name>]
  [DEVICE_OPTION <option name>]
  [DISPATCH_OPTION <option name>]
  [HOST_OPTION_DOC <doc string>]
  [DEVICE_OPTION_DOC <doc string>]
  [DISPATCH_OPTION_DOC <doc string>]
  [HOST <default host system name>]
  [DEVICE <default device system name>]
  [DISPATCH <default dispatch type>]
  [ADVANCED]
)

The optional arguments have sensible defaults, but may be configured per thrust_create_target call:

Argument Default Description
HOST_OPTION THRUST_HOST_SYSTEM Name of cache option for host
DEVICE_OPTION THRUST_DEVICE_SYSTEM Name of cache option for device
DISPATCH_OPTION THRUST_DISPATCH_TYPE Name of cache option for dispatch
HOST_OPTION_DOC Thrust's host system. Docstring for host option
DEVICE_OPTION_DOC Thrust's device system. Docstring for device option
DISPATCH_OPTION_DOC Thrust's dispatch type. Docstring for dispatch option
HOST CPP Default host system
DEVICE CUDA Default device system
DISPATCH Dispatch Default dispatch type
ADVANCED N/A Mark cache options advanced

Specifying Thrust Version Requirements

A specific version of Thrust may be required in the find_package call:

find_package(Thrust 1.9.10)

will only consider Thrust installations with version 1.9.10.X. An exact match down to the patch version can be forced by using EXACT matching:

find_package(Thrust 1.9.10.1 EXACT)

would only match the 1.9.10.1 release.

Using an Explicit TBB or OpenMP CMake Target

When thrust_create_target is called, it will lazily load the requested systems on-demand through internal find_package calls. If a project already uses TBB or OpenMP, it may specify a CMake target for Thrust to share instead:

thrust_set_TBB_target(MyTBBTarget)
thrust_set_OMP_target(MyOMPTarget)

These functions must be called before the corresponding system is loaded through thrust_create_target or find_package(Thrust COMPONENT [OMP|TBB]).

Using an Explicit libcu++ CMake Target

In contrast to the optional TBB/OMP dependencies, there is no thrust_set_libcudacxx_target function that specifies an explicit libcu++ target. This is because libcu++ is always required and must be found during the initial find_target(Thrust) call that defines these functions.

To force Thrust to use a specific libcu++ target, ensure that either the Thrust::libcudacxx or libcudacxx::libcudacxx targets are defined prior to the first invocation of find_package(Thrust). Thrust will automatically use these, giving preference to the Thrust::libcudacxx target.

Testing for Systems

The following functions check if a system has been found, either by lazy loading through thrust_create_target or as a find_package COMPONENT / OPTIONAL_COMPONENT:

# Set var_name to TRUE or FALSE if an individual system has been found:
thrust_is_cuda_system_found(<var_name>)
thrust_is_cpp_system_found(<var_name>)
thrust_is_tbb_system_found(<var_name>)
thrust_is_omp_system_found(<var_name>)

# Generic version that takes a component name from CUDA, CPP, TBB, OMP:
thrust_is_system_found(<component_name> <var_name>)

# Defines `THRUST_*_FOUND` variables in the current scope that reflect the
# state of all known systems. Can be used to refresh these flags after
# lazy system loading.
thrust_update_system_found_flags()

Debugging

Thrust will produce a detailed log describing its targets, cache options, and interfaces when --log-level=VERBOSE is passed to CMake:

$ cmake . --log-level=VERBOSE

This can be handy for inspecting interface and dependency information.

Fixing Legacy FindThrust.cmake

A community-created FindThrust.cmake module exists and is necessary to find Thrust installations prior to Thrust 1.9.10. Its usage is discouraged whenever possible and the config files in this directory should be strongly preferred. However, projects that need to support old versions of Thrust may still need to use the legacy FindThrust.cmake with pre-1.9.10 installations.

One popular flavor of this find module has a version parsing bug. Projects that rely on FindThrust.cmake should check for this and patch their copies as follows.

Replace:

string( REGEX MATCH "^[0-9]" major ${version} )
string( REGEX REPLACE "^${major}00" "" version "${version}" )
string( REGEX MATCH "^[0-9]" minor ${version} )
string( REGEX REPLACE "^${minor}0" "" version "${version}" )

with:

math(EXPR major "${version} / 100000")
math(EXPR minor "(${version} / 100) % 1000")
math(EXPR version "${version} % 100")

Thrust Developer Documentation

This portion of the file contains descriptions of Thrust's internal CMake target structure for Thrust developers. It should not be necessary for users who just want to use Thrust from their projects.

Internal Targets

By default, find_package(Thrust) will only create a single Thrust::Thrust target that describes where the actual Thrust headers are located. It does not locate or create configurations for any dependencies; these are lazily loaded on-demand by calls to create_thrust_target, or when explicitly requested via find_package's component mechanism.

As mentioned, the basic Thrust interface is described by the Thrust::Thrust target.

Each backend system (CPP, CUDA, TBB, OMP) is described by multiple targets:

  • Thrust::${system}
    • Specifies an interface configured to build against all dependencies for this backend (including Thrust::Thrust).
    • For example, the Thrust::CUDA target is an interface target that combines the interfaces of both Thrust and CUB.
  • Thrust::${system}::Host
    • Configures an interface for using a specific host system.
    • Multiple ::Host targets cannot be combined in the same library/executable. Attempting to do so will produce a CMake configuration error.
    • Only defined for systems that support being used as the host.
  • Thrust::${system}::Device
    • Configures an interface for using a specific device system.
    • Multiple ::Device targets cannot be combined in the same library/executable. Attempting to do so will produce a CMake configuration error.
    • Only defined for systems that support being used as the device.