-
Notifications
You must be signed in to change notification settings - Fork 35
Initial integration of a4w4 GEMM #663
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Micky774
wants to merge
1
commit into
dev
Choose a base branch
from
zain/aiter/a4w4-integration
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Submodule QoLA
updated
8 files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| # Copyright (c) 2026, Advanced Micro Devices, Inc. All rights reserved. | ||
| # SPDX-License-Identifier: MIT | ||
|
|
||
| cmake_minimum_required(VERSION 3.21) | ||
| set(CMAKE_CXX_STANDARD 17) | ||
| project(aiter_gemm LANGUAGES HIP CXX) | ||
|
|
||
| set(AITER_GEMM_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/transformer_engine/lib") | ||
|
|
||
| # a4w4 kernels are gfx950-only (ASM f4gemm .co blobs ship for gfx950). Drop | ||
| # unsupported arches; a runtime guard covers dispatch. | ||
| set(__AG_SUPPORTED_ARCHS "gfx950") | ||
| set(__AG_ARCHS) | ||
| foreach(__arch ${CMAKE_HIP_ARCHITECTURES}) | ||
| if(__arch IN_LIST __AG_SUPPORTED_ARCHS) | ||
| list(APPEND __AG_ARCHS ${__arch}) | ||
| else() | ||
| message(WARNING "[aiter_gemm] Skipping unsupported arch ${__arch} for a4w4 GEMM build.") | ||
| endif() | ||
| endforeach() | ||
| if(NOT __AG_ARCHS) | ||
| message(FATAL_ERROR | ||
| "[aiter_gemm] No supported architectures (need one of: ${__AG_SUPPORTED_ARCHS}). " | ||
| "Re-run the build with NVTE_AITER_GEMM=0 to disable the a4w4 GEMM backend.") | ||
| endif() | ||
|
|
||
| set(__QOLA_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../3rdparty/QoLA") | ||
| set(__AITER_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/qola/third_party/aiter") | ||
| if(DEFINED ENV{NVTE_AITER_SOURCE_DIR} AND NOT $ENV{NVTE_AITER_SOURCE_DIR} STREQUAL "") | ||
| set(__AITER_SOURCE_DIR $ENV{NVTE_AITER_SOURCE_DIR}) | ||
| message(STATUS "[aiter_gemm] Using AITER source from NVTE_AITER_SOURCE_DIR=${__AITER_SOURCE_DIR}. Disable AITER checkout.") | ||
| set(__SKIP_AITER_CHECKOUT TRUE) | ||
| else() | ||
| set(__SKIP_AITER_CHECKOUT FALSE) | ||
| endif() | ||
| set(AITER_INCLUDE_DIR "${__AITER_SOURCE_DIR}/csrc/include") | ||
|
|
||
| if(NOT Python_EXECUTABLE) | ||
| find_package(Python COMPONENTS Interpreter QUIET) | ||
| endif() | ||
|
|
||
| # Resolve the manifest-pinned AITER commit (defines AITER_SHA). | ||
| set(__QOLA_MANIFEST "${CMAKE_CURRENT_LIST_DIR}/qola_manifest.toml") | ||
| set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${__QOLA_MANIFEST}") | ||
| file(STRINGS "${__QOLA_MANIFEST}" __AITER_COMMIT_LINES | ||
| REGEX "^[ \t]*aiter_commit[ \t]*=[ \t]*\"[^\"]+\"") | ||
| list(LENGTH __AITER_COMMIT_LINES __AITER_COMMIT_COUNT) | ||
| if(NOT __AITER_COMMIT_COUNT EQUAL 1) | ||
| message(FATAL_ERROR | ||
| "Expected exactly one 'aiter_commit = \"...\"' line in ${__QOLA_MANIFEST}.") | ||
| endif() | ||
| list(GET __AITER_COMMIT_LINES 0 __AITER_COMMIT_LINE) | ||
| string(REGEX MATCH "\"([^\"]+)\"" _UNUSED "${__AITER_COMMIT_LINE}") | ||
| set(AITER_SHA "${CMAKE_MATCH_1}") | ||
|
|
||
| if(Python_EXECUTABLE AND NOT __SKIP_AITER_CHECKOUT) | ||
| execute_process( | ||
| COMMAND sh -c | ||
| "PYTHONPATH=\"${__QOLA_DIR}:$PYTHONPATH\" '${Python_EXECUTABLE}' -m qola.cli checkout \ | ||
| --manifest '${__QOLA_MANIFEST}' \ | ||
| --aiter-root '${__AITER_SOURCE_DIR}'" | ||
| RESULT_VARIABLE AITER_CHECKOUT_RESULT | ||
| OUTPUT_VARIABLE AITER_CHECKOUT_OUTPUT | ||
| ERROR_VARIABLE AITER_CHECKOUT_ERROR) | ||
| if(NOT AITER_CHECKOUT_RESULT EQUAL 0) | ||
| message(FATAL_ERROR | ||
| "[aiter_gemm] Failed to sync AITER source at ${__AITER_SOURCE_DIR} to ${AITER_SHA}.\n" | ||
| "${AITER_CHECKOUT_OUTPUT}\n${AITER_CHECKOUT_ERROR}") | ||
| endif() | ||
| message(STATUS "[aiter_gemm] Synced ${__AITER_SOURCE_DIR} to ${AITER_SHA}") | ||
| endif() | ||
|
|
||
| if(NOT EXISTS "${AITER_INCLUDE_DIR}") | ||
| message(FATAL_ERROR | ||
| "[aiter_gemm] Could not find AITER API at ${AITER_INCLUDE_DIR}.") | ||
| endif() | ||
|
|
||
| # Obtain the torch-free kernel libs: prebuilt bypass or build from source (QoLA). | ||
| set(__AITER_GEMM_LIB_PATH "") | ||
| set(__QOLA_INCLUDE_DIR "") | ||
| if(DEFINED ENV{AITER_GEMM_PATH}) | ||
| message(STATUS "[aiter_gemm] Using prebuilt libs from AITER_GEMM_PATH=$ENV{AITER_GEMM_PATH}") | ||
| set(__AITER_GEMM_LIB_PATH "$ENV{AITER_GEMM_PATH}/lib") | ||
| set(__QOLA_INCLUDE_DIR "$ENV{AITER_GEMM_PATH}/include") | ||
| else() | ||
| list(JOIN __AG_ARCHS ";" GPU_ARCHS_STR) | ||
| set(__QOLA_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/qola") | ||
| message(STATUS "[aiter_gemm] Building a4w4 GEMM kernels for ${GPU_ARCHS_STR} via QoLA.") | ||
| execute_process( | ||
| COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${__QOLA_DIR}:$ENV{PYTHONPATH}" | ||
| ${Python_EXECUTABLE} -m qola.cli build | ||
| --manifest ${__QOLA_MANIFEST} | ||
| --aiter-root ${__AITER_SOURCE_DIR} | ||
| --output-dir ${__QOLA_BUILD_DIR} | ||
| --arch "${GPU_ARCHS_STR}" | ||
| --skip-checkout | ||
| RESULT_VARIABLE QOLA_BUILD_RESULT) | ||
| if(NOT QOLA_BUILD_RESULT EQUAL 0) | ||
| message(FATAL_ERROR "[aiter_gemm] QoLA build failed.") | ||
| endif() | ||
| set(__AITER_GEMM_LIB_PATH "${__QOLA_BUILD_DIR}/lib") | ||
| set(__QOLA_INCLUDE_DIR "${__QOLA_BUILD_DIR}/include") | ||
| endif() | ||
|
|
||
| if(NOT EXISTS "${__QOLA_INCLUDE_DIR}/qola_config.h") | ||
| message(FATAL_ERROR "[aiter_gemm] Could not find QoLA public headers at ${__QOLA_INCLUDE_DIR}.") | ||
| endif() | ||
|
|
||
| add_library(aiter_gemm SHARED src/aiter_gemm_a4w4.cpp) | ||
| target_include_directories(aiter_gemm PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") | ||
| target_include_directories(aiter_gemm PRIVATE ${AITER_INCLUDE_DIR} ${__QOLA_INCLUDE_DIR}) | ||
|
|
||
| find_package(hip) | ||
| target_link_directories(aiter_gemm PUBLIC ${__AITER_GEMM_LIB_PATH}) | ||
| target_link_libraries(aiter_gemm PUBLIC | ||
| hip::host hip::device | ||
| -l:te_libgemm_a4w4_blockscale.so | ||
| -l:te_libgemm_a4w4_asm.so) | ||
| set_target_properties(aiter_gemm PROPERTIES INSTALL_RPATH "$ORIGIN") | ||
|
|
||
| if(NOT "${__AITER_GEMM_LIB_PATH}" STREQUAL "${AITER_GEMM_INSTALL_DIR}") | ||
| install(FILES | ||
| ${__AITER_GEMM_LIB_PATH}/te_libgemm_a4w4_blockscale.so | ||
| ${__AITER_GEMM_LIB_PATH}/te_libgemm_a4w4_asm.so | ||
| DESTINATION ${AITER_GEMM_INSTALL_DIR}) | ||
| endif() | ||
| install(TARGETS aiter_gemm DESTINATION ${AITER_GEMM_INSTALL_DIR}) | ||
82 changes: 82 additions & 0 deletions
82
transformer_engine/common/aiter_gemm/include/aiter_gemm/aiter_gemm.hpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| /************************************************************************* | ||
| * Copyright (c) 2026, Advanced Micro Devices, Inc. All rights reserved. | ||
| * | ||
| * License for AMD contributions = MIT. See LICENSE for more information | ||
| ************************************************************************/ | ||
|
|
||
| #ifndef AITER_GEMM_H | ||
| #define AITER_GEMM_H | ||
|
|
||
| #include <cstdint> | ||
| #include <hip/hip_runtime.h> | ||
|
|
||
| // TE-side wrapper around AITER's torch-free a4w4 (FP4 x FP4) GEMM kernels. | ||
| // | ||
| // This header is intentionally free of any AITER / QoLA headers so that | ||
| // libtransformer_engine.so can consume it without pulling in the AITER kernel | ||
| // headers. The translation to AITER's aiter_tensor_t POD lives in the .cpp. | ||
| // | ||
| // Kernel selection (tuned-CSV lookup) and weight/scale pre-shuffling are the | ||
| // caller's responsibility -- these entry points are thin executors that take a | ||
| // resolved kernel name and already-shuffled inputs. | ||
| namespace aiter_gemm { | ||
|
|
||
| // Mirrors AiterDtype in AITER's aiter_enum.h (only the subset a4w4 needs). | ||
| enum class DType { | ||
| fp4x2 = 0, /*!< two packed FP4 (E2M1) values per byte */ | ||
| e8m0 = 1, /*!< 8-bit exponent-only microscaling factor (1 byte) */ | ||
| bf16 = 2, | ||
| fp16 = 3, | ||
| fp32 = 4, | ||
| u8 = 5, | ||
| i8 = 6, | ||
| }; | ||
|
|
||
| // Lightweight tensor descriptor (raw device pointer + layout). The caller owns | ||
| // the storage; the descriptor must outlive the call but not the storage. | ||
| struct TensorDesc { | ||
| void* ptr = nullptr; | ||
| int ndim = 0; | ||
| int64_t shape[8] = {0}; | ||
| int64_t strides[8] = {0}; | ||
| DType dtype = DType::fp4x2; | ||
| int device_id = 0; | ||
| }; | ||
|
|
||
| // CK blockscale a4w4 GEMM: Y = XQ @ WQ^T with per-1x32 microscaling. | ||
| // XQ [M, K/2] fp4x2 | ||
| // WQ [N, K/2] fp4x2 | ||
| // x_scale [M, K/32] e8m0 | ||
| // w_scale [N, K/32] e8m0 | ||
| // Y [M, N] bf16 / fp16 (output, pre-allocated) | ||
| // `kernel_name` empty -> default heuristic; non-empty must exist in the | ||
| // compiled registry. Returns hipSuccess on success, hipErrorUnknown on a | ||
| // kernel-side failure (message logged). | ||
| hipError_t gemm_a4w4_blockscale(const TensorDesc& XQ, | ||
| const TensorDesc& WQ, | ||
| const TensorDesc& x_scale, | ||
| const TensorDesc& w_scale, | ||
| const TensorDesc& Y, | ||
| int split_k, | ||
| const char* kernel_name, | ||
| hipStream_t stream); | ||
|
|
||
| // ASM (f4gemm) a4w4 GEMM: D = alpha*A*B + beta*C. | ||
| // A/B/scales/out layout as above; `bias` may be null. | ||
| // `kernel_name` empty -> ASM heuristic. | ||
| hipError_t gemm_a4w4_asm(const TensorDesc& A, | ||
| const TensorDesc& B, | ||
| const TensorDesc& a_scale, | ||
| const TensorDesc& b_scale, | ||
| const TensorDesc& out, | ||
| const TensorDesc* bias, | ||
| const char* kernel_name, | ||
| float alpha, | ||
| float beta, | ||
| int bpreshuffle, | ||
| int log2_k_split, | ||
| hipStream_t stream); | ||
|
|
||
| } // namespace aiter_gemm | ||
|
|
||
| #endif // AITER_GEMM_H |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| # Copyright (c) 2026, Advanced Micro Devices, Inc. All rights reserved. | ||
| # SPDX-License-Identifier: MIT | ||
| # | ||
| # QoLA consumer manifest for TE's AITER a4w4 (FP4) GEMM integration. | ||
| # Builds the torch-free CK-blockscale and ASM kernels as standalone | ||
| # te_libgemm_a4w4_*.so shared libraries (cpp_itfs mode). | ||
|
|
||
| [qola] | ||
| # NB: with NVTE_AITER_SOURCE_DIR set the build skips `qola checkout` and uses | ||
| # that tree directly; this pin documents the intended AITER commit for the | ||
| # reproducible (checkout) path. | ||
| aiter_commit = "773c8f67b9bfd99be95700a527d887afb4d8ba6a" | ||
| namespace = "te" | ||
| rocm_versions = ["7.2"] | ||
|
|
||
| [build] | ||
| architectures = ["gfx950"] | ||
|
|
||
| [[modules]] | ||
| name = "libgemm_a4w4_blockscale" | ||
| mode = "cpp_itfs" | ||
|
|
||
| [[modules]] | ||
| name = "libgemm_a4w4_asm" | ||
| mode = "cpp_itfs" |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The QoLA build runs via
execute_processat CMake configure time.CMAKE_CONFIGURE_DEPENDSonqola_manifest.toml(line 44) covers manifest edits, but a modified AITER source tree (e.g.NVTE_AITER_SOURCE_DIRpointing at a local checkout that the developer is iterating on) will not trigger a rebuild — only re-runningcmake ..will. Theaiter_gemmshared library also has noadd_dependencieslink back to the QoLA output, so.sos that get replaced under${__QOLA_BUILD_DIR}/libdo not cause relinking.For a first integration this is likely acceptable, but a follow-up switching to
ExternalProject_Add(or a custom target withDEPENDS/BYPRODUCTSon thete_libgemm_a4w4_*.sos) would make iterative development on gfx950 far less error-prone. Worth at least aTODOcomment.