Skip to content

feat: Build hipSPARSELt device libraries via find_package(hipblaslt); ship tensilelite-host shared#9248

Open
davidd-amd wants to merge 1 commit into
developfrom
users/davidd-amd/tensilelite-shared-p3-codegen
Open

feat: Build hipSPARSELt device libraries via find_package(hipblaslt); ship tensilelite-host shared#9248
davidd-amd wants to merge 1 commit into
developfrom
users/davidd-amd/tensilelite-shared-p3-codegen

Conversation

@davidd-amd

Copy link
Copy Markdown
Contributor

Summary

This completes the TensileLite shared-library work. P1 (#7996) made origami a findable
package and P2 (#8133) turned tensilelite-host into an exportable target and landed the
hipblaslt_create_device_library() codegen module — but P2 shipped tensilelite-host
static by default and left hipSPARSELt building a private, in-tree copy of hipBLASLt via
add_subdirectory(hipblaslt).

This PR flips the switch: tensilelite-host builds shared by default, and hipSPARSELt
stops rebuilding hipBLASLt from source. Instead it consumes the installed hipBLASLt package
via find_package(hipblaslt CONFIG) and generates its own sparse device libraries by calling
the exported hipblaslt_create_device_library(). The result is a single shared
libtensilelite-host.so across both consumers (true structural dedup) and no duplicate
hipBLASLt build inside hipSPARSELt.

What changed

Five files, +91 / -32:

  • projects/hipsparselt/CMakeLists.txt — the core change. Replace the inline
    add_subdirectory(hipblaslt) (which built a private HOST-off/DEVICE-on hipBLASLt in
    hipSPARSELt's own tree) with find_package(hipblaslt CONFIG REQUIRED). When
    HIPSPARSELT_ENABLE_DEVICE, drive sparse codegen through the exported
    hipblaslt_create_device_library() against the binary package: point
    HIPBLASLT_CODEGEN_ROOT at the hipBLASLt tensilelite source (same repo, deliberately
    not installed), locate the installed rocisa from the imported roc::tensilelite-host
    target, and set PYTHONPATH/LD_LIBRARY_PATH/PATH for the codegen subprocess. Install
    the generated library/ to lib/hipsparselt.
  • projects/hipblaslt/tensilelite/CMakeLists.txt — default TENSILELITE_BUILD_SHARED_LIBS
    to ON, so the integrated build produces one co-exported libtensilelite-host.so instead
    of statically embedding a copy in each consumer (the dedup P2 deferred).
  • projects/hipblaslt/tensilelite/rocisa/CMakeLists.txt — install the rocisa extension
    (_rocisa, __init__.py, and the bundled libstinkytofu) to lib/hipblaslt/rocisa under
    the new option, so a downstream consumer can import rocisa when running codegen against
    the staged package. Guarded on HIPBLASLT_INSTALL_ROCISA AND NOT ROCISA_STANDALONE.
  • projects/hipblaslt/CMakeLists.txt — add option(HIPBLASLT_INSTALL_ROCISA ...),
    defaulting to HIPBLASLT_ENABLE_HOST.
  • projects/hipblaslt/cmake/HipBLASLtCodegen.cmake — honor HIPBLASLT_CODEGEN_ROOT when
    set (falling back to the in-source path), so a separate-subproject consumer can point the
    codegen at the hipBLASLt source tree.

Downstream (TheRock) coordination — not in this PR

The super-project consumer wiring lands in a separate TheRock PR (ROCm/TheRock#5650):
origami declared as a shared BLAS subproject, hipSPARSELt gaining hipBLASLt/origami
(RUNTIME) and hipBLAS-common (BUILD) deps so find_package(hipblaslt) and the transitive
find_dependency(hipblas-common) resolve, and the artifact manifest claiming
lib/hipblaslt/rocisa/**. Because rocm-libraries -> TheRock pin bumps are automated, that
TheRock PR must be merged before the automated bump of this commit, or the composed build
breaks. This is a merge-time sequencing item, not a code dependency in this PR.

JIRA ID

Test Plan

  • Integrated (TheRock super-project) build with the matching [CK_TILE] Add kpack example 06: FMHA BWD OGradDotO #5650 consumer wiring, gfx90a:
    • cmake -B build -GNinja . -DTHEROCK_AMDGPU_FAMILIES=gfx90a -DTHEROCK_BUILD_TESTING=OFF -DTHEROCK_FLAG_INCLUDE_PROFILER=ON
    • ninja -C build origami hipBLASLt hipSPARSELt
    • Confirm hipSPARSELt configures through find_package(hipblaslt) (no add_subdirectory),
      links the single libtensilelite-host.so, rocisa is installed with hipBLASLt and found
      by hipSPARSELt codegen, and sparse TensileLibrary_*_<arch>.co / .dat.zlib are
      generated and staged.
  • Static fallback: -DTENSILELITE_BUILD_SHARED_LIBS=OFF still builds and embeds.

Test Result

Built in the TheRock manylinux container (gfx90a) with the #5650 consumer wiring
(reland-origami tip) and the rocm-libraries submodule pinned at this commit:

  • origami -> hipBLASLt -> hipSPARSELt build: rc=0.
  • hipSPARSELt consumes the binary hipBLASLt package — resolves
    find_package(hipblaslt 1.2.2 CONFIG ... PATHS .../hipBLASLt/dist/lib/cmake/hipblaslt) and
    builds host-only in ~14s with no add_subdirectory(hipblaslt) (grep of the subproject
    cache confirms it is absent).
  • The exported codegen function is available downstreamhipblaslt-config.cmake
    includes HipBLASLtCodegen.cmake, so hipblaslt_create_device_library is defined after
    find_package(hipblaslt).
  • rocisa installs to lib/hipblaslt/rocisa (_rocisa.abi3.so, __init__.py, bundled
    libstinkytofu.so).

Not yet verified locally: end-to-end sparse .co/.dat generation in this build. The
hipSPARSELt subproject received an empty GPU_TARGETS in the local super-project
configuration, so HIPSPARSELT_ENABLE_DEVICE was gated off (CMakeLists.txt line ~88) and the
codegen step did not run. That is a super-project arch-propagation detail, not a defect in
this change; it is exercised in the TheRock CI pipeline once the pin is bumped. The device
codegen path should be confirmed green in the TheRock pipeline before this merges.

Related

Submission Checklist

…+ installable rocisa

hipSPARSELt consumes hipBLASLt via find_package(hipblaslt CONFIG REQUIRED) and
generates its own sparse Tensile device libraries by calling the exported
hipblaslt_create_device_library(), instead of add_subdirectory(hipblaslt).

The Tensile codegen Python is read from the hipBLASLt source tree (same repo,
not installed). The compiled rocisa extension IS a build-time requirement for a
separate-subproject consumer, so it is made installable and installed with
hipBLASLt (lib/hipblaslt/rocisa); hipSPARSELt derives its directory from the
imported roc::tensilelite-host target's location.

- tensilelite/CMakeLists.txt: default tensilelite-host to shared.
- tensilelite/rocisa/CMakeLists.txt: HIPBLASLT_INSTALL_ROCISA installs rocisa
  (+ bundled libstinkytofu) in the integrated build.
- hipblaslt/CMakeLists.txt: add HIPBLASLT_INSTALL_ROCISA option (default HOST).
- cmake/HipBLASLtCodegen.cmake: honor HIPBLASLT_CODEGEN_ROOT (else source fallback).
- hipsparselt/CMakeLists.txt: find_package(hipblaslt) + create_device_library,
  Tensile from source, rocisa via tensilelite-host target location.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@therock-pr-bot

therock-pr-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown

❌ PR Check — Action Required

Check Status Details
🌿 Branch Name ✅ Pass
📝 PR Title/Description ❌ Fail Error: Title is too long (98 characters).
Expected: at most 80 characters.
Desired format: type(optional-scope): short description
Forbidden Files ✅ Pass
🧪 Unit Test ✅ Pass PR does not contain code files — Unit Test auto-passed
🔎 pre-commit ✅ Pass
🚫 Draft PR 🔜 To Be Enabled
🚩 Feature Flag 🔜 To Be Enabled
📊 Code Coverage 🔜 To Be Enabled

⚠️ 1 policy check(s) failed. Please address the issues above before this PR can be Reviewed.

🚫 Please fix the failed policies

  • ❌ PR Title/Description

The Not ready to Review label was added to this PR. Once all policies pass, the label is removed automatically.

📖 Need help? See the Policy FAQ for details on every check and how to fix failures.

@therock-pr-bot

therock-pr-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown

🚫 Please fix the failed policies before requesting reviews.

The following policy checks failed:

  • ❌ PR Title/Description

The Not ready to Review label has been added to this PR.
Once all policies pass, the label will be removed automatically.

@codecov-commenter

codecov-commenter commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

❌ Your project status has failed because the head coverage (76.92%) is below the target coverage (80.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #9248      +/-   ##
===========================================
- Coverage    64.99%   64.99%   -0.00%     
===========================================
  Files         2685     2685              
  Lines       422116   422157      +41     
  Branches     62707    62717      +10     
===========================================
+ Hits        274344   274356      +12     
- Misses      127073   127102      +29     
  Partials     20699    20699              
Flag Coverage Δ *Carryforward flag
TensileLite 34.86% <ø> (ø)
hipBLAS 90.81% <ø> (ø) Carriedforward from 83cd82f
hipBLASLt 34.70% <ø> (-0.01%) ⬇️
hipCUB 82.68% <ø> (ø) Carriedforward from 83cd82f
hipDNN 86.15% <ø> (ø) Carriedforward from 83cd82f
hipFFT 50.88% <ø> (ø) Carriedforward from 83cd82f
hipRAND 76.12% <ø> (ø) Carriedforward from 83cd82f
hipSOLVER 69.18% <ø> (ø) Carriedforward from 83cd82f
hipSPARSE 86.10% <ø> (ø) Carriedforward from 83cd82f
rocBLAS 47.91% <ø> (ø) Carriedforward from 83cd82f
rocFFT 50.80% <ø> (ø) Carriedforward from 83cd82f
rocRAND 57.02% <ø> (ø) Carriedforward from 83cd82f
rocSOLVER 76.92% <ø> (ø) Carriedforward from 83cd82f
rocSPARSE 72.37% <ø> (ø) Carriedforward from 83cd82f
rocThrust 91.36% <ø> (ø) Carriedforward from 83cd82f

*This pull request uses carry forward flags. Click here to find out more.
see 5 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@davidd-amd davidd-amd changed the title [hipblaslt][hipsparselt] Build hipSPARSELt device libraries via find_package(hipblaslt); ship tensilelite-host shared feat: Build hipSPARSELt device libraries via find_package(hipblaslt); ship tensilelite-host shared Jul 9, 2026
if(NOT EXISTS "${HIPBLASLT_PATH}")
message(FATAL_ERROR "hipBLASLt required but no not found at ${HIPBLASLT_PATH}.")
endif()
find_package(hipblaslt CONFIG REQUIRED)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hipblaslt only conditionally builds tensilelite-host.

The old approach forced TENSILELITE_BUILD_SHARED_LIBS to true to ensure we had tensilelite-host. This new build does not guarantee that the hipblaslt we find has tensilelite-host installed.

It's needed by hipsparselt/library/src/hcc_detail/rocsparselt/CMakeLists.txt:31

set(HIPBLASLT_PYTHON_COMMAND
"${CMAKE_COMMAND}" -E env
"PYTHONPATH=$<TARGET_FILE_DIR:roc::tensilelite-host>/hipblaslt:${HIPBLASLT_CODEGEN_ROOT}"
"LD_LIBRARY_PATH=$<TARGET_FILE_DIR:roc::origami>:${_hipsparselt_rocisa_dir}:$ENV{LD_LIBRARY_PATH}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this also needs something for libstinkytofu

Comment on lines 64 to 66
$<BUILD_INTERFACE:rocisa::rocisa-cpp>
$<BUILD_INTERFACE:roc::origami>
$<BUILD_INTERFACE:hip::host>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't these also be install_interface. I believe that the resulting public headers for tensillite-host will have references to all three of these dependencies. We're currently fine since all three are being important manually wherever tensilelite is used.

Comment on lines +76 to +78
option(HIPBLASLT_INSTALL_ROCISA
"Install the rocisa Python extension with hipBLASLt so downstream consumers (e.g. hipSPARSELt) can import it to run device-library codegen against the staged hipBLASLt package."
${HIPBLASLT_ENABLE_HOST})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is misleading since it makes it sound like it enforces that rocisa will be installed. But I don't think that's true.

The the python rocisa extension is gated on: (HIPBLASLT_BUNDLE_PYTHON_DEPS OR ROCISA_STANDALONE) (rocisa/CMakeLists.txt:40)

For an integrated build, the second condition is false. So we need HIPBLASLT_BUNDLE_PYTHON_DEPS to build it.

This won't error out in the build, because the install(TARGETS _rocisa ...) is gated off, but the final install tree won't have the needed rocisa files.

# Tensile's toolchain validator resolves hipconfig (and clang) from PATH;
# provide the hip runtime bin dir and the compiler dir so the codegen
# subprocess finds them (mirrors hipBLASLt's own bundled-python PATH).
get_filename_component(_hipsparselt_hip_bindir "${hip_DIR}/../../../bin" ABSOLUTE)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks both fragile, and linux specific.

# subprocess finds them (mirrors hipBLASLt's own bundled-python PATH).
get_filename_component(_hipsparselt_hip_bindir "${hip_DIR}/../../../bin" ABSOLUTE)
get_filename_component(_hipsparselt_cxx_bindir "${CMAKE_CXX_COMPILER}" DIRECTORY)
set(HIPBLASLT_PYTHON_COMMAND

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hiblaslt has a helper function for something very similar: hipblaslt_configure_bundled_python_command.

Hisparselt's cmake file is depending on implementation details from inside hipblaslt. Can this be cleaned up so there isn't as much duplication?

)
endif()

add_subdirectory("${HIPBLASLT_PATH}" hipblaslt)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This used to call hipblaslt/device-library/CMakeLists.txt, which forwarded many build flags that are no longer being hooked up.

E.g. hipsparselt/install-host.sh:684 sets:

if [[ "${keep_build_tmp}" == true ]]; then
    tensile_opt="${tensile_opt} -DTENSILELITE_KEEP_BUILD_TMP=ON"
fi

But that goes nowhere now.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing this out, @Alex-Vasile. I wasn't aware that some of these build flags are no longer being propagated.

One thing I'm concerned about is that we still need a mechanism to keep the generated ASM files. Previously, we relied on build flags such as TENSILELITE_KEEP_BUILD_TMP for this purpose.

@davidd-amd, is there currently any way to preserve the generated ASM files with the new build flow?

This doesn't need to be addressed in this PR, but I'd like to make sure the requirement is captured.

find_package(ZLIB REQUIRED)

option(TENSILELITE_BUILD_SHARED_LIBS "Build tensilelite-host as shared vs static" OFF)
option(TENSILELITE_BUILD_SHARED_LIBS "Build tensilelite-host as shared vs static" ON)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we now run invoke build --static we get a static hipblaslt but a shared tensilelite-host. That seems counter-intuitive for someone asking for a static build.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants