Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,29 @@ else()
message(FATAL_ERROR "Failed to determine TensorRT LLM version")
endif()

# Where the configured executor/version.h is written. Out-of-tree builds point
# this at the build tree so the source tree is never written (it may be mounted
# read-only); the default keeps the in-source location.
set(TRTLLM_VERSION_H_INCLUDE_DIR
"${CMAKE_CURRENT_SOURCE_DIR}/include"
CACHE PATH "Include root for the configured executor/version.h")
configure_file(
cmake/templates/version.h
${CMAKE_CURRENT_SOURCE_DIR}/include/tensorrt_llm/executor/version.h)
"${TRTLLM_VERSION_H_INCLUDE_DIR}/tensorrt_llm/executor/version.h")
if(NOT TRTLLM_VERSION_H_INCLUDE_DIR STREQUAL
"${CMAKE_CURRENT_SOURCE_DIR}/include")
# BEFORE: the configured header must win over a stale in-source copy.
include_directories(BEFORE "${TRTLLM_VERSION_H_INCLUDE_DIR}")
endif()

# Generated FMHA sources (see contextFusedMultiHeadAttention/CMakeLists.txt for
# the full definition and default). fmha_cubin.h is included transitively by
# headers used across several targets, so when generation is redirected out of
# the source tree the directory must be on every target's include path, not just
# the FMHA target's.
if(DEFINED TRTLLM_FMHA_GEN_DIR AND NOT "${TRTLLM_FMHA_GEN_DIR}" STREQUAL "")
include_directories("${TRTLLM_FMHA_GEN_DIR}")
endif()

setup_cuda_compiler()

Expand Down
5 changes: 4 additions & 1 deletion cpp/kernels/fmha_v2/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2394,7 +2394,10 @@ def get_kernel_code(kspec, kname, lname):
params_str = 'reinterpret_cast<bert::Fused_multihead_attention_params_v2 &>(params)' if generate_cu_trtllm else 'params'
attn_mask_type_str = 'using Attention_mask_type = ContextAttentionMaskType;' if generate_cu_trtllm else 'using Attention_mask_type = fmha::Attention_mask_type;'
bert_launch_params = '' if generate_cu_trtllm else 'using Launch_params = bert::Fused_multihead_attention_launch_params;'
include_str = '#include "../fused_multihead_attention_common.h"\n' if generate_cu_trtllm else ''
# No "../" prefix: the generated .cu may live outside the source tree
# (TRTLLM_FMHA_GEN_DIR); the consuming CMake target puts the
# contextFusedMultiHeadAttention directory on the include path.
include_str = '#include "fused_multihead_attention_common.h"\n' if generate_cu_trtllm else ''
include_str += '#include "tensorrt_llm/common/config.h"' if generate_cu_trtllm else ''
num_compute_groups_str = '' if generate_cu_trtllm else 'static constexpr int NUM_COMPUTE_GROUPS = 2;'
fused_multihead_attention_params_v2_str = 'Fused_multihead_attention_params_v2' if generate_cu_trtllm else f'{params_type}'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,31 @@
# the License.
#

# Directory holding the generated FMHA sources (fmha_v2_cu/*.cu and
# cubin/fmha_cubin.{h,cpp}). scripts/build_wheel.py points this at an
# out-of-tree location when --out-of-tree is set; by default the generated files
# live in this directory as before.
set(TRTLLM_FMHA_GEN_DIR
"${CMAKE_CURRENT_SOURCE_DIR}"
CACHE PATH "Directory containing generated FMHA sources")

file(GLOB_RECURSE SRC_CPP *.cpp)
file(GLOB_RECURSE SRC_CU *.cu)
list(FILTER SRC_CU EXCLUDE REGEX "fmha_v2_cu/.*")
# fmha_cubin.cpp is generated; always take it from TRTLLM_FMHA_GEN_DIR so an
# out-of-tree copy is used when configured and a stale in-tree copy is never
# compiled alongside it.
list(FILTER SRC_CPP EXCLUDE REGEX "cubin/fmha_cubin\\.cpp$")
if(EXISTS "${TRTLLM_FMHA_GEN_DIR}/cubin/fmha_cubin.cpp")
list(APPEND SRC_CPP "${TRTLLM_FMHA_GEN_DIR}/cubin/fmha_cubin.cpp")
else()
message(
FATAL_ERROR
"Generated FMHA source ${TRTLLM_FMHA_GEN_DIR}/cubin/fmha_cubin.cpp is "
"missing. It is produced by the FMHA generation step "
"(scripts/build_wheel.py runs it before CMake); a missing file means "
"generation did not complete. Regenerate before configuring.")
endif()
Comment thread
coderabbitai[bot] marked this conversation as resolved.
# The skip_softmax sm_120/sm_121 warp-specialized FMHA is a hand-written TU that
# only compiles for the sm_120 family; it is added explicitly to the sm_120 arch
# target below, not to the all-arch source list.
Expand All @@ -31,6 +53,9 @@ filter_source_cuda_architectures(
IMPLICIT_FAMILY)

target_sources(context_attention_src PRIVATE ${SRC_CPP} ${SRC_CU})
# For #include "cubin/fmha_cubin.h" when the generated header is out of tree.
target_include_directories(context_attention_src
PRIVATE "${TRTLLM_FMHA_GEN_DIR}")
target_compile_definitions(context_attention_src PRIVATE USE_DEMO_BERT_PARAMS=1
GENERATE_CUBIN=1)
set_target_properties(
Expand Down Expand Up @@ -68,7 +93,7 @@ foreach(arch IN ITEMS 80 86 89 90 100 120)
continue()
endif()

file(GLOB arch_files "fmha_v2_cu/*_sm${arch}.cu")
file(GLOB arch_files "${TRTLLM_FMHA_GEN_DIR}/fmha_v2_cu/*_sm${arch}.cu")
# Compile the hand-written skip_softmax warp-specialized FMHA into the sm_120
# family target. It uses sm_120-only TMA + sync-MMA, so it must never be
# compiled for other architectures.
Expand All @@ -94,12 +119,28 @@ foreach(arch IN ITEMS 80 86 89 90 100 120)
set_target_properties(
${TARGET_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON
CUDA_RESOLVE_DEVICE_SYMBOLS ON)
# CMAKE_CURRENT_SOURCE_DIR resolves the generated kernels' #include
# "fused_multihead_attention_common.h" when they live out of tree (and is
# where includer-relative lookup lands in-tree).
target_include_directories(
${TARGET_NAME}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../../kernels/fmha_v2/src/
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/../../../kernels/fmha_v2/src/
${CMAKE_CURRENT_SOURCE_DIR}/../../../kernels/fmha_v2/generated/)
set_cuda_architectures(${TARGET_NAME} ${TARGET_ARCH})
target_sources(context_attention_src
PUBLIC $<TARGET_OBJECTS:${TARGET_NAME}>)
else()
# arch is enabled (disabled archs already `continue`d above) but the
# generation step produced no *_sm${arch}.cu kernels for it. Fail rather
# than silently building without this architecture's FMHA kernels, which
# would surface only as a missing-kernel failure at runtime. (arch 120
# always has the hand-written skip_softmax TU appended above, so this branch
# covers the generated-only architectures.)
message(
FATAL_ERROR
"No generated FMHA kernels (*_sm${arch}.cu) found in "
"${TRTLLM_FMHA_GEN_DIR}/fmha_v2_cu for enabled architecture ${arch}. "
"The FMHA generation step did not produce sources for this arch.")
endif()
endforeach()
12 changes: 11 additions & 1 deletion docs/source/installation/build-from-source.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ With `--build_root <dir>` set, the following default under `<dir>` instead of th

Conan's `cpp/CMakeUserPresets.json` convenience file is also skipped in this mode, since it would reference the (possibly ephemeral) out-of-tree build directory.

Only final artifacts are still written into the checkout: `tensorrt_llm/libs`, `tensorrt_llm/include`, Python bindings and stubs, generated FMHA kernel sources, and the `.whl` output directory (`--dist_dir`).
Only final artifacts are still written into the checkout: `tensorrt_llm/libs`, `tensorrt_llm/include`, Python bindings and stubs, generated FMHA kernel sources, the configured `cpp/include/tensorrt_llm/executor/version.h`, and the `.whl` output directory (`--dist_dir`).

Related knobs for shared-storage workflows:

Expand All @@ -119,6 +119,16 @@ Related knobs for shared-storage workflows:

Plain local-disk builds are unaffected: without `--build_root`, all paths behave as before.

#### Out-of-tree wheel builds (read-only checkout)

For CI or ephemeral-node workflows that only need a wheel, add `--out-of-tree` to guarantee the checkout is never written — it can even be mounted read-only:

```bash
python3 scripts/build_wheel.py --build_root /tmp/trtllm-build --out-of-tree --use_ccache -a "90-real"
```

In this mode the generated FMHA kernel sources and the configured `version.h` go to the build tree (via the `TRTLLM_FMHA_GEN_DIR` and `TRTLLM_VERSION_H_INCLUDE_DIR` CMake variables), and the wheel is assembled from a staging copy of the Python package under `<build_root>/package`, landing in `<build_root>/dist` by default. Submodules and git-lfs content must be materialized before the build (the usual `git submodule update --init --recursive`), since the build will not modify the checkout. Editable-install workflows (`--skip_building_wheel`, `--linking_install_binary`, `--install`) are incompatible with `--out-of-tree`: they import compiled artifacts from the checkout by design. `--version-override` is also incompatible, since it edits `tensorrt_llm/version.py` in the checkout.

### Python-only build (no C++ compilation)

If you only need to modify Python code, you can skip C++ compilation entirely by reusing precompiled binaries:
Expand Down
Loading
Loading