Skip to content

blockwise fp8 gemm integration for gfx942 and gfx950#658

Open
asdfvg123 wants to merge 47 commits into
devfrom
yeonsoo/blockwise_fp8_gemm_hipkittens_optim
Open

blockwise fp8 gemm integration for gfx942 and gfx950#658
asdfvg123 wants to merge 47 commits into
devfrom
yeonsoo/blockwise_fp8_gemm_hipkittens_optim

Conversation

@asdfvg123

Copy link
Copy Markdown
Contributor

Description

Integrating blockwise FP8 gemm for gfx942 and gfx950 using hipkittens. Using 2 submodules for now. The hipkittens submodule uses separate branch for CDNA3 and CDNA4.

Fixes # (issue)

Type of change

  • Documentation change (change only to the documentation, either a fix or a new content)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Infra/Build change
  • Code refactoring

Changes

Please list the changes introduced in this PR:

  • Change A
    separate the kernel for gfx942 and gfx950. The host selects the kernel in runtime.
    The kernel supports 1d2d, 1d1d GEMM with output bf16, fp32, fp16 / input fp8e5m2, fp8e4m3 / and different epilogues.

Checklist:

  • I have read and followed the contributing guidelines
  • The functionality is complete
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

asdfvg123 added 27 commits June 3, 2026 17:15
…dant HIP guards, revert unnecessary common.h change
# Conflicts:
#	tests/cpp/operator/CMakeLists.txt
…hipkittens_optim

# Conflicts:
#	transformer_engine/common/CMakeLists.txt
#	transformer_engine/common/gemm/kittens/CMakeLists.txt
#	transformer_engine/common/gemm/rocm_gemm.cu
#	transformer_engine/pytorch/quantization.py
@asdfvg123
asdfvg123 requested a review from alextmagro July 6, 2026 22:01
…gemm_hipkittens_optim

# Conflicts:
#	transformer_engine/common/gemm/kittens/cdna4/mxfp8_gemm.cpp
#	transformer_engine/pytorch/quantization.py
@asdfvg123 asdfvg123 added the ci-level 1 CI test level 1 label Jul 7, 2026
@asdfvg123
asdfvg123 requested a review from matthiasdiener July 9, 2026 14:12
@asdfvg123
asdfvg123 marked this pull request as ready for review July 9, 2026 14:12
@asdfvg123

Copy link
Copy Markdown
Contributor Author
  1. check_fp8_block_scaling_quantization_support
    These were temporary APIs introduced in PR enable blockwise FP8 quantization on rocm #609 to enable blockwise FP8 quantization only. Now that GEMM is also supported, they are folded into is_fp8_block_scaling_available and removed. This is an intentional public symbol removal with no known downstream users.

  2. constants.py FP8 dtype lookup fix
    Custom_DType_Dict.__missing__ now compares the enum key with == instead of is. This is a bug fix on the rocm side. tex.DType values returned from the C++ bindings (i.e. tensor._fp8_dtype) are fresh pybind11 instances that compare equal to but are not identical to the module-level singletons, so the identity check could cache the e4m3 key as e5m2. The dict is a process-global singleton, so this was a latent bug that surfaced when a C++-Enum lookup was the first e4m3 lookup in the process (seen in test_float8block_linear_fused_adam_master_weights). The Custom_DType_Dict class is created in this fork (upstream does not have the class), so no upstream compatibility concern.

@ipanfilo

Copy link
Copy Markdown
Collaborator

Is CDNA3 support expected to be ported to HK?

@alextmagro

Copy link
Copy Markdown
Contributor

Is CDNA3 support expected to be ported to HK?

Currently HK supports CDNA3, CDNA4, and UDNA1. There is currently effort with the external HK team to move away from having separate git branches for each arch to having directory level separation.

@ipanfilo

Copy link
Copy Markdown
Collaborator

Is CDNA3 support expected to be ported to HK?

Currently HK supports CDNA3, CDNA4, and UDNA1. There is currently effort with the external HK team to move away from having separate git branches for each arch to having directory level separation.

In this case can we avoid having 2 copies of HK submodule?

@alextmagro

Copy link
Copy Markdown
Contributor

Is CDNA3 support expected to be ported to HK?

Currently HK supports CDNA3, CDNA4, and UDNA1. There is currently effort with the external HK team to move away from having separate git branches for each arch to having directory level separation.

In this case can we avoid having 2 copies of HK submodule?

Yes, looks like they merged it in late last week. I think that will require some integration/cmake changes so that the right headers are imported for each kernel. We'll probably want to move our kittens kernels into cdna3/cdna4/udna1 folders as well, so might be better as a follow up ticket?

emulated = get_device_compute_capability() >= (10, 0)
return supported and not emulated

def rocm_blockwise_unsupported_reason(

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.

Here generally I think we should return a tuple -- True/False, followed by an optional reason. Maybe rename to rocm_blockwise_is_supported too.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed

):
if not fp8_blockwise_gemm_supported():
pytest.skip("CUDA version does not support blockwise FP8 gemm.")
if IS_HIP_EXTENSION:

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.

We could also potentially use the rocm function above here too?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yes, now we are using the function

is_w_1d_scaled,
) -> None:
# NOTE: BGRAD epilogue is not supported for fp8.
if IS_HIP_EXTENSION:

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.

One of the great things about hipKittens is how easy it is to fuse epilogues into kernels. If you have time it might be worth looking into bgrad/accumulator support.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I will leave this as a future support. The current implementation supports the minimal cases that the test is expecting

) -> None:
# e5m2 by e5m2 not supported.
if IS_HIP_EXTENSION:
expected_err_msg = "does not support e5m2 by e5m2 inputs"

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.

e5m2 should be supported by hipkittens, have a look at the mxfp8 kernels to see how we template for that

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Same here. The test expects e4m3 x e4m3 / e4m3 x e5m2 / e5m2 x e4m3 but not e5m2 x e5m2 and the current implementation also supports the former 3 but not the e5m2 x e5m2. While this is an easy support, I will leave it as a future PR

use_split_accumulator,
is_x_1d_scaled,
is_w_1d_scaled,
expected_err_msg="dimension requirement",

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 change should be hip guarded

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed. To keep the upstream lines untouched, I guarded early-return block, which makes the code a bit longer. Let me know if you have a cleaner approach.


#ifndef KITTENS_DTYPE_ENUM_DEFINED
#define KITTENS_DTYPE_ENUM_DEFINED
enum KittensDType {

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'd rather not have to redefine these. I think we can have a parent folder header file that contains these enums and any other shared values.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed. Added kittens_gemm_enums.h

#endif // KITTENS_SCALING_MODE_DEFINED

namespace blockwise_gfx942 {
void kittens_blockwise_fp8_gemm_impl_cdna3(

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.

Rather than a namespace for gfx942 and gfx950, etc, I think we would be better off with a purely virtual class at the parent folder level, with child class definitions for functions within each architectural folder. That way we can track more easily what is available and what is not for each architecture.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed

@@ -0,0 +1,1459 @@
/*************************************************************************

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.

Most of my comments regarding the cdna3 kernel applies here as well -- otherwise the kernel looks good.

option(NVTE_KITTENS_USE_POWER_OF_2_SCALE
"Use HW E8M0 MFMA scaling for power-of-2 blockwise FP8 scales (gfx950)" ON)

function(try_enable_hipkittens_gemm)

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.

Not sure this needs to bea function if we are only calling it once?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed

return;
}
}
#endif

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 hipkittens is not being used, we should add an nvte_error here for blockwise usage

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixed

@asdfvg123
asdfvg123 requested a review from alextmagro July 22, 2026 02:19
emulated = get_device_compute_capability() >= (10, 0)
return supported and not emulated

def rocm_blockwise_is_supported(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Guard our rocm-specific functions via IS_HIP_EXTENSION

):
if x_dtype == torch.float8_e5m2 and w_dtype == torch.float8_e5m2:
if IS_HIP_EXTENSION:
atol = rtol = 8e-3

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is NV upstream using a different atol/rtol? If so, why

Comment on lines +40 to +43
is_1d2d = is_x_1d_scaled and not is_w_1d_scaled
is_1d1d = is_x_1d_scaled and is_w_1d_scaled
if not (is_1d2d or is_1d1d):
return False, "Only 1D by 1D and 1D by 2D block scaling GEMM is supported"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Actually, let's have a subsection in readme to state our support matrix as well, and how it is different from NV side?

is_w_1d_scaled,
) -> None:
if IS_HIP_EXTENSION:
expected_err_msg = "requires split accumulator"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

use_split_accumulator in line 703 is set to false

Comment on lines +50 to +55
__device__ inline float rtne_bias(float v) {
uint32_t bits = __builtin_bit_cast(uint32_t, v);
if ((bits & 0x7f800000u) == 0x7f800000u) return v;
bits += 0x7fffu + ((bits >> 16) & 1u);
return __builtin_bit_cast(float, bits);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I recall we have hardware rtne casting instructions in gfx950?

handle = hipblaslt_handles[compute_stream_offset];
}

#ifdef USE_HIPKITTENS_GEMM

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Emm, any reason that we don't want to build and use hipkitten fp8 blockwise gemm?

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

Labels

ci-level 1 CI test level 1

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants