1#ifndef __MATH_MFMA_KERNEL_H__
2#define __MATH_MFMA_KERNEL_H__
102#include <hip/hip_runtime.h>
129#if defined(__gfx90a__) || defined(__gfx942__)
198template < const
int LX >
200 if (
sizeof(
real) == 4) {
201 return (
LX >= 2) && (
LX <= 12);
203 return (
sizeof(
real) == 8) && (
LX >= 4) && (
LX <= 12);
276#define NEKO_MFMA_NWF_CANDIDATES 5
277#define NEKO_MFMA_TILE_CANDIDATES 2
278#define NEKO_MFMA_CANDIDATES \
279 (NEKO_MFMA_NWF_CANDIDATES * NEKO_MFMA_TILE_CANDIDATES)
280#define NEKO_MFMA_NWF(C) (1 << ((C) % NEKO_MFMA_NWF_CANDIDATES))
281#define NEKO_MFMA_TILE(C) ((C) / NEKO_MFMA_NWF_CANDIDATES)
282#define NEKO_MFMA_NTHRDS(C) dim3(64, NEKO_MFMA_NWF(C), 1)
339#define NEKO_MFMA_PAD_N(LX, SZ) (((LX) % 2 == 0) ? (NEKO_MFMA_PAD) : 0)
341#define NEKO_MFMA_PAD_N(LX, SZ) \
342 ((((LX) % 4 == 0) && !((LX) == 4 && (SZ) == 4)) ? 1 : 0)
345#define NEKO_MFMA_SJ_N(LX, SZ) ((LX) + NEKO_MFMA_PAD_N(LX, SZ))
346#define NEKO_MFMA_SK_N(LX, SZ) (NEKO_MFMA_SJ_N(LX, SZ) * (LX))
347#define NEKO_MFMA_CUBE_N(LX, SZ) (NEKO_MFMA_SK_N(LX, SZ) * (LX))
367#define NEKO_MFMA_SD_N(LX, SZ) NEKO_MFMA_SJ_N(LX, SZ)
368#define NEKO_MFMA_DMAT_N(LX, SZ) (NEKO_MFMA_SD_N(LX, SZ) * (LX))
383 if (
sizeof(
real) == 8) {
384#ifdef MFMA_F64_USE_16X16
390#ifdef MFMA_F32_USE_16X16
393 return sizeof(
real) == 4;
402 if (
sizeof(
real) == 8) {
403#ifdef MFMA_F64_USE_16X16
409#ifdef MFMA_F32_USE_16X16
448#define NEKO_MFMA_NGROUPS(LX) (((LX) * (LX) + 15) / 16)
456#define NEKO_MFMA_LDS_N(EB, LX, SZ) \
457 ((3 * NEKO_MFMA_DMAT_N(LX, SZ) + 4 * (EB) * NEKO_MFMA_CUBE_N(LX, SZ)) * (SZ))
458#define NEKO_MFMA_LDS_FITS(EB, LX, SZ) \
459 (NEKO_MFMA_LDS_N(EB, LX, SZ) <= NEKO_EB_MAX_LDS)
467#define NEKO_MFMA_EB_N(NWF, LX, SZ) \
468 ((NWF) / NEKO_MFMA_NGROUPS(LX) >= 16 && NEKO_MFMA_LDS_FITS(16, LX, SZ) ? 16 :\
469 (NWF) / NEKO_MFMA_NGROUPS(LX) >= 8 && NEKO_MFMA_LDS_FITS(8, LX, SZ) ? 8 : \
470 (NWF) / NEKO_MFMA_NGROUPS(LX) >= 4 && NEKO_MFMA_LDS_FITS(4, LX, SZ) ? 4 : \
471 (NWF) / NEKO_MFMA_NGROUPS(LX) >= 2 && NEKO_MFMA_LDS_FITS(2, LX, SZ) ? 2 : 1)
472#define NEKO_MFMA_EB(LX, C) \
473 NEKO_MFMA_EB_N(NEKO_MFMA_NWF(C), LX, sizeof(real))
475#define NEKO_MFMA_WPE(LX, C) (NEKO_MFMA_NWF(C) / NEKO_MFMA_EB(LX, C))
493#define NEKO_MFMA_POW2_FLOOR(X) \
494 ((X) >= 16 ? 16 : (X) >= 8 ? 8 : (X) >= 4 ? 4 : (X) >= 2 ? 2 : 1)
495#ifdef MFMA_F32_USE_16X16
496#define NEKO_MFMA_NEL_N(EB, LX, SZ, TILE) 1
498#define NEKO_MFMA_NEL_N(EB, LX, SZ, TILE) \
499 (((SZ) == 4 && (TILE) == 0) ? \
500 ((EB) < NEKO_MFMA_POW2_FLOOR(64 / ((LX) * (LX))) ? \
501 (EB) : NEKO_MFMA_POW2_FLOOR(64 / ((LX) * (LX)))) : 1)
503#define NEKO_MFMA_NEL(LX, C) \
504 NEKO_MFMA_NEL_N(NEKO_MFMA_EB(LX, C), LX, sizeof(real), NEKO_MFMA_TILE(C))
518#define NEKO_MFMA_SPT_N(WPE, LX, SZ) \
519 ((NEKO_MFMA_CUBE_N(LX, SZ) + (WPE) * 64 - 1) / ((WPE) * 64))
520#define NEKO_MFMA_SPT(LX, C) \
521 NEKO_MFMA_SPT_N(NEKO_MFMA_WPE(LX, C), LX, sizeof(real))
546#ifndef NEKO_MFMA_VECTOR_GREG_VGPRS
547#define NEKO_MFMA_VECTOR_GREG_VGPRS 64
549#define NEKO_MFMA_VECTOR_GREG_N(SPT, SZ) \
550 ((7 * (SPT) * ((SZ) / 4)) <= NEKO_MFMA_VECTOR_GREG_VGPRS)
551#define NEKO_MFMA_VECTOR_GREG(LX, C) \
552 NEKO_MFMA_VECTOR_GREG_N(NEKO_MFMA_SPT(LX, C), sizeof(real))
554#define NEKO_MFMA_NBLCKS(NELV, LX, C) \
555 dim3(((NELV) + NEKO_MFMA_EB(LX, C) - 1) / NEKO_MFMA_EB(LX, C), 1, 1)
572 const char *
v =
getenv(
"NEKO_MFMA_TUNE");
575 return (
atoi(
v) != 0);
594 const char *
v =
getenv(
"NEKO_MFMA_NWF");
595 const char *t =
getenv(
"NEKO_MFMA_TILE");
633#define NEKO_TUNE_LOG_MFMA(LX, T3) \
635 for (int c = 0; c < NEKO_MFMA_CANDIDATES; c++) { \
636 if ((T3)[c] >= NEKO_TUNE_INIT) { continue; } \
637 sprintf(neko_log_buf, "MFMA %s %2dwf %-2de x%-2d %-5s: %9.2f us/call", \
638 mfma_tile_name(c), NEKO_MFMA_NWF(c), NEKO_MFMA_EB(LX, c), \
639 (int) NEKO_MFMA_NEL(LX, c), \
640 NEKO_MFMA_PAD_N(LX, sizeof(real)) ? "pad" : "plain", \
641 NEKO_TUNE_US((T3)[c], iters)); \
642 log_message(neko_log_buf); \
655#define NEKO_TUNE_LOG_MFMA_VEC(LX, T3) \
657 for (int c = 0; c < NEKO_MFMA_CANDIDATES; c++) { \
658 if ((T3)[c] >= NEKO_TUNE_INIT) { continue; } \
659 sprintf(neko_log_buf, \
660 "MFMA %s %2dwf %-2de x%-2d %-5s %-4s: %9.2f us/call", \
661 mfma_tile_name(c), NEKO_MFMA_NWF(c), NEKO_MFMA_EB(LX, c), \
662 (int) NEKO_MFMA_NEL(LX, c), \
663 NEKO_MFMA_PAD_N(LX, sizeof(real)) ? "pad" : "plain", \
664 NEKO_MFMA_VECTOR_GREG(LX, c) ? "reg" : "glob", \
665 NEKO_TUNE_US((T3)[c], iters)); \
666 log_message(neko_log_buf); \
670#if defined(__gfx90a__) || defined(__gfx942__)
681template<
typename T >
716template< const
int LX, const
int PAD >
731template< const
int LX, const
int PAD >
733 return row + mfma_cube<LX, PAD>::SD *
col;
741template< const
int LX, const
int AXIS, const
int PAD = 0 >
744 const int a = n %
LX;
745 const int b = n /
LX;
746 if (
AXIS == 0)
return p + C::SJ *
a + C::SK * b;
747 if (
AXIS == 1)
return a + C::SJ * p + C::SK * b;
748 return a + C::SJ * b + C::SK * p;
769template< const
int LX, const
int PAD >
775 const int k = s / C::SK;
776 const int rem = s -
k * C::SK;
777 const int j =
rem / C::SJ;
778 const int i =
rem -
j * C::SJ;
799template<
typename T,
const int LX,
const int AXIS,
806 const int lane,
const int wf = 0) {
808 const int g =
lane >> 4;
809 const int c =
lane & 15;
820 const int l =
ks * 4 + g;
822 if (c <
LX && l <
LX)
828 for (
int p = 0; p <
NPASS; ++p) {
829 const int nt = wf + p *
NWF;
831 const int n = nt * 16 + c;
832 typename mma_t::acc_t
acc = {0, 0, 0, 0};
835 const int l =
ks * 4 + g;
837 if (l <
LX && n <
LX *
LX)
843 for (
int r = 0; r < 4; ++r) {
844 const int m = mma_t::out_row(g, r);
845 if (m <
LX && n <
LX *
LX) {
896template<
const int LX,
const int AXIS,
903 const int lane,
const int wf = 0) {
907 const int MT = (
LX + 3) / 4;
937 const int n =
ng * 16 +
gemm * 4 +
lo;
944 const int l =
ks * 4 +
kq;
946 if (l <
LX && n <
LX *
LX)
1026template<
const int LX,
const int AXIS,
1028 const int PAD = 0,
const int NEL = 1 >
1033 const int lane,
const int wf = 0) {
1037 const int MT = (
LX + 3) / 4;
1040 const int NG = (
NCOL + 63) / 64;
1051 for (
int l = 0; l <
LX; ++l) {
1074 for (
int l = 0; l <
LX; ++l) {
1086 for (
int r = 0; r < 4; ++r) {
1087 const int m_d =
mt * 4 + r;
1127template<
typename T,
const int LX,
const int AXIS,
1129 const int TILE = 0,
const int PAD = 0,
const int NEL = 1 >
1131 static_assert(
NEL == 1,
1132 "only the single precision 4x4x1 tile batches elements");
1145 const int NWF,
const int PAD,
const int NEL >
1147 static_assert(
NEL == 1,
1148 "only the single precision 4x4x1 tile batches elements");
1153#ifdef MFMA_F64_USE_16X16
1167 const int NWF,
const int PAD,
const int NEL >
1169 static_assert(
NEL == 1,
1170 "only the single precision 4x4x1 tile batches elements");
1184 const int NWF,
const int PAD,
const int NEL >
1190#ifdef MFMA_F32_USE_16X16
1191 static_assert(
NEL == 1,
1192 "NEKO_MFMA_NEL_N is 1 under MFMA_F32_USE_16X16");
__global__ void ale_add_kinematics_kernel(const int n, T *__restrict__ wx, T *__restrict__ wy, T *__restrict__ wz, const T *__restrict__ x_ref, const T *__restrict__ y_ref, const T *__restrict__ z_ref, const T *__restrict__ phi, const T *__restrict__ x, const T *__restrict__ y, const T *__restrict__ z, const kinematics_params_t kin_params)
__global__ void T *__restrict__ T *__restrict__ const T *__restrict__ const T *__restrict__ v
static __global__ void hip_mfma_arch_probe(int *flag)
static bool mfma_lx_supported()
static const char * mfma_tile_name(const int c)
#define NEKO_MFMA_NWF_CANDIDATES
#define NEKO_MFMA_CANDIDATES
static int neko_mfma_pin()
static int neko_mfma_candidates()
#define NEKO_MFMA_TILE_CANDIDATES
static bool hip_have_mfma()
#define NEKO_MFMA_TILE(C)
static int neko_mfma_sweep()
static bool mfma_tile_offered(const int c)