Skip to content

Commit 73e1e77

Browse files
committed
optimize static dispatch
1 parent d0f6ae3 commit 73e1e77

2 files changed

Lines changed: 101 additions & 41 deletions

File tree

src/flag_blas/runtime/backend/_nvidia/hopper/ops/gemm.py

Lines changed: 97 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1800,6 +1800,96 @@ def _hgemm_tt_kernel3(
18001800
desc_c.store([offs_m, offs_n], result)
18011801

18021802

1803+
# ---------------------------------------------------------------------------
1804+
# Module-level condition predicates for hgemm StaticDispatch
1805+
# ---------------------------------------------------------------------------
1806+
def _hgemm_nn_is_skinny_aligned_large(m, n, k, aligned, **_kw):
1807+
return (
1808+
aligned
1809+
and (m * n > 2048 * 2048)
1810+
and min(m, n) >= 64
1811+
and (
1812+
(m >= 16384 and max(n, k) <= 2048)
1813+
or (n >= 16384 and max(m, k) <= 2048)
1814+
)
1815+
)
1816+
1817+
1818+
def _hgemm_nn_is_aligned_large(m, n, k, aligned, **_kw):
1819+
return aligned and (m * n > 2048 * 2048) and min(m, n) >= 64
1820+
1821+
1822+
def _hgemm_nn_is_aligned_small(m, n, k, aligned, **_kw):
1823+
return aligned and max(m, n) <= 1024
1824+
1825+
1826+
def _hgemm_nn_is_default(**_kw):
1827+
return True
1828+
1829+
1830+
# ---------------------------------------------------------------------------
1831+
# Module-level factory functions for hgemm StaticDispatch
1832+
# ---------------------------------------------------------------------------
1833+
def _hgemm_nn_build_kernel4(
1834+
A, B, C, m, n, k, lda, ldb, ldc, alpha, beta, beta_is_zero,
1835+
):
1836+
return lambda: _hgemm_nn_kernel4[(
1837+
triton.cdiv(m, 128) * triton.cdiv(n, 256),
1838+
)](
1839+
TensorDescriptor(base=A, shape=[m, k], strides=[lda, 1], block_shape=[128, 64]),
1840+
TensorDescriptor(base=B, shape=[k, n], strides=[ldb, 1], block_shape=[64, 256]),
1841+
TensorDescriptor(base=C, shape=[m, n], strides=[ldc, 1], block_shape=[128, 256]),
1842+
alpha, beta, m, n, k, beta_is_zero,
1843+
BLOCK_M=128, BLOCK_N=256, BLOCK_K=64, GROUP_M=8,
1844+
num_stages=4, num_warps=8, num_ctas=1,
1845+
)
1846+
1847+
1848+
def _hgemm_nn_build_kernel3(
1849+
A, B, C, m, n, k, lda, ldb, ldc, alpha, beta, beta_is_zero,
1850+
):
1851+
grid = lambda meta: (
1852+
triton.cdiv(m, meta["BLOCK_M"]) * triton.cdiv(n, meta["BLOCK_N"]),
1853+
)
1854+
return lambda: _hgemm_nn_kernel3[grid](
1855+
A, B, C, alpha, beta, m, n, k, lda, ldb, ldc, beta_is_zero,
1856+
)
1857+
1858+
1859+
def _hgemm_nn_build_kernel2(
1860+
A, B, C, m, n, k, lda, ldb, ldc, alpha, beta, beta_is_zero,
1861+
):
1862+
grid = lambda meta: (
1863+
triton.cdiv(m, meta["BLOCK_M"]) * triton.cdiv(n, meta["BLOCK_N"]),
1864+
)
1865+
return lambda: _hgemm_nn_kernel2[grid](
1866+
A, B, C, alpha, beta, m, n, k, lda, ldb, ldc, beta_is_zero,
1867+
)
1868+
1869+
1870+
def _hgemm_nn_build_kernel(
1871+
A, B, C, m, n, k, lda, ldb, ldc, alpha, beta, beta_is_zero,
1872+
):
1873+
grid = lambda meta: (
1874+
triton.cdiv(m, meta["BLOCK_M"]) * triton.cdiv(n, meta["BLOCK_N"]),
1875+
)
1876+
return lambda: _hgemm_nn_kernel[grid](
1877+
A, B, C, alpha, beta, m, n, k, lda, ldb, ldc, beta_is_zero,
1878+
)
1879+
1880+
1881+
_HGEMM_NN_DISPATCH = StaticDispatch([
1882+
# skinny + aligned large → kernel4 (TensorDescriptor, hardcoded config)
1883+
(_hgemm_nn_is_skinny_aligned_large, _hgemm_nn_build_kernel4),
1884+
# aligned large → kernel3 (TensorDescriptor, autotuned config)
1885+
(_hgemm_nn_is_aligned_large, _hgemm_nn_build_kernel3),
1886+
# aligned small → kernel2 (block_ptr)
1887+
(_hgemm_nn_is_aligned_small, _hgemm_nn_build_kernel2),
1888+
# default → kernel (original)
1889+
(_hgemm_nn_is_default, _hgemm_nn_build_kernel),
1890+
])
1891+
1892+
18031893
def hgemm(
18041894
transa: int,
18051895
transb: int,
@@ -1861,48 +1951,14 @@ def hgemm(
18611951
aligned = _is_gemm_aligned(A, lda, B, ldb, C, ldc)
18621952
with torch_device_fn.device(A.device):
18631953
if transa == CUBLAS_OP_N and transb == CUBLAS_OP_N:
1864-
dispatch = StaticDispatch([
1865-
# skinny + aligned large → kernel4 (TensorDescriptor, hardcoded config)
1866-
(
1867-
lambda m, n, k, aligned, **_kw:
1868-
aligned and (m * n > 2048 * 2048) and min(m, n) >= 64
1869-
and ((m >= 16384 and max(n, k) <= 2048) or (n >= 16384 and max(m, k) <= 2048)),
1870-
lambda: lambda: _hgemm_nn_kernel4[(
1871-
triton.cdiv(m, 128) * triton.cdiv(n, 256),
1872-
)](
1873-
TensorDescriptor(base=A, shape=[m, k], strides=[lda, 1], block_shape=[128, 64]),
1874-
TensorDescriptor(base=B, shape=[k, n], strides=[ldb, 1], block_shape=[64, 256]),
1875-
TensorDescriptor(base=C, shape=[m, n], strides=[ldc, 1], block_shape=[128, 256]),
1876-
alpha, beta, m, n, k, beta_is_zero,
1877-
BLOCK_M=128, BLOCK_N=256, BLOCK_K=64, GROUP_M=8,
1878-
num_stages=4, num_warps=8, num_ctas=1,
1879-
),
1880-
),
1881-
# aligned large → kernel3 (TensorDescriptor, autotuned config)
1882-
(
1883-
lambda m, n, k, aligned, **_kw:
1884-
aligned and (m * n > 2048 * 2048) and min(m, n) >= 64,
1885-
lambda: lambda: _hgemm_nn_kernel3[grid](
1886-
A, B, C, alpha, beta, m, n, k, lda, ldb, ldc, beta_is_zero,
1887-
),
1888-
),
1889-
# aligned small → kernel2 (block_ptr)
1890-
(
1891-
lambda m, n, k, aligned, **_kw:
1892-
aligned and max(m, n) <= 1024,
1893-
lambda: lambda: _hgemm_nn_kernel2[grid](
1894-
A, B, C, alpha, beta, m, n, k, lda, ldb, ldc, beta_is_zero,
1895-
),
1954+
runner = _HGEMM_NN_DISPATCH.lookup_and_build(
1955+
m, n, k, aligned,
1956+
context=dict(
1957+
A=A, B=B, C=C, m=m, n=n, k=k,
1958+
lda=lda, ldb=ldb, ldc=ldc,
1959+
alpha=alpha, beta=beta, beta_is_zero=beta_is_zero,
18961960
),
1897-
# default → kernel (original)
1898-
(
1899-
lambda **_kw: True,
1900-
lambda: lambda: _hgemm_nn_kernel[grid](
1901-
A, B, C, alpha, beta, m, n, k, lda, ldb, ldc, beta_is_zero,
1902-
),
1903-
),
1904-
])
1905-
runner = dispatch.lookup_and_build(m, n, k, aligned)
1961+
)
19061962
runner()
19071963
elif transa == CUBLAS_OP_T and transb == CUBLAS_OP_N:
19081964
is_skinny = (m >= 16384 and max(n, k) <= 2048) or (

src/flag_blas/runtime/dispatch.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,10 +367,14 @@ def lookup_and_build(
367367
n: int,
368368
k: int,
369369
aligned: bool,
370+
*,
371+
context: Optional[dict] = None,
370372
**extra,
371373
) -> Callable[[], None]:
372374
for condition, factory in self._table:
373375
if condition(m=m, n=n, k=k, aligned=aligned, **extra):
376+
if context is not None:
377+
return factory(**context)
374378
return factory()
375379
raise ValueError(
376380
f"StaticDispatch: no matching entry for "

0 commit comments

Comments
 (0)