|
|
|
@@ -350,20 +350,24 @@ static __host__ int ggml_cuda_fattn_mma_get_nstages(const int DKQ, const int DV,
|
|
|
|
|
return cp_async_available(cc) && ncols2 >= 2 ? ggml_cuda_fattn_mma_get_nstages_target(DKQ, DV, ncols1*ncols2, cc) : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static constexpr __device__ int ggml_cuda_fattn_mma_get_nstages(const int DKQ, const int DV, const int ncols1, const int ncols2) {
|
|
|
|
|
static constexpr __device__ int ggml_cuda_fattn_mma_get_nstages(
|
|
|
|
|
const int DKQ, const int DV, const int ncols1, const int ncols2, const bool use_sparse) {
|
|
|
|
|
#ifdef CP_ASYNC_AVAILABLE
|
|
|
|
|
return ncols2 >= 2 ? ggml_cuda_fattn_mma_get_nstages_target(DKQ, DV, ncols1*ncols2) : 0;
|
|
|
|
|
const int nstages_target = ncols2 >= 2 ? ggml_cuda_fattn_mma_get_nstages_target(DKQ, DV, ncols1*ncols2) : 0;
|
|
|
|
|
// sparse gather is not implemented for multi-stage loading
|
|
|
|
|
return use_sparse && nstages_target > 1 ? 1 : nstages_target;
|
|
|
|
|
#else
|
|
|
|
|
GGML_UNUSED_VARS(DKQ, DV, ncols1, ncols2);
|
|
|
|
|
GGML_UNUSED_VARS(DKQ, DV, ncols1, ncols2, use_sparse);
|
|
|
|
|
return 0;
|
|
|
|
|
#endif // CP_ASYNC_AVAILABLE
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
template<int stride_tile, bool swz, int nwarps, int nbatch_fa, bool use_cp_async, bool oob_check>
|
|
|
|
|
template<int stride_tile, bool swz, int nwarps, int nbatch_fa, bool use_cp_async, bool oob_check, bool use_sparse>
|
|
|
|
|
static __device__ __forceinline__ void flash_attn_ext_f16_load_tile(
|
|
|
|
|
const half2 * const __restrict__ KV, half2 * const __restrict__ tile_KV, const int D2, const int stride_KV, const int i_sup) {
|
|
|
|
|
const half2 * const __restrict__ KV, half2 * const __restrict__ tile_KV, const int D2, const int stride_KV,
|
|
|
|
|
const int k_VKQ_0, const int i_sup, const int32_t * const __restrict__ indices) {
|
|
|
|
|
constexpr int warp_size = ggml_cuda_get_physical_warp_size();
|
|
|
|
|
// K/V data is loaded with decreasing granularity for D for better memory bandwidth.
|
|
|
|
|
// The minimum granularity is 16 bytes.
|
|
|
|
@@ -371,7 +375,7 @@ static __device__ __forceinline__ void flash_attn_ext_f16_load_tile(
|
|
|
|
|
const int chunks_per_row = D2 / h2_per_chunk;
|
|
|
|
|
if constexpr (use_cp_async) {
|
|
|
|
|
static_assert(warp_size == 32, "bad warp_size");
|
|
|
|
|
static_assert(!oob_check, "OOB check not compatible with cp_async");
|
|
|
|
|
static_assert(!oob_check || use_sparse, "OOB check not compatible with cp_async");
|
|
|
|
|
constexpr int preload = 64;
|
|
|
|
|
|
|
|
|
|
const unsigned int tile_KV_32 = ggml_cuda_cvta_generic_to_shared(tile_KV);
|
|
|
|
@@ -394,15 +398,24 @@ static __device__ __forceinline__ void flash_attn_ext_f16_load_tile(
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64_t i_KV;
|
|
|
|
|
if constexpr (use_sparse) {
|
|
|
|
|
// padded slots gather row 0, the -inf mask removes their contribution
|
|
|
|
|
const int32_t index = i < i_sup ? indices[k_VKQ_0 + i] : 0;
|
|
|
|
|
i_KV = index >= 0 ? index : 0;
|
|
|
|
|
} else {
|
|
|
|
|
i_KV = k_VKQ_0 + i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#pragma unroll
|
|
|
|
|
for (int k0 = k0_start; k0 < k0_stop; k0 += stride_k) {
|
|
|
|
|
const int k = k0 + (stride_k == warp_size ? threadIdx.x : threadIdx.x % stride_k);
|
|
|
|
|
|
|
|
|
|
if constexpr (swz) {
|
|
|
|
|
const int smem_offs_b = ggml_cuda_fattn_smem_swizzle::bytes_rc<stride_tile>(i, k*h2_per_chunk);
|
|
|
|
|
cp_async_cg_16<preload>(tile_KV_32 + smem_offs_b, KV + i*stride_KV + k*h2_per_chunk);
|
|
|
|
|
cp_async_cg_16<preload>(tile_KV_32 + smem_offs_b, KV + i_KV*stride_KV + k*h2_per_chunk);
|
|
|
|
|
} else {
|
|
|
|
|
cp_async_cg_16<preload>(tile_KV_32 + i*(stride_tile*sizeof(half2)) + k*16, KV + i*stride_KV + k*h2_per_chunk);
|
|
|
|
|
cp_async_cg_16<preload>(tile_KV_32 + i*(stride_tile*sizeof(half2)) + k*16, KV + i_KV*stride_KV + k*h2_per_chunk);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -438,12 +451,17 @@ static __device__ __forceinline__ void flash_attn_ext_f16_load_tile(
|
|
|
|
|
for (int k0 = k0_start; k0 < k0_stop; k0 += stride_k) {
|
|
|
|
|
const int k = k0 + (stride_k == warp_size ? threadIdx.x : threadIdx.x % stride_k);
|
|
|
|
|
|
|
|
|
|
if constexpr (swz) {
|
|
|
|
|
ggml_cuda_memcpy_1<16>((char *) tile_KV + ggml_cuda_fattn_smem_swizzle::bytes_rc<stride_tile>(i, k*h2_per_chunk),
|
|
|
|
|
!oob_check || i < i_sup ? KV + i*stride_KV + k*h2_per_chunk : zero);
|
|
|
|
|
const half2 * src;
|
|
|
|
|
if constexpr (use_sparse) {
|
|
|
|
|
const int32_t index = i < i_sup ? indices[k_VKQ_0 + i] : -1;
|
|
|
|
|
src = index >= 0 ? KV + int64_t(index)*stride_KV + k*h2_per_chunk : zero;
|
|
|
|
|
} else {
|
|
|
|
|
ggml_cuda_memcpy_1<16>(tile_KV + i*stride_tile + k*4,
|
|
|
|
|
!oob_check || i < i_sup ? KV + i*stride_KV + k*h2_per_chunk : zero);
|
|
|
|
|
src = !oob_check || i < i_sup ? KV + int64_t(k_VKQ_0 + i)*stride_KV + k*h2_per_chunk : zero;
|
|
|
|
|
}
|
|
|
|
|
if constexpr (swz) {
|
|
|
|
|
ggml_cuda_memcpy_1<16>((char *) tile_KV + ggml_cuda_fattn_smem_swizzle::bytes_rc<stride_tile>(i, k*h2_per_chunk), src);
|
|
|
|
|
} else {
|
|
|
|
|
ggml_cuda_memcpy_1<16>(tile_KV + i*stride_tile + k*4, src);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -458,14 +476,16 @@ static __device__ __forceinline__ void flash_attn_ext_f16_load_tile(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<int ncols1, int nwarps, int nbatch_fa, bool use_cp_async, bool oob_check>
|
|
|
|
|
template<int ncols1, int nwarps, int nbatch_fa, bool use_cp_async, bool oob_check, bool use_sparse>
|
|
|
|
|
static __device__ __forceinline__ void flash_attn_ext_f16_load_mask(
|
|
|
|
|
const half * const __restrict__ mask_h, half * const __restrict__ tile_mask,
|
|
|
|
|
const int stride_mask, const int i_sup, const int j0, const uint3 ne01) {
|
|
|
|
|
const int stride_mask, const int k_VKQ_0, const int i_sup, const int j0, const uint3 ne01,
|
|
|
|
|
const int32_t * const __restrict__ indices) {
|
|
|
|
|
constexpr int warp_size = ggml_cuda_get_physical_warp_size();
|
|
|
|
|
if constexpr (use_cp_async) {
|
|
|
|
|
static_assert(nbatch_fa <= 8*warp_size && nbatch_fa % 8 == 0, "bad nbatch_fa");
|
|
|
|
|
static_assert(!oob_check, "OOB check incompatible with cp_async");
|
|
|
|
|
static_assert(!use_sparse, "sparse gather incompatible with cp_async");
|
|
|
|
|
constexpr int preload = nbatch_fa >= 32 ? nbatch_fa * sizeof(half) : 64;
|
|
|
|
|
constexpr int cols_per_warp = 8*warp_size/nbatch_fa;
|
|
|
|
|
constexpr int stride_j = nwarps * cols_per_warp;
|
|
|
|
@@ -483,9 +503,9 @@ static __device__ __forceinline__ void flash_attn_ext_f16_load_mask(
|
|
|
|
|
|
|
|
|
|
const int i = 8 * (threadIdx.x % (nbatch_fa/8));
|
|
|
|
|
|
|
|
|
|
cp_async_cg_16<preload>(tile_mask_32 + j_sram*(nbatch_fa*sizeof(half) + 16) + i*sizeof(half), mask_h + int64_t(j_vram)*stride_mask + i);
|
|
|
|
|
cp_async_cg_16<preload>(tile_mask_32 + j_sram*(nbatch_fa*sizeof(half) + 16) + i*sizeof(half), mask_h + int64_t(j_vram)*stride_mask + k_VKQ_0 + i);
|
|
|
|
|
}
|
|
|
|
|
} else if constexpr (oob_check) {
|
|
|
|
|
} else if constexpr (oob_check || use_sparse) {
|
|
|
|
|
#pragma unroll
|
|
|
|
|
for (int j1 = 0; j1 < ncols1; j1 += nwarps) {
|
|
|
|
|
const int j_sram = j1 + threadIdx.y;
|
|
|
|
@@ -499,7 +519,12 @@ static __device__ __forceinline__ void flash_attn_ext_f16_load_mask(
|
|
|
|
|
for (int i0 = 0; i0 < nbatch_fa; i0 += warp_size) {
|
|
|
|
|
const int i = i0 + threadIdx.x;
|
|
|
|
|
|
|
|
|
|
tile_mask[j_sram*(nbatch_fa + 8) + i] = i < i_sup ? mask_h[int64_t(j_vram)*stride_mask + i] : half(0.0f);
|
|
|
|
|
if constexpr (use_sparse) {
|
|
|
|
|
const int32_t index = i < i_sup ? indices[k_VKQ_0 + i] : -1;
|
|
|
|
|
tile_mask[j_sram*(nbatch_fa + 8) + i] = index >= 0 ? mask_h[int64_t(j_vram)*stride_mask + index] : half(-INFINITY);
|
|
|
|
|
} else {
|
|
|
|
|
tile_mask[j_sram*(nbatch_fa + 8) + i] = i < i_sup ? mask_h[int64_t(j_vram)*stride_mask + k_VKQ_0 + i] : half(0.0f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if constexpr (nbatch_fa < 2*warp_size) {
|
|
|
|
@@ -516,7 +541,7 @@ static __device__ __forceinline__ void flash_attn_ext_f16_load_mask(
|
|
|
|
|
|
|
|
|
|
const int i = threadIdx.x % (warp_size/cols_per_warp);
|
|
|
|
|
|
|
|
|
|
ggml_cuda_memcpy_1<sizeof(half2)>(tile_mask + j_sram*(nbatch_fa + 8) + 2*i, mask_h + int64_t(j_vram)*stride_mask + 2*i);
|
|
|
|
|
ggml_cuda_memcpy_1<sizeof(half2)>(tile_mask + j_sram*(nbatch_fa + 8) + 2*i, mask_h + int64_t(j_vram)*stride_mask + k_VKQ_0 + 2*i);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
#pragma unroll
|
|
|
|
@@ -532,20 +557,21 @@ static __device__ __forceinline__ void flash_attn_ext_f16_load_mask(
|
|
|
|
|
for (int i0 = 0; i0 < nbatch_fa; i0 += 2*warp_size) {
|
|
|
|
|
const int i = i0 + 2*threadIdx.x;
|
|
|
|
|
|
|
|
|
|
ggml_cuda_memcpy_1<sizeof(half2)>(tile_mask + j_sram*(nbatch_fa + 8) + i, mask_h + int64_t(j_vram)*stride_mask + i);
|
|
|
|
|
ggml_cuda_memcpy_1<sizeof(half2)>(tile_mask + j_sram*(nbatch_fa + 8) + i, mask_h + int64_t(j_vram)*stride_mask + k_VKQ_0 + i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<int DKQ, int DV, int ncols1, int ncols2, int nwarps,
|
|
|
|
|
bool use_logit_softcap, bool V_is_K_view, bool needs_fixup, bool is_fixup, bool last_iter, bool oob_check,
|
|
|
|
|
bool use_logit_softcap, bool V_is_K_view, bool use_sparse, bool needs_fixup, bool is_fixup, bool last_iter, bool oob_check,
|
|
|
|
|
typename T_A_KQ, typename T_B_KQ, typename T_C_KQ, typename T_A_VKQ, typename T_B_VKQ, typename T_C_VKQ>
|
|
|
|
|
static __device__ __forceinline__ void flash_attn_ext_f16_iter(
|
|
|
|
|
const float2 * const __restrict__ Q_f2,
|
|
|
|
|
const half2 * const __restrict__ K_h2,
|
|
|
|
|
const half2 * const __restrict__ V_h2,
|
|
|
|
|
const half * const __restrict__ mask_h,
|
|
|
|
|
const int32_t * const __restrict__ indices,
|
|
|
|
|
float2 * const __restrict__ dstk,
|
|
|
|
|
float2 * const __restrict__ dstk_fixup,
|
|
|
|
|
const float scale,
|
|
|
|
@@ -577,7 +603,7 @@ static __device__ __forceinline__ void flash_attn_ext_f16_iter(
|
|
|
|
|
constexpr int nbatch_K2 = ggml_cuda_fattn_mma_get_nbatch_K2(DKQ, DV, ncols);
|
|
|
|
|
constexpr int nbatch_V2 = ggml_cuda_fattn_mma_get_nbatch_V2(DKQ, DV, ncols);
|
|
|
|
|
constexpr bool Q_in_reg = ggml_cuda_fattn_mma_get_Q_in_reg (DKQ, DV, ncols);
|
|
|
|
|
constexpr int nstages = ggml_cuda_fattn_mma_get_nstages (DKQ, DV, ncols1, ncols2);
|
|
|
|
|
constexpr int nstages = ggml_cuda_fattn_mma_get_nstages (DKQ, DV, ncols1, ncols2, use_sparse);
|
|
|
|
|
|
|
|
|
|
// swizzle the tile stride for K and V based on the batch size.
|
|
|
|
|
constexpr int stride_tile_K = ggml_cuda_fattn_smem_swizzle::tile_stride(nbatch_K2);
|
|
|
|
@@ -601,13 +627,14 @@ static __device__ __forceinline__ void flash_attn_ext_f16_iter(
|
|
|
|
|
constexpr bool use_cp_async = true;
|
|
|
|
|
cp_async_wait_all();
|
|
|
|
|
__syncthreads();
|
|
|
|
|
flash_attn_ext_f16_load_tile<stride_tile_V, swz_V, nwarps, nbatch_fa, use_cp_async, oob_check>
|
|
|
|
|
(V_h2 + int64_t(k_VKQ_0)*stride_V, tile_V, nbatch_V2, stride_V, k_VKQ_sup);
|
|
|
|
|
flash_attn_ext_f16_load_tile<stride_tile_V, swz_V, nwarps, nbatch_fa, use_cp_async, oob_check, use_sparse>
|
|
|
|
|
(V_h2, tile_V, nbatch_V2, stride_V, k_VKQ_0, k_VKQ_sup, nullptr);
|
|
|
|
|
} else {
|
|
|
|
|
constexpr bool use_cp_async = nstages == 1;
|
|
|
|
|
// the sparse mask values are gathered per element, always load them synchronously
|
|
|
|
|
constexpr bool use_cp_async = nstages == 1 && !use_sparse;
|
|
|
|
|
if (ncols2 > 1 || mask_h) {
|
|
|
|
|
flash_attn_ext_f16_load_mask<ncols1, nwarps, nbatch_fa, use_cp_async, oob_check>
|
|
|
|
|
(mask_h + k_VKQ_0, tile_mask, stride_mask, k_VKQ_sup, jt*ncols1, ne01);
|
|
|
|
|
flash_attn_ext_f16_load_mask<ncols1, nwarps, nbatch_fa, use_cp_async, oob_check, use_sparse>
|
|
|
|
|
(mask_h, tile_mask, stride_mask, k_VKQ_0, k_VKQ_sup, jt*ncols1, ne01, indices);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -620,8 +647,8 @@ static __device__ __forceinline__ void flash_attn_ext_f16_iter(
|
|
|
|
|
if constexpr (nstages <= 1) {
|
|
|
|
|
const int k0_diff = k0_stop - k0_start;
|
|
|
|
|
constexpr bool use_cp_async = nstages == 1;
|
|
|
|
|
flash_attn_ext_f16_load_tile<stride_tile_K, swz_K, nwarps, nbatch_fa, use_cp_async, oob_check>
|
|
|
|
|
(K_h2 + int64_t(k_VKQ_0)*stride_K + k0_start, tile_K, k0_diff, stride_K, k_VKQ_sup);
|
|
|
|
|
flash_attn_ext_f16_load_tile<stride_tile_K, swz_K, nwarps, nbatch_fa, use_cp_async, oob_check, use_sparse>
|
|
|
|
|
(K_h2 + k0_start, tile_K, k0_diff, stride_K, k_VKQ_0, k_VKQ_sup, indices);
|
|
|
|
|
if (use_cp_async) {
|
|
|
|
|
cp_async_wait_all();
|
|
|
|
|
}
|
|
|
|
@@ -946,6 +973,7 @@ static __device__ __forceinline__ void flash_attn_ext_f16_iter(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if constexpr (nstages > 1) {
|
|
|
|
|
static_assert(!use_sparse, "sparse gather not implemented for multi-stage loading");
|
|
|
|
|
static_assert(!V_is_K_view, "K data reuse not implemented multi-stage loading");
|
|
|
|
|
// Preload K tile for next iteration:
|
|
|
|
|
constexpr bool use_cp_async = true;
|
|
|
|
@@ -953,11 +981,11 @@ static __device__ __forceinline__ void flash_attn_ext_f16_iter(
|
|
|
|
|
__syncthreads();
|
|
|
|
|
if (!last_iter) {
|
|
|
|
|
if (ncols2 > 1 || mask_h) {
|
|
|
|
|
flash_attn_ext_f16_load_mask<ncols1, nwarps, nbatch_fa, use_cp_async, oob_check>
|
|
|
|
|
(mask_h + k_VKQ_0 + nbatch_fa, tile_mask, stride_mask, k_VKQ_sup, jt*ncols1, ne01);
|
|
|
|
|
flash_attn_ext_f16_load_mask<ncols1, nwarps, nbatch_fa, use_cp_async, oob_check, use_sparse>
|
|
|
|
|
(mask_h, tile_mask, stride_mask, k_VKQ_0 + nbatch_fa, k_VKQ_sup, jt*ncols1, ne01, nullptr);
|
|
|
|
|
}
|
|
|
|
|
flash_attn_ext_f16_load_tile<stride_tile_K, swz_K, nwarps, nbatch_fa, use_cp_async, oob_check>
|
|
|
|
|
(K_h2 + int64_t(k_VKQ_0 + nbatch_fa)*stride_K, tile_K, nbatch_K2, stride_K, k_VKQ_sup);
|
|
|
|
|
flash_attn_ext_f16_load_tile<stride_tile_K, swz_K, nwarps, nbatch_fa, use_cp_async, oob_check, use_sparse>
|
|
|
|
|
(K_h2, tile_K, nbatch_K2, stride_K, k_VKQ_0 + nbatch_fa, k_VKQ_sup, nullptr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -972,8 +1000,8 @@ static __device__ __forceinline__ void flash_attn_ext_f16_iter(
|
|
|
|
|
const int i0_diff = i0_stop - i0_start;
|
|
|
|
|
if (!V_is_K_view || i0_stop > 2*nbatch_K2) {
|
|
|
|
|
constexpr bool use_cp_async = nstages == 1;
|
|
|
|
|
flash_attn_ext_f16_load_tile<stride_tile_V, swz_V, nwarps, nbatch_fa, use_cp_async, oob_check>
|
|
|
|
|
(V_h2 + int64_t(k_VKQ_0)*stride_V + i0_start/2, tile_V, i0_diff/2, stride_V, k_VKQ_sup);
|
|
|
|
|
flash_attn_ext_f16_load_tile<stride_tile_V, swz_V, nwarps, nbatch_fa, use_cp_async, oob_check, use_sparse>
|
|
|
|
|
(V_h2 + i0_start/2, tile_V, i0_diff/2, stride_V, k_VKQ_0, k_VKQ_sup, indices);
|
|
|
|
|
if (use_cp_async) {
|
|
|
|
|
cp_async_wait_all();
|
|
|
|
|
}
|
|
|
|
@@ -1028,7 +1056,7 @@ static __device__ __forceinline__ void flash_attn_ext_f16_iter(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
GGML_UNUSED_VARS(Q_f2, K_h2, V_h2, mask_h, dstk, dstk_fixup,
|
|
|
|
|
GGML_UNUSED_VARS(Q_f2, K_h2, V_h2, mask_h, indices, dstk, dstk_fixup,
|
|
|
|
|
scale, slope, logit_softcap, ne01, ne02,
|
|
|
|
|
stride_K, stride_V, stride_mask,
|
|
|
|
|
tile_Q, tile_K, tile_V, tile_mask,
|
|
|
|
@@ -1126,12 +1154,13 @@ template<int DV, int ncols> struct mma_tile_sizes {
|
|
|
|
|
};
|
|
|
|
|
#endif // defined(TURING_MMA_AVAILABLE)
|
|
|
|
|
|
|
|
|
|
template<int DKQ, int DV, int ncols1, int ncols2, int nwarps, bool use_logit_softcap, bool V_is_K_view, bool needs_fixup, bool is_fixup>
|
|
|
|
|
template<int DKQ, int DV, int ncols1, int ncols2, int nwarps, bool use_logit_softcap, bool V_is_K_view, bool use_sparse, bool needs_fixup, bool is_fixup>
|
|
|
|
|
static __device__ __forceinline__ void flash_attn_ext_f16_process_tile(
|
|
|
|
|
const float2 * const __restrict__ Q_f2,
|
|
|
|
|
const half2 * const __restrict__ K_h2,
|
|
|
|
|
const half2 * const __restrict__ V_h2,
|
|
|
|
|
const half * const __restrict__ mask_h,
|
|
|
|
|
const int32_t * const __restrict__ indices,
|
|
|
|
|
const float * const __restrict__ sinks_f,
|
|
|
|
|
float2 * const __restrict__ dstk,
|
|
|
|
|
float2 * const __restrict__ dstk_fixup,
|
|
|
|
@@ -1171,7 +1200,7 @@ static __device__ __forceinline__ void flash_attn_ext_f16_process_tile(
|
|
|
|
|
constexpr int nbatch_V2 = ggml_cuda_fattn_mma_get_nbatch_V2 (DKQ, DV, ncols);
|
|
|
|
|
constexpr int nbatch_combine = ggml_cuda_fattn_mma_get_nbatch_combine(DKQ, DV, ncols);
|
|
|
|
|
constexpr bool Q_in_reg = ggml_cuda_fattn_mma_get_Q_in_reg (DKQ, DV, ncols);
|
|
|
|
|
constexpr int nstages = ggml_cuda_fattn_mma_get_nstages (DKQ, DV, ncols1, ncols2);
|
|
|
|
|
constexpr int nstages = ggml_cuda_fattn_mma_get_nstages (DKQ, DV, ncols1, ncols2, use_sparse);
|
|
|
|
|
|
|
|
|
|
if (cols_per_warp > ncols) {
|
|
|
|
|
NO_DEVICE_CODE;
|
|
|
|
@@ -1272,37 +1301,38 @@ static __device__ __forceinline__ void flash_attn_ext_f16_process_tile(
|
|
|
|
|
|
|
|
|
|
// Preload mask and K data for first iteration when using cp_async with multiple stages:
|
|
|
|
|
if constexpr (nstages > 1) {
|
|
|
|
|
static_assert(!use_sparse, "sparse gather not implemented for multi-stage loading");
|
|
|
|
|
static_assert(nbatch_K2 == DKQ/2, "batching not implemented for multi-stage pipeline");
|
|
|
|
|
constexpr bool use_cp_async = true;
|
|
|
|
|
constexpr bool oob_check = false;
|
|
|
|
|
constexpr int k_VKQ_sup = nbatch_fa;
|
|
|
|
|
if (ncols2 > 1 || mask_h) {
|
|
|
|
|
flash_attn_ext_f16_load_mask<ncols1, nwarps, nbatch_fa, use_cp_async, oob_check>
|
|
|
|
|
(mask_h + kb0*nbatch_fa, tile_mask, stride_mask, k_VKQ_sup, jt*ncols1, ne01);
|
|
|
|
|
flash_attn_ext_f16_load_mask<ncols1, nwarps, nbatch_fa, use_cp_async, oob_check, use_sparse>
|
|
|
|
|
(mask_h, tile_mask, stride_mask, kb0*nbatch_fa, k_VKQ_sup, jt*ncols1, ne01, nullptr);
|
|
|
|
|
}
|
|
|
|
|
flash_attn_ext_f16_load_tile<stride_tile_K, swz_K, nwarps, nbatch_fa, use_cp_async, oob_check>
|
|
|
|
|
(K_h2 + int64_t(kb0)*nbatch_fa*stride_K, tile_K, nbatch_K2, stride_K, k_VKQ_sup);
|
|
|
|
|
flash_attn_ext_f16_load_tile<stride_tile_K, swz_K, nwarps, nbatch_fa, use_cp_async, oob_check, use_sparse>
|
|
|
|
|
(K_h2, tile_K, nbatch_K2, stride_K, kb0*nbatch_fa, k_VKQ_sup, nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// kb0_start is always < kb0_stop so the last iter can be executed unconditionally.
|
|
|
|
|
if constexpr (ncols2 == 1) {
|
|
|
|
|
if constexpr (ncols2 == 1 || use_sparse) {
|
|
|
|
|
constexpr bool oob_check = true;
|
|
|
|
|
for (; kb0 < kb0_stop-1; ++kb0) {
|
|
|
|
|
constexpr bool last_iter = false;
|
|
|
|
|
constexpr int k_VKQ_sup = nbatch_fa;
|
|
|
|
|
flash_attn_ext_f16_iter
|
|
|
|
|
<DKQ, DV, ncols1, ncols2, nwarps, use_logit_softcap, V_is_K_view, needs_fixup, is_fixup, last_iter, oob_check,
|
|
|
|
|
<DKQ, DV, ncols1, ncols2, nwarps, use_logit_softcap, V_is_K_view, use_sparse, needs_fixup, is_fixup, last_iter, oob_check,
|
|
|
|
|
T_A_KQ, T_B_KQ, T_C_KQ, T_A_VKQ, T_B_VKQ, T_C_VKQ>
|
|
|
|
|
(Q_f2, K_h2, V_h2, mask_h, dstk, dstk_fixup, scale, slope, logit_softcap,
|
|
|
|
|
(Q_f2, K_h2, V_h2, mask_h, indices, dstk, dstk_fixup, scale, slope, logit_softcap,
|
|
|
|
|
ne01, ne02, stride_K, stride_V, stride_mask, tile_Q, tile_K, tile_V, tile_mask, Q_B, VKQ_C,
|
|
|
|
|
KQ_max, KQ_rowsum, jt, kb0, k_VKQ_sup);
|
|
|
|
|
}
|
|
|
|
|
constexpr bool last_iter = true;
|
|
|
|
|
const int k_VKQ_sup = ne11 - kb0*nbatch_fa;
|
|
|
|
|
flash_attn_ext_f16_iter
|
|
|
|
|
<DKQ, DV, ncols1, ncols2, nwarps, use_logit_softcap, V_is_K_view, needs_fixup, is_fixup, last_iter, oob_check,
|
|
|
|
|
<DKQ, DV, ncols1, ncols2, nwarps, use_logit_softcap, V_is_K_view, use_sparse, needs_fixup, is_fixup, last_iter, oob_check,
|
|
|
|
|
T_A_KQ, T_B_KQ, T_C_KQ, T_A_VKQ, T_B_VKQ, T_C_VKQ>
|
|
|
|
|
(Q_f2, K_h2, V_h2, mask_h, dstk, dstk_fixup, scale, slope, logit_softcap,
|
|
|
|
|
(Q_f2, K_h2, V_h2, mask_h, indices, dstk, dstk_fixup, scale, slope, logit_softcap,
|
|
|
|
|
ne01, ne02, stride_K, stride_V, stride_mask, tile_Q, tile_K, tile_V, tile_mask, Q_B, VKQ_C,
|
|
|
|
|
KQ_max, KQ_rowsum, jt, kb0, k_VKQ_sup);
|
|
|
|
|
} else {
|
|
|
|
@@ -1311,18 +1341,18 @@ static __device__ __forceinline__ void flash_attn_ext_f16_process_tile(
|
|
|
|
|
constexpr bool last_iter = false;
|
|
|
|
|
constexpr int k_VKQ_sup = nbatch_fa;
|
|
|
|
|
flash_attn_ext_f16_iter
|
|
|
|
|
<DKQ, DV, ncols1, ncols2, nwarps, use_logit_softcap, V_is_K_view, needs_fixup, is_fixup, last_iter, oob_check,
|
|
|
|
|
<DKQ, DV, ncols1, ncols2, nwarps, use_logit_softcap, V_is_K_view, use_sparse, needs_fixup, is_fixup, last_iter, oob_check,
|
|
|
|
|
T_A_KQ, T_B_KQ, T_C_KQ, T_A_VKQ, T_B_VKQ, T_C_VKQ>
|
|
|
|
|
(Q_f2, K_h2, V_h2, mask_h, dstk, dstk_fixup, scale, slope, logit_softcap,
|
|
|
|
|
(Q_f2, K_h2, V_h2, mask_h, indices, dstk, dstk_fixup, scale, slope, logit_softcap,
|
|
|
|
|
ne01, ne02, stride_K, stride_V, stride_mask, tile_Q, tile_K, tile_V, tile_mask, Q_B, VKQ_C,
|
|
|
|
|
KQ_max, KQ_rowsum, jt, kb0, k_VKQ_sup);
|
|
|
|
|
}
|
|
|
|
|
constexpr bool last_iter = true;
|
|
|
|
|
constexpr int k_VKQ_sup = nbatch_fa;
|
|
|
|
|
flash_attn_ext_f16_iter
|
|
|
|
|
<DKQ, DV, ncols1, ncols2, nwarps, use_logit_softcap, V_is_K_view, needs_fixup, is_fixup, last_iter, oob_check,
|
|
|
|
|
<DKQ, DV, ncols1, ncols2, nwarps, use_logit_softcap, V_is_K_view, use_sparse, needs_fixup, is_fixup, last_iter, oob_check,
|
|
|
|
|
T_A_KQ, T_B_KQ, T_C_KQ, T_A_VKQ, T_B_VKQ, T_C_VKQ>
|
|
|
|
|
(Q_f2, K_h2, V_h2, mask_h, dstk, dstk_fixup, scale, slope, logit_softcap,
|
|
|
|
|
(Q_f2, K_h2, V_h2, mask_h, indices, dstk, dstk_fixup, scale, slope, logit_softcap,
|
|
|
|
|
ne01, ne02, stride_K, stride_V, stride_mask, tile_Q, tile_K, tile_V, tile_mask, Q_B, VKQ_C,
|
|
|
|
|
KQ_max, KQ_rowsum, jt, kb0, k_VKQ_sup);
|
|
|
|
|
}
|
|
|
|
@@ -1717,7 +1747,7 @@ static __device__ __forceinline__ void flash_attn_ext_f16_process_tile(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
GGML_UNUSED_VARS(Q_f2, K_h2, V_h2, mask_h, sinks_f, dstk, dstk_fixup,
|
|
|
|
|
GGML_UNUSED_VARS(Q_f2, K_h2, V_h2, mask_h, indices, sinks_f, dstk, dstk_fixup,
|
|
|
|
|
scale, slope, logit_softcap, ne01, ne02, gqa_ratio,
|
|
|
|
|
stride_Q1, stride_Q2, stride_K, stride_V, stride_mask,
|
|
|
|
|
jt, kb0_start, kb0_stop);
|
|
|
|
@@ -1725,7 +1755,13 @@ static __device__ __forceinline__ void flash_attn_ext_f16_process_tile(
|
|
|
|
|
#endif // defined(VOLTA_MMA_AVAILABLE) || defined(TURING_MMA_AVAILABLE) || defined(AMD_WMMA_AVAILABLE) || defined(AMD_MFMA_AVAILABLE)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<int DKQ, int DV, int ncols1, int ncols2, bool use_logit_softcap, bool V_is_K_view>
|
|
|
|
|
static constexpr __host__ __device__ bool ggml_cuda_flash_attn_ext_mma_f16_may_use_sparse(
|
|
|
|
|
const int DKQ, const int DV, const int ncols1, const int ncols2) {
|
|
|
|
|
return (DKQ == 512 && DV == 512 && ncols1 == 1 && ncols2 == 8) ||
|
|
|
|
|
(DKQ == 576 && DV == 512 && ncols1 == 1 && ncols2 == 16);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<int DKQ, int DV, int ncols1, int ncols2, bool use_logit_softcap, bool V_is_K_view, bool use_sparse>
|
|
|
|
|
__launch_bounds__(ggml_cuda_fattn_mma_get_nthreads(DKQ, DV, ncols1*ncols2), ggml_cuda_fattn_mma_get_occupancy(DKQ, DV, ncols1*ncols2))
|
|
|
|
|
static __global__ void flash_attn_ext_f16(
|
|
|
|
|
const char * Q_ptr,
|
|
|
|
@@ -1751,14 +1787,15 @@ static __global__ void flash_attn_ext_f16(
|
|
|
|
|
const int32_t nb31, const int32_t nb32, const int64_t nb33) {
|
|
|
|
|
ggml_cuda_pdl_sync(); // TODO optimize placement
|
|
|
|
|
#if defined(FLASH_ATTN_AVAILABLE) && (defined(VOLTA_MMA_AVAILABLE) || defined(TURING_MMA_AVAILABLE) || defined(AMD_WMMA_AVAILABLE) || defined(AMD_MFMA_AVAILABLE))
|
|
|
|
|
const char * GGML_CUDA_RESTRICT Q = Q_ptr;
|
|
|
|
|
const char * GGML_CUDA_RESTRICT K = K_ptr;
|
|
|
|
|
const char * GGML_CUDA_RESTRICT V = V_ptr;
|
|
|
|
|
const char * GGML_CUDA_RESTRICT mask = mask_ptr;
|
|
|
|
|
const char * GGML_CUDA_RESTRICT sinks = sinks_ptr;
|
|
|
|
|
const int * GGML_CUDA_RESTRICT KV_max = KV_max_ptr;
|
|
|
|
|
float * GGML_CUDA_RESTRICT dst = dst_ptr;
|
|
|
|
|
float2 * GGML_CUDA_RESTRICT dst_meta = dst_meta_ptr;
|
|
|
|
|
const char * GGML_CUDA_RESTRICT Q = Q_ptr;
|
|
|
|
|
const char * GGML_CUDA_RESTRICT K = K_ptr;
|
|
|
|
|
const char * GGML_CUDA_RESTRICT V = V_ptr;
|
|
|
|
|
const char * GGML_CUDA_RESTRICT mask = mask_ptr;
|
|
|
|
|
const char * GGML_CUDA_RESTRICT sinks = sinks_ptr;
|
|
|
|
|
const int * GGML_CUDA_RESTRICT KV_max = use_sparse ? nullptr : KV_max_ptr;
|
|
|
|
|
const int * GGML_CUDA_RESTRICT sparse_indices = use_sparse ? KV_max_ptr : nullptr;
|
|
|
|
|
float * GGML_CUDA_RESTRICT dst = dst_ptr;
|
|
|
|
|
float2 * GGML_CUDA_RESTRICT dst_meta = dst_meta_ptr;
|
|
|
|
|
|
|
|
|
|
// Skip unused kernel variants for faster compilation:
|
|
|
|
|
if (use_logit_softcap && !(DKQ == 128 || DKQ == 256 || DKQ == 512)) {
|
|
|
|
@@ -1769,6 +1806,11 @@ static __global__ void flash_attn_ext_f16(
|
|
|
|
|
NO_DEVICE_CODE;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ggml_cuda_flash_attn_ext_mma_f16_may_use_sparse(DKQ, DV, ncols1, ncols2) && use_sparse) {
|
|
|
|
|
NO_DEVICE_CODE;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#ifdef VOLTA_MMA_AVAILABLE
|
|
|
|
|
if (ncols1*ncols2 < 32) {
|
|
|
|
|
NO_DEVICE_CODE;
|
|
|
|
@@ -1845,6 +1887,7 @@ static __global__ void flash_attn_ext_f16(
|
|
|
|
|
|
|
|
|
|
const half2 * V_h2 = V_is_K_view ? K_h2 : (const half2 *) (V + nb23*sequence + nb22*z_KV);
|
|
|
|
|
const float * sinks_f = sinks ? (const float *) sinks + zt_Q : nullptr;
|
|
|
|
|
const int32_t * indices = use_sparse ? sparse_indices + (int64_t(sequence % ne33)*ne31 + jt*ncols1)*ne11 : nullptr;
|
|
|
|
|
|
|
|
|
|
const float slope = ncols2 == 1 ? get_alibi_slope(max_bias, zt_Q, n_head_log2, m0, m1) : 1.0f;
|
|
|
|
|
|
|
|
|
@@ -1854,13 +1897,13 @@ static __global__ void flash_attn_ext_f16(
|
|
|
|
|
constexpr bool is_fixup = false; // All but (potentially) the last iterations write their data to dst rather than the fixup buffer.
|
|
|
|
|
if (kb0_start == 0) {
|
|
|
|
|
constexpr bool needs_fixup = false; // CUDA block is working on an entire tile.
|
|
|
|
|
flash_attn_ext_f16_process_tile<DKQ, DV, ncols1, ncols2, nwarps, use_logit_softcap, V_is_K_view, needs_fixup, is_fixup>
|
|
|
|
|
(Q_f2, K_h2, V_h2, mask_h, sinks_f, dstk, dst_meta, scale, slope, logit_softcap,
|
|
|
|
|
flash_attn_ext_f16_process_tile<DKQ, DV, ncols1, ncols2, nwarps, use_logit_softcap, V_is_K_view, use_sparse, needs_fixup, is_fixup>
|
|
|
|
|
(Q_f2, K_h2, V_h2, mask_h, indices, sinks_f, dstk, dst_meta, scale, slope, logit_softcap,
|
|
|
|
|
ne01, ne02, gqa_ratio, ne11, stride_Q1, stride_Q2, stride_K, stride_V, stride_mask, jt, zt_gqa, kb0_start, kb0_stop);
|
|
|
|
|
} else {
|
|
|
|
|
constexpr bool needs_fixup = true; // CUDA block is missing the beginning of a tile.
|
|
|
|
|
flash_attn_ext_f16_process_tile<DKQ, DV, ncols1, ncols2, nwarps, use_logit_softcap, V_is_K_view, needs_fixup, is_fixup>
|
|
|
|
|
(Q_f2, K_h2, V_h2, mask_h, sinks_f, dstk, dst_meta, scale, slope, logit_softcap,
|
|
|
|
|
flash_attn_ext_f16_process_tile<DKQ, DV, ncols1, ncols2, nwarps, use_logit_softcap, V_is_K_view, use_sparse, needs_fixup, is_fixup>
|
|
|
|
|
(Q_f2, K_h2, V_h2, mask_h, indices, sinks_f, dstk, dst_meta, scale, slope, logit_softcap,
|
|
|
|
|
ne01, ne02, gqa_ratio, ne11, stride_Q1, stride_Q2, stride_K, stride_V, stride_mask, jt, zt_gqa, kb0_start, kb0_stop);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1891,6 +1934,7 @@ static __global__ void flash_attn_ext_f16(
|
|
|
|
|
|
|
|
|
|
const half2 * V_h2 = V_is_K_view ? K_h2 : (const half2 *) (V + nb23*sequence + nb22*z_KV);
|
|
|
|
|
const float * sinks_f = sinks ? (const float *) sinks + zt_Q : nullptr;
|
|
|
|
|
const int32_t * indices = use_sparse ? sparse_indices + (int64_t(sequence % ne33)*ne31 + jt*ncols1)*ne11 : nullptr;
|
|
|
|
|
|
|
|
|
|
const float slope = ncols2 == 1 ? get_alibi_slope(max_bias, zt_Q, n_head_log2, m0, m1) : 1.0f;
|
|
|
|
|
|
|
|
|
@@ -1900,8 +1944,8 @@ static __global__ void flash_attn_ext_f16(
|
|
|
|
|
|
|
|
|
|
constexpr bool is_fixup = true; // Last index writes its data to fixup buffer to avoid data races with other blocks.
|
|
|
|
|
constexpr bool needs_fixup = false;
|
|
|
|
|
flash_attn_ext_f16_process_tile<DKQ, DV, ncols1, ncols2, nwarps, use_logit_softcap, V_is_K_view, needs_fixup, is_fixup>
|
|
|
|
|
(Q_f2, K_h2, V_h2, mask_h, sinks_f, dstk, dst_meta, scale, slope, logit_softcap,
|
|
|
|
|
flash_attn_ext_f16_process_tile<DKQ, DV, ncols1, ncols2, nwarps, use_logit_softcap, V_is_K_view, use_sparse, needs_fixup, is_fixup>
|
|
|
|
|
(Q_f2, K_h2, V_h2, mask_h, indices, sinks_f, dstk, dst_meta, scale, slope, logit_softcap,
|
|
|
|
|
ne01, ne02, gqa_ratio, ne11, stride_Q1, stride_Q2, stride_K, stride_V, stride_mask, jt, zt_gqa, kb0_start, kb0_stop);
|
|
|
|
|
#else
|
|
|
|
|
GGML_UNUSED_VARS(Q_ptr, K_ptr, V_ptr, mask_ptr, sinks_ptr, KV_max_ptr, dst_ptr, dst_meta_ptr, scale,
|
|
|
|
@@ -1917,6 +1961,8 @@ static __global__ void flash_attn_ext_f16(
|
|
|
|
|
#endif // defined(FLASH_ATTN_AVAILABLE) && (defined(VOLTA_MMA_AVAILABLE) || defined(TURING_MMA_AVAILABLE) || defined(AMD_WMMA_AVAILABLE) || defined(AMD_MFMA_AVAILABLE))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ggml_cuda_flash_attn_ext_mma_f16_shall_use_sparse(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
|
|
|
|
|
|
|
|
|
template <int DKQ, int DV, int ncols1, int ncols2>
|
|
|
|
|
void ggml_cuda_flash_attn_ext_mma_f16_case(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
|
|
|
|
const ggml_tensor * KQV = dst;
|
|
|
|
@@ -1963,20 +2009,49 @@ void ggml_cuda_flash_attn_ext_mma_f16_case(ggml_backend_cuda_context & ctx, ggml
|
|
|
|
|
using fattn_kernel_ptr_t = fattn_kernel_t;
|
|
|
|
|
#endif // defined(GGML_USE_HIP)
|
|
|
|
|
fattn_kernel_t fattn_kernel;
|
|
|
|
|
bool use_sparse = false;
|
|
|
|
|
if (logit_softcap == 0.0f) {
|
|
|
|
|
constexpr bool use_logit_softcap = false;
|
|
|
|
|
fattn_kernel = flash_attn_ext_f16<DKQ, DV, ncols1, ncols2, use_logit_softcap, V_is_K_view>;
|
|
|
|
|
#if !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
|
|
|
if constexpr (ggml_cuda_flash_attn_ext_mma_f16_may_use_sparse(DKQ, DV, ncols1, ncols2)) {
|
|
|
|
|
if (ggml_cuda_flash_attn_ext_mma_f16_shall_use_sparse(ctx, dst)) {
|
|
|
|
|
constexpr bool use_sparse_kernel = true;
|
|
|
|
|
fattn_kernel = flash_attn_ext_f16<DKQ, DV, ncols1, ncols2, use_logit_softcap, V_is_K_view, use_sparse_kernel>;
|
|
|
|
|
use_sparse = true;
|
|
|
|
|
|
|
|
|
|
static bool shared_memory_limit_raised[GGML_CUDA_MAX_DEVICES] = {false};
|
|
|
|
|
if (!shared_memory_limit_raised[id]) {
|
|
|
|
|
CUDA_CHECK(cudaFuncSetAttribute(reinterpret_cast<fattn_kernel_ptr_t>(fattn_kernel), cudaFuncAttributeMaxDynamicSharedMemorySize, nbytes_shared_total));
|
|
|
|
|
shared_memory_limit_raised[id] = true;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
constexpr bool use_sparse_kernel = false;
|
|
|
|
|
fattn_kernel = flash_attn_ext_f16<DKQ, DV, ncols1, ncols2, use_logit_softcap, V_is_K_view, use_sparse_kernel>;
|
|
|
|
|
|
|
|
|
|
static bool shared_memory_limit_raised[GGML_CUDA_MAX_DEVICES] = {false};
|
|
|
|
|
if (!shared_memory_limit_raised[id]) {
|
|
|
|
|
CUDA_CHECK(cudaFuncSetAttribute(reinterpret_cast<fattn_kernel_ptr_t>(fattn_kernel), cudaFuncAttributeMaxDynamicSharedMemorySize, nbytes_shared_total));
|
|
|
|
|
shared_memory_limit_raised[id] = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
#endif // !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
|
|
|
{
|
|
|
|
|
constexpr bool use_sparse_kernel = false;
|
|
|
|
|
fattn_kernel = flash_attn_ext_f16<DKQ, DV, ncols1, ncols2, use_logit_softcap, V_is_K_view, use_sparse_kernel>;
|
|
|
|
|
|
|
|
|
|
#if !defined(GGML_USE_MUSA)
|
|
|
|
|
static bool shared_memory_limit_raised[GGML_CUDA_MAX_DEVICES] = {false};
|
|
|
|
|
if (!shared_memory_limit_raised[id]) {
|
|
|
|
|
CUDA_CHECK(cudaFuncSetAttribute(reinterpret_cast<fattn_kernel_ptr_t>(fattn_kernel), cudaFuncAttributeMaxDynamicSharedMemorySize, nbytes_shared_total));
|
|
|
|
|
shared_memory_limit_raised[id] = true;
|
|
|
|
|
}
|
|
|
|
|
static bool shared_memory_limit_raised[GGML_CUDA_MAX_DEVICES] = {false};
|
|
|
|
|
if (!shared_memory_limit_raised[id]) {
|
|
|
|
|
CUDA_CHECK(cudaFuncSetAttribute(reinterpret_cast<fattn_kernel_ptr_t>(fattn_kernel), cudaFuncAttributeMaxDynamicSharedMemorySize, nbytes_shared_total));
|
|
|
|
|
shared_memory_limit_raised[id] = true;
|
|
|
|
|
}
|
|
|
|
|
#endif // !defined(GGML_USE_MUSA)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
constexpr bool use_logit_softcap = true;
|
|
|
|
|
fattn_kernel = flash_attn_ext_f16<DKQ, DV, ncols1, ncols2, use_logit_softcap, V_is_K_view>;
|
|
|
|
|
constexpr bool use_sparse_kernel = false;
|
|
|
|
|
fattn_kernel = flash_attn_ext_f16<DKQ, DV, ncols1, ncols2, use_logit_softcap, V_is_K_view, use_sparse_kernel>;
|
|
|
|
|
|
|
|
|
|
#if !defined(GGML_USE_MUSA)
|
|
|
|
|
static bool shared_memory_limit_raised[GGML_CUDA_MAX_DEVICES] = {false};
|
|
|
|
@@ -1988,7 +2063,7 @@ void ggml_cuda_flash_attn_ext_mma_f16_case(ggml_backend_cuda_context & ctx, ggml
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
launch_fattn<DV, ncols1, ncols2>
|
|
|
|
|
(ctx, dst, fattn_kernel, nwarps, nbytes_shared_total, nbatch_fa, true, true, true, warp_size_host);
|
|
|
|
|
(ctx, dst, fattn_kernel, nwarps, nbytes_shared_total, nbatch_fa, true, true, true, use_sparse, warp_size_host);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|