Spaces:
Runtime error
Runtime error
Upload folder using huggingface_hub (part 4)
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- backend/llama.cpp/ggml/src/ggml-cuda/fwht.cu +101 -0
- backend/llama.cpp/ggml/src/ggml-cuda/fwht.cuh +4 -0
- backend/llama.cpp/ggml/src/ggml-cuda/gated_delta_net.cu +327 -0
- backend/llama.cpp/ggml/src/ggml-cuda/gated_delta_net.cuh +14 -0
- backend/llama.cpp/ggml/src/ggml-cuda/getrows.cu +311 -0
- backend/llama.cpp/ggml/src/ggml-cuda/getrows.cuh +15 -0
- backend/llama.cpp/ggml/src/ggml-cuda/ggml-cuda.cu +0 -0
- backend/llama.cpp/ggml/src/ggml-cuda/gla.cu +93 -0
- backend/llama.cpp/ggml/src/ggml-cuda/gla.cuh +3 -0
- backend/llama.cpp/ggml/src/ggml-cuda/im2col.cu +267 -0
- backend/llama.cpp/ggml/src/ggml-cuda/im2col.cuh +6 -0
- backend/llama.cpp/ggml/src/ggml-cuda/mean.cu +77 -0
- backend/llama.cpp/ggml/src/ggml-cuda/mean.cuh +3 -0
- backend/llama.cpp/ggml/src/ggml-cuda/mma.cuh +1456 -0
- backend/llama.cpp/ggml/src/ggml-cuda/mmf.cu +191 -0
- backend/llama.cpp/ggml/src/ggml-cuda/mmf.cuh +908 -0
- backend/llama.cpp/ggml/src/ggml-cuda/mmid.cu +164 -0
- backend/llama.cpp/ggml/src/ggml-cuda/mmid.cuh +5 -0
- backend/llama.cpp/ggml/src/ggml-cuda/mmq.cu +379 -0
- backend/llama.cpp/ggml/src/ggml-cuda/mmq.cuh +0 -0
- backend/llama.cpp/ggml/src/ggml-cuda/mmvf.cu +869 -0
- backend/llama.cpp/ggml/src/ggml-cuda/mmvf.cuh +14 -0
- backend/llama.cpp/ggml/src/ggml-cuda/mmvq.cu +1289 -0
- backend/llama.cpp/ggml/src/ggml-cuda/mmvq.cuh +18 -0
- backend/llama.cpp/ggml/src/ggml-cuda/norm.cu +698 -0
- backend/llama.cpp/ggml/src/ggml-cuda/norm.cuh +18 -0
- backend/llama.cpp/ggml/src/ggml-cuda/opt-step-adamw.cu +78 -0
- backend/llama.cpp/ggml/src/ggml-cuda/opt-step-adamw.cuh +5 -0
- backend/llama.cpp/ggml/src/ggml-cuda/opt-step-sgd.cu +49 -0
- backend/llama.cpp/ggml/src/ggml-cuda/opt-step-sgd.cuh +5 -0
- backend/llama.cpp/ggml/src/ggml-cuda/out-prod.cu +127 -0
- backend/llama.cpp/ggml/src/ggml-cuda/out-prod.cuh +3 -0
- backend/llama.cpp/ggml/src/ggml-cuda/pad.cu +106 -0
- backend/llama.cpp/ggml/src/ggml-cuda/pad.cuh +5 -0
- backend/llama.cpp/ggml/src/ggml-cuda/pad_reflect_1d.cu +91 -0
- backend/llama.cpp/ggml/src/ggml-cuda/pad_reflect_1d.cuh +5 -0
- backend/llama.cpp/ggml/src/ggml-cuda/pool2d.cu +94 -0
- backend/llama.cpp/ggml/src/ggml-cuda/pool2d.cuh +5 -0
- backend/llama.cpp/ggml/src/ggml-cuda/quantize.cu +450 -0
- backend/llama.cpp/ggml/src/ggml-cuda/quantize.cuh +41 -0
- backend/llama.cpp/ggml/src/ggml-cuda/reduce_rows.cuh +43 -0
- backend/llama.cpp/ggml/src/ggml-cuda/roll.cu +67 -0
- backend/llama.cpp/ggml/src/ggml-cuda/roll.cuh +5 -0
- backend/llama.cpp/ggml/src/ggml-cuda/rope.cu +672 -0
- backend/llama.cpp/ggml/src/ggml-cuda/rope.cuh +9 -0
- backend/llama.cpp/ggml/src/ggml-cuda/scale.cu +37 -0
- backend/llama.cpp/ggml/src/ggml-cuda/scale.cuh +5 -0
- backend/llama.cpp/ggml/src/ggml-cuda/set-rows.cu +398 -0
- backend/llama.cpp/ggml/src/ggml-cuda/set-rows.cuh +7 -0
- backend/llama.cpp/ggml/src/ggml-cuda/set.cu +39 -0
backend/llama.cpp/ggml/src/ggml-cuda/fwht.cu
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
#include "fwht.cuh"
|
| 3 |
+
|
| 4 |
+
template <int N>
|
| 5 |
+
__launch_bounds__(4*ggml_cuda_get_physical_warp_size(), 1)
|
| 6 |
+
__global__ void fwht_cuda(const float * src, float * dst, const int64_t n_rows, const float scale) {
|
| 7 |
+
constexpr int warp_size = ggml_cuda_get_physical_warp_size();
|
| 8 |
+
|
| 9 |
+
const int64_t r = (int64_t) blockIdx.x * blockDim.y + threadIdx.y;
|
| 10 |
+
|
| 11 |
+
if (r >= n_rows) {
|
| 12 |
+
return;
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
src += r * N;
|
| 16 |
+
dst += r * N;
|
| 17 |
+
|
| 18 |
+
static constexpr int el_w = N / warp_size;
|
| 19 |
+
float reg[el_w];
|
| 20 |
+
const int lane = threadIdx.x;
|
| 21 |
+
|
| 22 |
+
ggml_cuda_pdl_sync();
|
| 23 |
+
#pragma unroll
|
| 24 |
+
for (int i = 0; i < el_w; ++i) {
|
| 25 |
+
reg[i] = src[i * warp_size + lane] * scale;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
#pragma unroll
|
| 29 |
+
for (int h = 1; h < warp_size; h *= 2) {
|
| 30 |
+
#pragma unroll
|
| 31 |
+
for (int j = 0; j < el_w; j++) {
|
| 32 |
+
const float val = reg[j];
|
| 33 |
+
const float val2 = __shfl_xor_sync(0xFFFFFFFF, val, h, warp_size);
|
| 34 |
+
|
| 35 |
+
reg[j] = (lane & h) == 0 ? val + val2 : val2 - val;
|
| 36 |
+
}
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
#pragma unroll
|
| 40 |
+
for (int h = warp_size; h < N; h *= 2) {
|
| 41 |
+
const int step = h / warp_size;
|
| 42 |
+
#pragma unroll
|
| 43 |
+
for (int j = 0; j < el_w; j += 2 * step) {
|
| 44 |
+
#pragma unroll
|
| 45 |
+
for (int k = 0; k < step; k++) {
|
| 46 |
+
const float x = reg[j + k];
|
| 47 |
+
const float y = reg[j + k + step];
|
| 48 |
+
|
| 49 |
+
reg[j + k] = x + y;
|
| 50 |
+
reg[j + k + step] = x - y;
|
| 51 |
+
}
|
| 52 |
+
}
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
#pragma unroll
|
| 56 |
+
for (int i = 0; i < el_w; ++i) {
|
| 57 |
+
dst[i * warp_size + lane] = reg[i];
|
| 58 |
+
}
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
bool ggml_cuda_op_fwht(ggml_backend_cuda_context & ctx, const ggml_tensor * src, ggml_tensor * dst) {
|
| 62 |
+
GGML_ASSERT(ggml_are_same_shape(src, dst));
|
| 63 |
+
if (!ggml_is_contiguous(src) || !ggml_is_contiguous(dst)) {
|
| 64 |
+
return false;
|
| 65 |
+
}
|
| 66 |
+
const int n = src->ne[0];
|
| 67 |
+
const int64_t rows = ggml_nrows(src);
|
| 68 |
+
|
| 69 |
+
const float * src_d = (const float *) src->data;
|
| 70 |
+
float * dst_d = (float *) dst->data;
|
| 71 |
+
|
| 72 |
+
const int warp_size = ggml_cuda_info().devices[ggml_cuda_get_device()].warp_size;
|
| 73 |
+
const int rows_per_block = 4;
|
| 74 |
+
|
| 75 |
+
const int64_t num_blocks = (rows + rows_per_block - 1) / rows_per_block;
|
| 76 |
+
|
| 77 |
+
cudaStream_t stream = ctx.stream();
|
| 78 |
+
dim3 grid_dims(num_blocks, 1, 1);
|
| 79 |
+
dim3 block_dims(warp_size, rows_per_block, 1);
|
| 80 |
+
const ggml_cuda_kernel_launch_params launch_params =
|
| 81 |
+
ggml_cuda_kernel_launch_params(grid_dims, block_dims, 0, stream);
|
| 82 |
+
|
| 83 |
+
const float scale = 1 / sqrtf(n);
|
| 84 |
+
|
| 85 |
+
switch (n) {
|
| 86 |
+
case 64:
|
| 87 |
+
ggml_cuda_kernel_launch(fwht_cuda<64>, launch_params, src_d, dst_d, rows, scale);
|
| 88 |
+
return true;
|
| 89 |
+
case 128:
|
| 90 |
+
ggml_cuda_kernel_launch(fwht_cuda<128>, launch_params, src_d, dst_d, rows, scale);
|
| 91 |
+
return true;
|
| 92 |
+
case 256:
|
| 93 |
+
ggml_cuda_kernel_launch(fwht_cuda<256>, launch_params, src_d, dst_d, rows, scale);
|
| 94 |
+
return true;
|
| 95 |
+
case 512:
|
| 96 |
+
ggml_cuda_kernel_launch(fwht_cuda<512>, launch_params, src_d, dst_d, rows, scale);
|
| 97 |
+
return true;
|
| 98 |
+
default:
|
| 99 |
+
return false;
|
| 100 |
+
}
|
| 101 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/fwht.cuh
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
|
| 3 |
+
// Returns whether the Fast Walsh-Hadamard transform could be used.
|
| 4 |
+
bool ggml_cuda_op_fwht(ggml_backend_cuda_context & ctx, const ggml_tensor * src, ggml_tensor * dst);
|
backend/llama.cpp/ggml/src/ggml-cuda/gated_delta_net.cu
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "gated_delta_net.cuh"
|
| 2 |
+
#include "ggml-cuda/common.cuh"
|
| 3 |
+
|
| 4 |
+
template <int S_v, bool KDA, bool keep_rs_t>
|
| 5 |
+
__global__ void __launch_bounds__((ggml_cuda_get_physical_warp_size() < S_v ? ggml_cuda_get_physical_warp_size() : S_v) * 4, 2)
|
| 6 |
+
gated_delta_net_cuda(const float * q,
|
| 7 |
+
const float * k,
|
| 8 |
+
const float * v,
|
| 9 |
+
const float * g,
|
| 10 |
+
const float * beta,
|
| 11 |
+
const float * curr_state,
|
| 12 |
+
float * dst,
|
| 13 |
+
float * state,
|
| 14 |
+
int64_t H,
|
| 15 |
+
int64_t n_tokens,
|
| 16 |
+
int64_t n_seqs,
|
| 17 |
+
int64_t sq1,
|
| 18 |
+
int64_t sq2,
|
| 19 |
+
int64_t sq3,
|
| 20 |
+
int64_t sv1,
|
| 21 |
+
int64_t sv2,
|
| 22 |
+
int64_t sv3,
|
| 23 |
+
int64_t sb1,
|
| 24 |
+
int64_t sb2,
|
| 25 |
+
int64_t sb3,
|
| 26 |
+
const uint3 neqk1_magic,
|
| 27 |
+
const uint3 rq3_magic,
|
| 28 |
+
float scale,
|
| 29 |
+
int64_t state_slot_stride,
|
| 30 |
+
int K) {
|
| 31 |
+
const uint32_t h_idx = blockIdx.x;
|
| 32 |
+
const uint32_t sequence = blockIdx.y;
|
| 33 |
+
// each warp owns one column, using warp-level primitives to reduce across rows
|
| 34 |
+
const int lane = threadIdx.x;
|
| 35 |
+
const int col = blockIdx.z * blockDim.y + threadIdx.y;
|
| 36 |
+
|
| 37 |
+
const uint32_t iq1 = fastmodulo(h_idx, neqk1_magic);
|
| 38 |
+
const uint32_t iq3 = fastdiv(sequence, rq3_magic);
|
| 39 |
+
|
| 40 |
+
float * attn_data = dst;
|
| 41 |
+
|
| 42 |
+
// input state holds s0 only: [S_v, S_v, H, n_seqs] — seq stride is D = H * S_v * S_v.
|
| 43 |
+
// output state layout (per-slot D * n_seqs) — same per-(seq,head) offset as before.
|
| 44 |
+
const int64_t state_in_offset = sequence * H * S_v * S_v + h_idx * S_v * S_v;
|
| 45 |
+
const int64_t state_out_offset = (sequence * H + h_idx) * S_v * S_v;
|
| 46 |
+
state += state_out_offset;
|
| 47 |
+
curr_state += state_in_offset + col * S_v;
|
| 48 |
+
attn_data += (sequence * n_tokens * H + h_idx) * S_v;
|
| 49 |
+
|
| 50 |
+
constexpr int warp_size = ggml_cuda_get_physical_warp_size() < S_v ? ggml_cuda_get_physical_warp_size() : S_v;
|
| 51 |
+
static_assert(S_v % warp_size == 0, "S_v must be a multiple of warp_size");
|
| 52 |
+
constexpr int rows_per_lane = (S_v + warp_size - 1) / warp_size;
|
| 53 |
+
float s_shard[rows_per_lane];
|
| 54 |
+
// state is stored transposed: M[col][i] = S[i][col], row col is contiguous
|
| 55 |
+
|
| 56 |
+
ggml_cuda_pdl_sync();
|
| 57 |
+
#pragma unroll
|
| 58 |
+
for (int r = 0; r < rows_per_lane; r++) {
|
| 59 |
+
const int i = r * warp_size + lane;
|
| 60 |
+
s_shard[r] = curr_state[i];
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
for (int t = 0; t < n_tokens; t++) {
|
| 64 |
+
const float * q_t = q + iq3 * sq3 + t * sq2 + iq1 * sq1;
|
| 65 |
+
const float * k_t = k + iq3 * sq3 + t * sq2 + iq1 * sq1;
|
| 66 |
+
const float * v_t = v + sequence * sv3 + t * sv2 + h_idx * sv1;
|
| 67 |
+
|
| 68 |
+
const int64_t gb_offset = sequence * sb3 + t * sb2 + h_idx * sb1;
|
| 69 |
+
const float * beta_t = beta + gb_offset;
|
| 70 |
+
const float * g_t = g + gb_offset * (KDA ? S_v : 1);
|
| 71 |
+
|
| 72 |
+
const float beta_val = *beta_t;
|
| 73 |
+
|
| 74 |
+
// Cache k and q in registers
|
| 75 |
+
float k_reg[rows_per_lane];
|
| 76 |
+
float q_reg[rows_per_lane];
|
| 77 |
+
#pragma unroll
|
| 78 |
+
for (int r = 0; r < rows_per_lane; r++) {
|
| 79 |
+
const int i = r * warp_size + lane;
|
| 80 |
+
k_reg[r] = k_t[i];
|
| 81 |
+
q_reg[r] = q_t[i];
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
if constexpr (!KDA) {
|
| 85 |
+
const float g_val = expf(*g_t);
|
| 86 |
+
|
| 87 |
+
// kv[col] = (S^T @ k)[col] = sum_i S[i][col] * k[i]
|
| 88 |
+
float kv_shard = 0.0f;
|
| 89 |
+
#pragma unroll
|
| 90 |
+
for (int r = 0; r < rows_per_lane; r++) {
|
| 91 |
+
kv_shard += s_shard[r] * k_reg[r];
|
| 92 |
+
}
|
| 93 |
+
float kv_col = warp_reduce_sum<warp_size>(kv_shard);
|
| 94 |
+
|
| 95 |
+
// delta[col] = (v[col] - g * kv[col]) * beta
|
| 96 |
+
float delta_col = (v_t[col] - g_val * kv_col) * beta_val;
|
| 97 |
+
|
| 98 |
+
// fused: S[i][col] = g * S[i][col] + k[i] * delta[col]
|
| 99 |
+
// attn[col] = (S^T @ q)[col] = sum_i S[i][col] * q[i]
|
| 100 |
+
float attn_partial = 0.0f;
|
| 101 |
+
#pragma unroll
|
| 102 |
+
for (int r = 0; r < rows_per_lane; r++) {
|
| 103 |
+
s_shard[r] = g_val * s_shard[r] + k_reg[r] * delta_col;
|
| 104 |
+
attn_partial += s_shard[r] * q_reg[r];
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
float attn_col = warp_reduce_sum<warp_size>(attn_partial);
|
| 108 |
+
|
| 109 |
+
if (lane == 0) {
|
| 110 |
+
attn_data[col] = attn_col * scale;
|
| 111 |
+
}
|
| 112 |
+
} else {
|
| 113 |
+
// kv[col] = sum_i g[i] * S[i][col] * k[i]
|
| 114 |
+
float kv_shard = 0.0f;
|
| 115 |
+
#pragma unroll
|
| 116 |
+
for (int r = 0; r < rows_per_lane; r++) {
|
| 117 |
+
const int i = r * warp_size + lane;
|
| 118 |
+
kv_shard += expf(g_t[i]) * s_shard[r] * k_reg[r];
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
float kv_col = warp_reduce_sum<warp_size>(kv_shard);
|
| 122 |
+
|
| 123 |
+
// delta[col] = (v[col] - kv[col]) * beta
|
| 124 |
+
float delta_col = (v_t[col] - kv_col) * beta_val;
|
| 125 |
+
|
| 126 |
+
// fused: S[i][col] = g[i] * S[i][col] + k[i] * delta[col]
|
| 127 |
+
// attn[col] = (S^T @ q)[col] = sum_i S[i][col] * q[i]
|
| 128 |
+
float attn_partial = 0.0f;
|
| 129 |
+
#pragma unroll
|
| 130 |
+
for (int r = 0; r < rows_per_lane; r++) {
|
| 131 |
+
const int i = r * warp_size + lane;
|
| 132 |
+
s_shard[r] = expf(g_t[i]) * s_shard[r] + k_reg[r] * delta_col;
|
| 133 |
+
attn_partial += s_shard[r] * q_reg[r];
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
float attn_col = warp_reduce_sum<warp_size>(attn_partial);
|
| 137 |
+
|
| 138 |
+
if (lane == 0) {
|
| 139 |
+
attn_data[col] = attn_col * scale;
|
| 140 |
+
}
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
attn_data += S_v * H;
|
| 144 |
+
|
| 145 |
+
if constexpr (keep_rs_t) {
|
| 146 |
+
// snapshot slot mapping: slot 0 = most recent state, slot s = s tokens back.
|
| 147 |
+
// When n_tokens < K only slots 0..n_tokens-1 are written; older slots are caller-owned.
|
| 148 |
+
const int target_slot = (int) n_tokens - 1 - t;
|
| 149 |
+
if (target_slot >= 0 && target_slot < K) {
|
| 150 |
+
float * curr_state = state + target_slot * state_slot_stride;
|
| 151 |
+
#pragma unroll
|
| 152 |
+
for (int r = 0; r < rows_per_lane; r++) {
|
| 153 |
+
const int i = r * warp_size + lane;
|
| 154 |
+
curr_state[col * S_v + i] = s_shard[r];
|
| 155 |
+
}
|
| 156 |
+
}
|
| 157 |
+
}
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
if constexpr (!keep_rs_t) {
|
| 161 |
+
#pragma unroll
|
| 162 |
+
for (int r = 0; r < rows_per_lane; r++) {
|
| 163 |
+
const int i = r * warp_size + lane;
|
| 164 |
+
state[col * S_v + i] = s_shard[r];
|
| 165 |
+
}
|
| 166 |
+
}
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
template <bool KDA, bool keep_rs_t>
|
| 170 |
+
static void launch_gated_delta_net(
|
| 171 |
+
const float * q_d, const float * k_d, const float * v_d,
|
| 172 |
+
const float * g_d, const float * b_d, const float * s_d,
|
| 173 |
+
float * dst_d, float * state_d,
|
| 174 |
+
int64_t S_v, int64_t H, int64_t n_tokens, int64_t n_seqs,
|
| 175 |
+
int64_t sq1, int64_t sq2, int64_t sq3,
|
| 176 |
+
int64_t sv1, int64_t sv2, int64_t sv3,
|
| 177 |
+
int64_t sb1, int64_t sb2, int64_t sb3,
|
| 178 |
+
int64_t neqk1, int64_t rq3,
|
| 179 |
+
float scale, int64_t state_slot_stride, int K, cudaStream_t stream) {
|
| 180 |
+
//TODO: Add chunked kernel for even faster pre-fill
|
| 181 |
+
const int warp_size = ggml_cuda_info().devices[ggml_cuda_get_device()].warp_size;
|
| 182 |
+
const int num_warps = 4;
|
| 183 |
+
dim3 grid_dims(H, n_seqs, (S_v + num_warps - 1) / num_warps);
|
| 184 |
+
dim3 block_dims(warp_size <= S_v ? warp_size : S_v, num_warps, 1);
|
| 185 |
+
|
| 186 |
+
const uint3 neqk1_magic = init_fastdiv_values(neqk1);
|
| 187 |
+
const uint3 rq3_magic = init_fastdiv_values(rq3);
|
| 188 |
+
|
| 189 |
+
const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params(grid_dims, block_dims, 0, stream);
|
| 190 |
+
switch (S_v) {
|
| 191 |
+
case 16:
|
| 192 |
+
ggml_cuda_kernel_launch(gated_delta_net_cuda<16, KDA, keep_rs_t>, launch_params,
|
| 193 |
+
q_d, k_d, v_d, g_d, b_d, s_d, dst_d, state_d, H,
|
| 194 |
+
n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3,
|
| 195 |
+
sb1, sb2, sb3, neqk1_magic, rq3_magic, scale, state_slot_stride, K);
|
| 196 |
+
break;
|
| 197 |
+
case 32:
|
| 198 |
+
ggml_cuda_kernel_launch(gated_delta_net_cuda<32, KDA, keep_rs_t>, launch_params,
|
| 199 |
+
q_d, k_d, v_d, g_d, b_d, s_d, dst_d, state_d, H,
|
| 200 |
+
n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3,
|
| 201 |
+
sb1, sb2, sb3, neqk1_magic, rq3_magic, scale, state_slot_stride, K);
|
| 202 |
+
break;
|
| 203 |
+
case 64: {
|
| 204 |
+
ggml_cuda_kernel_launch(gated_delta_net_cuda<64, KDA, keep_rs_t>, launch_params,
|
| 205 |
+
q_d, k_d, v_d, g_d, b_d, s_d, dst_d, state_d, H,
|
| 206 |
+
n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3,
|
| 207 |
+
sb1, sb2, sb3, neqk1_magic, rq3_magic, scale, state_slot_stride, K);
|
| 208 |
+
break;
|
| 209 |
+
}
|
| 210 |
+
case 128: {
|
| 211 |
+
ggml_cuda_kernel_launch(gated_delta_net_cuda<128, KDA, keep_rs_t>, launch_params,
|
| 212 |
+
q_d, k_d, v_d, g_d, b_d, s_d, dst_d, state_d, H,
|
| 213 |
+
n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3,
|
| 214 |
+
sb1, sb2, sb3, neqk1_magic, rq3_magic, scale, state_slot_stride, K);
|
| 215 |
+
break;
|
| 216 |
+
}
|
| 217 |
+
default:
|
| 218 |
+
GGML_ABORT("fatal error");
|
| 219 |
+
break;
|
| 220 |
+
}
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
static void ggml_cuda_op_gated_delta_net_impl(
|
| 224 |
+
ggml_backend_cuda_context & ctx, ggml_tensor * dst, const ggml_cuda_gated_delta_net_fused_cache * cache) {
|
| 225 |
+
ggml_tensor * src_q = dst->src[0];
|
| 226 |
+
ggml_tensor * src_k = dst->src[1];
|
| 227 |
+
ggml_tensor * src_v = dst->src[2];
|
| 228 |
+
ggml_tensor * src_g = dst->src[3];
|
| 229 |
+
ggml_tensor * src_beta = dst->src[4];
|
| 230 |
+
ggml_tensor * src_state = dst->src[5];
|
| 231 |
+
|
| 232 |
+
GGML_TENSOR_LOCALS(int64_t, neq, src_q, ne);
|
| 233 |
+
GGML_TENSOR_LOCALS(size_t , nbq, src_q, nb);
|
| 234 |
+
GGML_TENSOR_LOCALS(int64_t, nek, src_k, ne);
|
| 235 |
+
GGML_TENSOR_LOCALS(size_t , nbk, src_k, nb);
|
| 236 |
+
GGML_TENSOR_LOCALS(int64_t, nev, src_v, ne);
|
| 237 |
+
GGML_TENSOR_LOCALS(size_t, nbv, src_v, nb);
|
| 238 |
+
GGML_TENSOR_LOCALS(size_t, nbb, src_beta, nb);
|
| 239 |
+
|
| 240 |
+
const int64_t S_v = nev0;
|
| 241 |
+
const int64_t H = nev1;
|
| 242 |
+
const int64_t n_tokens = nev2;
|
| 243 |
+
const int64_t n_seqs = nev3;
|
| 244 |
+
|
| 245 |
+
const bool kda = (src_g->ne[0] == S_v);
|
| 246 |
+
|
| 247 |
+
GGML_ASSERT(neq1 == nek1);
|
| 248 |
+
const int64_t neqk1 = neq1;
|
| 249 |
+
|
| 250 |
+
const int64_t rq3 = nev3 / neq3;
|
| 251 |
+
|
| 252 |
+
const float * q_d = (const float *) src_q->data;
|
| 253 |
+
const float * k_d = (const float *) src_k->data;
|
| 254 |
+
const float * v_d = (const float *) src_v->data;
|
| 255 |
+
const float * g_d = (const float *) src_g->data;
|
| 256 |
+
const float * b_d = (const float *) src_beta->data;
|
| 257 |
+
|
| 258 |
+
const float * s_d = (const float *) src_state->data;
|
| 259 |
+
float * dst_d = (float *) dst->data;
|
| 260 |
+
|
| 261 |
+
GGML_ASSERT(ggml_is_contiguous_rows(src_q));
|
| 262 |
+
GGML_ASSERT(ggml_is_contiguous_rows(src_k));
|
| 263 |
+
GGML_ASSERT(ggml_is_contiguous_rows(src_v));
|
| 264 |
+
GGML_ASSERT(ggml_are_same_stride(src_q, src_k));
|
| 265 |
+
GGML_ASSERT(src_g->ne[0] == 1 || kda);
|
| 266 |
+
GGML_ASSERT(ggml_is_contiguous(src_g));
|
| 267 |
+
GGML_ASSERT(ggml_is_contiguous(src_beta));
|
| 268 |
+
GGML_ASSERT(ggml_is_contiguous(src_state));
|
| 269 |
+
|
| 270 |
+
// strides in floats (beta strides used for both g and beta offset computation)
|
| 271 |
+
const int64_t sq1 = nbq1 / sizeof(float);
|
| 272 |
+
const int64_t sq2 = nbq2 / sizeof(float);
|
| 273 |
+
const int64_t sq3 = nbq3 / sizeof(float);
|
| 274 |
+
const int64_t sv1 = nbv1 / sizeof(float);
|
| 275 |
+
const int64_t sv2 = nbv2 / sizeof(float);
|
| 276 |
+
const int64_t sv3 = nbv3 / sizeof(float);
|
| 277 |
+
const int64_t sb1 = nbb1 / sizeof(float);
|
| 278 |
+
const int64_t sb2 = nbb2 / sizeof(float);
|
| 279 |
+
const int64_t sb3 = nbb3 / sizeof(float);
|
| 280 |
+
|
| 281 |
+
const float scale = 1.0f / sqrtf((float) S_v);
|
| 282 |
+
|
| 283 |
+
cudaStream_t stream = ctx.stream();
|
| 284 |
+
|
| 285 |
+
// K (snapshot slot count) is an op param; state holds s0 only [S_v, S_v, H, n_seqs].
|
| 286 |
+
const int K = ggml_get_op_params_i32(dst, 0);
|
| 287 |
+
const bool keep_rs = K > 1;
|
| 288 |
+
|
| 289 |
+
// recurrent state -> gdn_out tail (after attention scores), or the cache when fusing
|
| 290 |
+
float * state_d = dst_d + S_v * H * n_tokens * n_seqs;
|
| 291 |
+
int64_t state_slot_stride = S_v * S_v * H * n_seqs;
|
| 292 |
+
if (cache != nullptr) {
|
| 293 |
+
state_d = cache->data;
|
| 294 |
+
state_slot_stride = cache->slot_stride;
|
| 295 |
+
}
|
| 296 |
+
|
| 297 |
+
if (kda) {
|
| 298 |
+
if (keep_rs) {
|
| 299 |
+
launch_gated_delta_net<true, true>(q_d, k_d, v_d, g_d, b_d, s_d, dst_d, state_d,
|
| 300 |
+
S_v, H, n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3,
|
| 301 |
+
sb1, sb2, sb3, neqk1, rq3, scale, state_slot_stride, K, stream);
|
| 302 |
+
} else {
|
| 303 |
+
launch_gated_delta_net<true, false>(q_d, k_d, v_d, g_d, b_d, s_d, dst_d, state_d,
|
| 304 |
+
S_v, H, n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3,
|
| 305 |
+
sb1, sb2, sb3, neqk1, rq3, scale, state_slot_stride, K, stream);
|
| 306 |
+
}
|
| 307 |
+
} else {
|
| 308 |
+
if (keep_rs) {
|
| 309 |
+
launch_gated_delta_net<false, true>(q_d, k_d, v_d, g_d, b_d, s_d, dst_d, state_d,
|
| 310 |
+
S_v, H, n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3,
|
| 311 |
+
sb1, sb2, sb3, neqk1, rq3, scale, state_slot_stride, K, stream);
|
| 312 |
+
} else {
|
| 313 |
+
launch_gated_delta_net<false, false>(q_d, k_d, v_d, g_d, b_d, s_d, dst_d, state_d,
|
| 314 |
+
S_v, H, n_tokens, n_seqs, sq1, sq2, sq3, sv1, sv2, sv3,
|
| 315 |
+
sb1, sb2, sb3, neqk1, rq3, scale, state_slot_stride, K, stream);
|
| 316 |
+
}
|
| 317 |
+
}
|
| 318 |
+
}
|
| 319 |
+
|
| 320 |
+
void ggml_cuda_op_gated_delta_net(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 321 |
+
ggml_cuda_op_gated_delta_net_impl(ctx, dst, nullptr);
|
| 322 |
+
}
|
| 323 |
+
|
| 324 |
+
void ggml_cuda_op_gated_delta_net_fused_cache(
|
| 325 |
+
ggml_backend_cuda_context & ctx, ggml_tensor * dst, ggml_cuda_gated_delta_net_fused_cache cache) {
|
| 326 |
+
ggml_cuda_op_gated_delta_net_impl(ctx, dst, &cache);
|
| 327 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/gated_delta_net.cuh
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
#include "ggml.h"
|
| 3 |
+
|
| 4 |
+
// fused-kernel recurrent-state output; strides in elements (per-seq stride is always D, set in-kernel)
|
| 5 |
+
struct ggml_cuda_gated_delta_net_fused_cache {
|
| 6 |
+
float * data; // rollback slot 0
|
| 7 |
+
int64_t slot_stride; // between rollback slots (0 when K==1)
|
| 8 |
+
};
|
| 9 |
+
|
| 10 |
+
void ggml_cuda_op_gated_delta_net(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
| 11 |
+
|
| 12 |
+
// same op, but writes the snapshot(s) into the cache instead of dst (see ggml_cuda_try_gdn_cache_fusion)
|
| 13 |
+
void ggml_cuda_op_gated_delta_net_fused_cache(ggml_backend_cuda_context & ctx, ggml_tensor * dst,
|
| 14 |
+
ggml_cuda_gated_delta_net_fused_cache cache);
|
backend/llama.cpp/ggml/src/ggml-cuda/getrows.cu
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "getrows.cuh"
|
| 2 |
+
#include "dequantize.cuh"
|
| 3 |
+
#include "convert.cuh"
|
| 4 |
+
|
| 5 |
+
template<int qk, int qr, dequantize_kernel_t dequantize_kernel, typename dst_t>
|
| 6 |
+
static __global__ void k_get_rows(
|
| 7 |
+
const void * __restrict__ src0, const int32_t * __restrict__ src1, dst_t * __restrict__ dst,
|
| 8 |
+
const int64_t ne00, /*const int64_t ne01, const int64_t ne02, const int64_t ne03,*/
|
| 9 |
+
/*const int64_t ne10,*/ const int64_t ne11, const uint3 ne12_fdv, /*const int64_t ne13,*/
|
| 10 |
+
/*const size_t s0,*/ const size_t s1, const size_t s2, const size_t s3,
|
| 11 |
+
/*const size_t nb00,*/ const size_t nb01, const size_t nb02, const size_t nb03,
|
| 12 |
+
const size_t s10, const size_t s11, const size_t s12/*, const size_t s13*/) {
|
| 13 |
+
|
| 14 |
+
ggml_cuda_pdl_sync();
|
| 15 |
+
for (int64_t z = blockIdx.z; z < ne11*(int64_t)ne12_fdv.z; z += gridDim.z) {
|
| 16 |
+
for (int64_t i00 = 2*(blockIdx.y*blockDim.x + threadIdx.x); i00 < ne00; i00 += gridDim.y*blockDim.x) {
|
| 17 |
+
// The x and y dimensions of the grid are swapped because the maximum allowed grid size for x is higher.
|
| 18 |
+
const int i10 = blockIdx.x;
|
| 19 |
+
const uint2 dm = fast_div_modulo((uint32_t)z, ne12_fdv);
|
| 20 |
+
const int i11 = dm.x;
|
| 21 |
+
const int i12 = dm.y;
|
| 22 |
+
|
| 23 |
+
const int i01 = src1[i10*s10 + i11*s11 + i12*s12];
|
| 24 |
+
|
| 25 |
+
dst_t * dst_row = dst + i10*s1 + i11*s2 + i12*s3;
|
| 26 |
+
const void * src0_row = (const char *) src0 + i01*nb01 + i11*nb02 + i12*nb03;
|
| 27 |
+
|
| 28 |
+
const int ib = i00/qk; // block index
|
| 29 |
+
const int iqs = (i00%qk)/qr; // quant index
|
| 30 |
+
const int iybs = i00 - i00%qk; // dst block start index
|
| 31 |
+
const int y_offset = qr == 1 ? 1 : qk/2;
|
| 32 |
+
|
| 33 |
+
// dequantize
|
| 34 |
+
float2 v;
|
| 35 |
+
dequantize_kernel(src0_row, ib, iqs, v);
|
| 36 |
+
|
| 37 |
+
dst_row[iybs + iqs + 0] = ggml_cuda_cast<dst_t>(v.x);
|
| 38 |
+
dst_row[iybs + iqs + y_offset] = ggml_cuda_cast<dst_t>(v.y);
|
| 39 |
+
}
|
| 40 |
+
}
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
template<typename src0_t, typename dst_t>
|
| 44 |
+
static __global__ void k_get_rows_float(
|
| 45 |
+
const src0_t * src0_ptr, const int32_t * src1_ptr, dst_t * dst_ptr,
|
| 46 |
+
const int64_t ne00, /*const int64_t ne01, const int64_t ne02, const int64_t ne03,*/
|
| 47 |
+
/*const int64_t ne10,*/ const int64_t ne11, const uint3 ne12_fdv, /*const int64_t ne13,*/
|
| 48 |
+
/*const size_t s0,*/ const size_t s1, const size_t s2, const size_t s3,
|
| 49 |
+
/*const size_t nb00,*/ const size_t nb01, const size_t nb02, const size_t nb03,
|
| 50 |
+
const size_t s10, const size_t s11, const size_t s12/*, const size_t s13*/) {
|
| 51 |
+
|
| 52 |
+
ggml_cuda_pdl_lc();
|
| 53 |
+
const src0_t * GGML_CUDA_RESTRICT src0 = src0_ptr;
|
| 54 |
+
const int32_t * GGML_CUDA_RESTRICT src1 = src1_ptr;
|
| 55 |
+
dst_t * GGML_CUDA_RESTRICT dst = dst_ptr;
|
| 56 |
+
ggml_cuda_pdl_sync();
|
| 57 |
+
for (int64_t z = blockIdx.z; z < ne11*(int64_t)ne12_fdv.z; z += gridDim.z) {
|
| 58 |
+
for (int64_t i00 = blockIdx.y*blockDim.x + threadIdx.x; i00 < ne00; i00 += gridDim.y*blockDim.x) {
|
| 59 |
+
// The x and y dimensions of the grid are swapped because the maximum allowed grid size for x is higher.
|
| 60 |
+
const int i10 = blockIdx.x;
|
| 61 |
+
const uint2 dm = fast_div_modulo((uint32_t)z, ne12_fdv);
|
| 62 |
+
const int i11 = dm.x;
|
| 63 |
+
const int i12 = dm.y;
|
| 64 |
+
|
| 65 |
+
if (i00 >= ne00) {
|
| 66 |
+
return;
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
const int i01 = src1[i10*s10 + i11*s11 + i12*s12];
|
| 70 |
+
|
| 71 |
+
dst_t * dst_row = dst + i10*s1 + i11*s2 + i12*s3;
|
| 72 |
+
const src0_t * src0_row = (const src0_t *)((const char *) src0 + i01*nb01 + i11*nb02 + i12*nb03);
|
| 73 |
+
|
| 74 |
+
dst_row[i00] = ggml_cuda_cast<dst_t>(src0_row[i00]);
|
| 75 |
+
}
|
| 76 |
+
}
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
template<typename grad_t, typename dst_t>
|
| 80 |
+
static __global__ void k_get_rows_back_float(
|
| 81 |
+
const grad_t * __restrict__ grad, const int32_t * __restrict__ rows, dst_t * __restrict__ dst,
|
| 82 |
+
const int64_t ncols, const int64_t nrows_grad, const int64_t nrows_dst) {
|
| 83 |
+
const int col = blockIdx.x*blockDim.x + threadIdx.x;
|
| 84 |
+
|
| 85 |
+
if (col >= ncols) {
|
| 86 |
+
return;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
ggml_cuda_pdl_sync();
|
| 90 |
+
|
| 91 |
+
// grid.y is clamped to the CUDA grid limit, so stride over the destination rows
|
| 92 |
+
for (int64_t dst_row = blockIdx.y; dst_row < nrows_dst; dst_row += gridDim.y) {
|
| 93 |
+
float sum = 0.0f;
|
| 94 |
+
|
| 95 |
+
for (int64_t i = 0; i < nrows_grad; ++i) {
|
| 96 |
+
if (rows[i] != dst_row) {
|
| 97 |
+
continue;
|
| 98 |
+
}
|
| 99 |
+
sum += grad[i*ncols + col];
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
dst[dst_row*ncols + col] = sum;
|
| 103 |
+
}
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
template<int qk, int qr, dequantize_kernel_t dq, typename dst_t>
|
| 107 |
+
static void get_rows_cuda_q(
|
| 108 |
+
const void * src0_d, const int32_t * src1_d, dst_t * dst_d,
|
| 109 |
+
const int64_t ne00, const size_t nb01, const size_t nb02, const size_t nb03,
|
| 110 |
+
const int64_t ne10, const int64_t ne11, const int64_t ne12, const size_t nb10, const size_t nb11, const size_t nb12,
|
| 111 |
+
const size_t nb1, const size_t nb2, const size_t nb3,
|
| 112 |
+
cudaStream_t stream) {
|
| 113 |
+
const dim3 block_dims(CUDA_GET_ROWS_BLOCK_SIZE, 1, 1);
|
| 114 |
+
const int block_num_y = (ne00 + 2*CUDA_GET_ROWS_BLOCK_SIZE - 1) / (2*CUDA_GET_ROWS_BLOCK_SIZE);
|
| 115 |
+
const dim3 block_nums(ne10, MIN(block_num_y, UINT16_MAX), MIN(ne11*ne12, UINT16_MAX));
|
| 116 |
+
|
| 117 |
+
// strides in elements
|
| 118 |
+
// const size_t s0 = nb0 / sizeof(dst_t);
|
| 119 |
+
const size_t s1 = nb1 / sizeof(dst_t);
|
| 120 |
+
const size_t s2 = nb2 / sizeof(dst_t);
|
| 121 |
+
const size_t s3 = nb3 / sizeof(dst_t);
|
| 122 |
+
|
| 123 |
+
const size_t s10 = nb10 / sizeof(int32_t);
|
| 124 |
+
const size_t s11 = nb11 / sizeof(int32_t);
|
| 125 |
+
const size_t s12 = nb12 / sizeof(int32_t);
|
| 126 |
+
// const size_t s13 = nb13 / sizeof(int32_t);
|
| 127 |
+
|
| 128 |
+
GGML_ASSERT(ne00 % 2 == 0);
|
| 129 |
+
|
| 130 |
+
GGML_ASSERT(ne12 > 0);
|
| 131 |
+
GGML_ASSERT(ne11 <= std::numeric_limits<uint32_t>::max() / ne12);
|
| 132 |
+
const uint3 ne12_fdv = init_fastdiv_values(ne12);
|
| 133 |
+
|
| 134 |
+
k_get_rows<qk, qr, dq><<<block_nums, block_dims, 0, stream>>>(
|
| 135 |
+
src0_d, src1_d, dst_d,
|
| 136 |
+
ne00, /*ne01, ne02, ne03,*/
|
| 137 |
+
/*ne10,*/ ne11, ne12_fdv, /*ne13,*/
|
| 138 |
+
/* s0,*/ s1, s2, s3,
|
| 139 |
+
/* nb00,*/ nb01, nb02, nb03,
|
| 140 |
+
s10, s11, s12/*, s13*/);
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
template<typename src0_t, typename dst_t>
|
| 144 |
+
static void get_rows_cuda_float(
|
| 145 |
+
const src0_t * src0_d, const int32_t * src1_d, dst_t * dst_d,
|
| 146 |
+
const int64_t ne00, const size_t nb01, const size_t nb02, const size_t nb03,
|
| 147 |
+
const int64_t ne10, const int64_t ne11, const int64_t ne12, const size_t nb10, const size_t nb11, const size_t nb12,
|
| 148 |
+
const size_t nb1, const size_t nb2, const size_t nb3,
|
| 149 |
+
cudaStream_t stream) {
|
| 150 |
+
const dim3 block_dims(CUDA_GET_ROWS_BLOCK_SIZE, 1, 1);
|
| 151 |
+
const int block_num_y = (ne00 + CUDA_GET_ROWS_BLOCK_SIZE - 1) / CUDA_GET_ROWS_BLOCK_SIZE;
|
| 152 |
+
const dim3 block_nums(ne10, MIN(block_num_y, UINT16_MAX), MIN(ne11*ne12, UINT16_MAX));
|
| 153 |
+
|
| 154 |
+
// strides in elements
|
| 155 |
+
// const size_t s0 = nb0 / sizeof(dst_t);
|
| 156 |
+
const size_t s1 = nb1 / sizeof(dst_t);
|
| 157 |
+
const size_t s2 = nb2 / sizeof(dst_t);
|
| 158 |
+
const size_t s3 = nb3 / sizeof(dst_t);
|
| 159 |
+
|
| 160 |
+
const size_t s10 = nb10 / sizeof(int32_t);
|
| 161 |
+
const size_t s11 = nb11 / sizeof(int32_t);
|
| 162 |
+
const size_t s12 = nb12 / sizeof(int32_t);
|
| 163 |
+
// const size_t s13 = nb13 / sizeof(int32_t);
|
| 164 |
+
|
| 165 |
+
GGML_ASSERT(ne12 > 0);
|
| 166 |
+
GGML_ASSERT(ne11 <= std::numeric_limits<uint32_t>::max() / ne12);
|
| 167 |
+
const uint3 ne12_fdv = init_fastdiv_values(ne12);
|
| 168 |
+
|
| 169 |
+
const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params{block_nums, block_dims, 0, stream};
|
| 170 |
+
ggml_cuda_kernel_launch(k_get_rows_float<src0_t, dst_t>, launch_params,
|
| 171 |
+
src0_d, src1_d, dst_d,
|
| 172 |
+
ne00, /*ne01, ne02, ne03,*/
|
| 173 |
+
/*ne10,*/ ne11, ne12_fdv, /*ne13,*/
|
| 174 |
+
/* s0,*/ s1, s2, s3,
|
| 175 |
+
/* nb00,*/ nb01, nb02, nb03,
|
| 176 |
+
s10, s11, s12/*, s13*/);
|
| 177 |
+
}
|
| 178 |
+
|
| 179 |
+
template <typename dst_t>
|
| 180 |
+
static void ggml_cuda_get_rows_switch_src0_type(
|
| 181 |
+
const void * src0_d, const ggml_type src0_type, const int32_t * src1_d, dst_t * dst_d,
|
| 182 |
+
const int64_t ne00, const size_t nb01, const size_t nb02, const size_t nb03,
|
| 183 |
+
const int64_t ne10, const int64_t ne11, const int64_t ne12, const size_t nb10, const size_t nb11, const size_t nb12,
|
| 184 |
+
const size_t nb1, const size_t nb2, const size_t nb3,
|
| 185 |
+
cudaStream_t stream) {
|
| 186 |
+
switch (src0_type) {
|
| 187 |
+
case GGML_TYPE_F16:
|
| 188 |
+
get_rows_cuda_float((const half *) src0_d, src1_d, dst_d,
|
| 189 |
+
ne00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb1, nb2, nb3, stream);
|
| 190 |
+
break;
|
| 191 |
+
case GGML_TYPE_F32:
|
| 192 |
+
get_rows_cuda_float((const float *) src0_d, src1_d, dst_d,
|
| 193 |
+
ne00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb1, nb2, nb3, stream);
|
| 194 |
+
break;
|
| 195 |
+
case GGML_TYPE_I32:
|
| 196 |
+
get_rows_cuda_float((const int32_t *) src0_d, src1_d, dst_d,
|
| 197 |
+
ne00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb1, nb2, nb3, stream);
|
| 198 |
+
break;
|
| 199 |
+
case GGML_TYPE_BF16:
|
| 200 |
+
get_rows_cuda_float((const nv_bfloat16 *) src0_d, src1_d, dst_d,
|
| 201 |
+
ne00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb1, nb2, nb3, stream);
|
| 202 |
+
break;
|
| 203 |
+
case GGML_TYPE_Q1_0:
|
| 204 |
+
get_rows_cuda_q<QK1_0, QR1_0, dequantize_q1_0>(src0_d, src1_d, dst_d,
|
| 205 |
+
ne00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb1, nb2, nb3, stream);
|
| 206 |
+
break;
|
| 207 |
+
case GGML_TYPE_Q4_0:
|
| 208 |
+
get_rows_cuda_q<QK4_0, QR4_0, dequantize_q4_0>(src0_d, src1_d, dst_d,
|
| 209 |
+
ne00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb1, nb2, nb3, stream);
|
| 210 |
+
break;
|
| 211 |
+
case GGML_TYPE_Q4_1:
|
| 212 |
+
get_rows_cuda_q<QK4_1, QR4_1, dequantize_q4_1>(src0_d, src1_d, dst_d,
|
| 213 |
+
ne00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb1, nb2, nb3, stream);
|
| 214 |
+
break;
|
| 215 |
+
case GGML_TYPE_Q5_0:
|
| 216 |
+
get_rows_cuda_q<QK5_0, QR5_0, dequantize_q5_0>(src0_d, src1_d, dst_d,
|
| 217 |
+
ne00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb1, nb2, nb3, stream);
|
| 218 |
+
break;
|
| 219 |
+
case GGML_TYPE_Q5_1:
|
| 220 |
+
get_rows_cuda_q<QK5_1, QR5_1, dequantize_q5_1>(src0_d, src1_d, dst_d,
|
| 221 |
+
ne00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb1, nb2, nb3, stream);
|
| 222 |
+
break;
|
| 223 |
+
case GGML_TYPE_Q8_0:
|
| 224 |
+
get_rows_cuda_q<QK8_0, QR8_0, dequantize_q8_0>(src0_d, src1_d, dst_d,
|
| 225 |
+
ne00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb1, nb2, nb3, stream);
|
| 226 |
+
break;
|
| 227 |
+
default:
|
| 228 |
+
// TODO: k-quants
|
| 229 |
+
GGML_ABORT("%s: unsupported src0 type: %s\n", __func__, ggml_type_name(src0_type));
|
| 230 |
+
break;
|
| 231 |
+
}
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
+
void get_rows_cuda(
|
| 235 |
+
const void * src0_d, ggml_type src0_type, const int32_t * src1_d, void * dst_d, ggml_type dst_type,
|
| 236 |
+
int64_t ne00, size_t nb01, size_t nb02, size_t nb03,
|
| 237 |
+
int64_t ne10, int64_t ne11, int64_t ne12, size_t nb10, size_t nb11, size_t nb12,
|
| 238 |
+
size_t nb1, size_t nb2, size_t nb3,
|
| 239 |
+
cudaStream_t stream) {
|
| 240 |
+
switch (dst_type) {
|
| 241 |
+
case GGML_TYPE_F32:
|
| 242 |
+
ggml_cuda_get_rows_switch_src0_type(src0_d, src0_type, src1_d, (float *) dst_d,
|
| 243 |
+
ne00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb1, nb2, nb3, stream);
|
| 244 |
+
break;
|
| 245 |
+
case GGML_TYPE_I32:
|
| 246 |
+
ggml_cuda_get_rows_switch_src0_type(src0_d, src0_type, src1_d, (int32_t *) dst_d,
|
| 247 |
+
ne00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb1, nb2, nb3, stream);
|
| 248 |
+
break;
|
| 249 |
+
case GGML_TYPE_F16:
|
| 250 |
+
ggml_cuda_get_rows_switch_src0_type(src0_d, src0_type, src1_d, (half *) dst_d,
|
| 251 |
+
ne00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb1, nb2, nb3, stream);
|
| 252 |
+
break;
|
| 253 |
+
case GGML_TYPE_BF16:
|
| 254 |
+
ggml_cuda_get_rows_switch_src0_type(src0_d, src0_type, src1_d, (nv_bfloat16 *) dst_d,
|
| 255 |
+
ne00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb1, nb2, nb3, stream);
|
| 256 |
+
break;
|
| 257 |
+
default:
|
| 258 |
+
GGML_ABORT("%s: unsupported dst type: %s\n", __func__, ggml_type_name(dst_type));
|
| 259 |
+
break;
|
| 260 |
+
}
|
| 261 |
+
}
|
| 262 |
+
|
| 263 |
+
void ggml_cuda_op_get_rows(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 264 |
+
const ggml_tensor * src0 = dst->src[0];
|
| 265 |
+
const ggml_tensor * src1 = dst->src[1];
|
| 266 |
+
|
| 267 |
+
cudaStream_t stream = ctx.stream();
|
| 268 |
+
|
| 269 |
+
GGML_TENSOR_BINARY_OP_LOCALS
|
| 270 |
+
|
| 271 |
+
GGML_ASSERT(src1->type == GGML_TYPE_I32);
|
| 272 |
+
GGML_ASSERT(ne13 == 1);
|
| 273 |
+
|
| 274 |
+
GGML_ASSERT(src0->nb[0] == ggml_type_size(src0->type));
|
| 275 |
+
GGML_ASSERT(src1->nb[0] == ggml_type_size(src1->type));
|
| 276 |
+
GGML_ASSERT(dst->nb[0] == ggml_type_size(dst->type));
|
| 277 |
+
|
| 278 |
+
get_rows_cuda(src0->data, src0->type, (const int32_t *) src1->data, dst->data, dst->type,
|
| 279 |
+
ne00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb1, nb2, nb3, stream);
|
| 280 |
+
}
|
| 281 |
+
|
| 282 |
+
void ggml_cuda_op_get_rows_back(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 283 |
+
const ggml_tensor * src0 = dst->src[0]; // gradients of forward pass output
|
| 284 |
+
const ggml_tensor * src1 = dst->src[1]; // src1 in forward pass
|
| 285 |
+
|
| 286 |
+
GGML_TENSOR_BINARY_OP_LOCALS
|
| 287 |
+
|
| 288 |
+
const float * src0_d = (const float *) src0->data;
|
| 289 |
+
const int32_t * src1_d = (const int32_t *) src1->data;
|
| 290 |
+
float * dst_d = (float *) dst->data;
|
| 291 |
+
|
| 292 |
+
cudaStream_t stream = ctx.stream();
|
| 293 |
+
|
| 294 |
+
GGML_ASSERT(src0->type == GGML_TYPE_F32);
|
| 295 |
+
GGML_ASSERT(src1->type == GGML_TYPE_I32);
|
| 296 |
+
GGML_ASSERT(dst->type == GGML_TYPE_F32);
|
| 297 |
+
|
| 298 |
+
GGML_ASSERT(ggml_is_contiguous(src0));
|
| 299 |
+
GGML_ASSERT(ggml_is_contiguous(src1));
|
| 300 |
+
GGML_ASSERT(ggml_is_contiguous(dst));
|
| 301 |
+
|
| 302 |
+
GGML_ASSERT(ne02*ne03 == 1);
|
| 303 |
+
GGML_ASSERT(ne12*ne13 == 1);
|
| 304 |
+
GGML_ASSERT(ne2*ne3 == 1);
|
| 305 |
+
|
| 306 |
+
const dim3 block_dims(CUDA_GET_ROWS_BACK_BLOCK_SIZE, 1, 1);
|
| 307 |
+
const int block_num_x = (ne00 + CUDA_GET_ROWS_BACK_BLOCK_SIZE - 1) / CUDA_GET_ROWS_BACK_BLOCK_SIZE;
|
| 308 |
+
const dim3 block_nums(block_num_x, MIN(ne1, (int64_t)UINT16_MAX), 1);
|
| 309 |
+
|
| 310 |
+
k_get_rows_back_float<<<block_nums, block_dims, 0, stream>>>(src0_d, src1_d, dst_d, ne00, ne10, ne1);
|
| 311 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/getrows.cuh
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
|
| 3 |
+
#define CUDA_GET_ROWS_BLOCK_SIZE 256
|
| 4 |
+
#define CUDA_GET_ROWS_BACK_BLOCK_SIZE 256
|
| 5 |
+
|
| 6 |
+
void get_rows_cuda(
|
| 7 |
+
const void * src0_d, ggml_type src0_type, const int32_t * src1_d, void * dst_d, ggml_type dst_type,
|
| 8 |
+
int64_t ne00, size_t nb01, size_t nb02, size_t nb03,
|
| 9 |
+
int64_t ne10, int64_t ne11, int64_t ne12, size_t nb10, size_t nb11, size_t nb12,
|
| 10 |
+
size_t nb1, size_t nb2, size_t nb3,
|
| 11 |
+
cudaStream_t stream);
|
| 12 |
+
|
| 13 |
+
void ggml_cuda_op_get_rows(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
| 14 |
+
|
| 15 |
+
void ggml_cuda_op_get_rows_back(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
backend/llama.cpp/ggml/src/ggml-cuda/ggml-cuda.cu
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
backend/llama.cpp/ggml/src/ggml-cuda/gla.cu
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
#include "gla.cuh"
|
| 3 |
+
|
| 4 |
+
template<int HEAD_SIZE>
|
| 5 |
+
static __global__ void gated_linear_attn_f32(const int B, const int T, const int C, const int H, const float scale,
|
| 6 |
+
const float * k, const float * v, const float * r, const float * td, const float * s, float * dst) {
|
| 7 |
+
const int tid = threadIdx.x;
|
| 8 |
+
const int bid = blockIdx.x;
|
| 9 |
+
|
| 10 |
+
const int head_size = HEAD_SIZE;
|
| 11 |
+
const int batch_i = bid / H;
|
| 12 |
+
const int head_i = bid % H;
|
| 13 |
+
const int state_size = C * head_size;
|
| 14 |
+
const int n_seq_tokens = T / B;
|
| 15 |
+
|
| 16 |
+
float state[head_size];
|
| 17 |
+
__shared__ float _k[head_size], _r[head_size], _td[head_size];
|
| 18 |
+
|
| 19 |
+
#pragma unroll
|
| 20 |
+
for (int i = 0; i < head_size; i++) {
|
| 21 |
+
state[i] = s[batch_i * state_size + head_i * head_size * head_size + i * head_size + tid];
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
for (int t = batch_i * n_seq_tokens * C + head_i * head_size + tid; t < (batch_i + 1) * n_seq_tokens * C + head_i * head_size + tid; t += C) {
|
| 25 |
+
__syncthreads();
|
| 26 |
+
_k[tid] = k[t];
|
| 27 |
+
_r[tid] = r[t];
|
| 28 |
+
_td[tid] = td[t];
|
| 29 |
+
__syncthreads();
|
| 30 |
+
|
| 31 |
+
const float _v = v[t];
|
| 32 |
+
float y = 0;
|
| 33 |
+
for (int j = 0; j < head_size; j += 4) {
|
| 34 |
+
const float4 & k = (float4 &)(_k[j]);
|
| 35 |
+
const float4 & r = (float4 &)(_r[j]);
|
| 36 |
+
const float4 & td = (float4 &)(_td[j]);
|
| 37 |
+
float4 & s = (float4 &)(state[j]);
|
| 38 |
+
float4 kv;
|
| 39 |
+
|
| 40 |
+
kv.x = k.x * _v;
|
| 41 |
+
kv.y = k.y * _v;
|
| 42 |
+
kv.z = k.z * _v;
|
| 43 |
+
kv.w = k.w * _v;
|
| 44 |
+
|
| 45 |
+
s.x = s.x * td.x + kv.x;
|
| 46 |
+
s.y = s.y * td.y + kv.y;
|
| 47 |
+
s.z = s.z * td.z + kv.z;
|
| 48 |
+
s.w = s.w * td.w + kv.w;
|
| 49 |
+
|
| 50 |
+
y += r.x * s.x;
|
| 51 |
+
y += r.y * s.y;
|
| 52 |
+
y += r.z * s.z;
|
| 53 |
+
y += r.w * s.w;
|
| 54 |
+
}
|
| 55 |
+
dst[t] = y * scale;
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
#pragma unroll
|
| 59 |
+
for (int i = 0; i < head_size; i++) {
|
| 60 |
+
dst[T * C + batch_i * state_size + head_i * head_size * head_size + i * head_size + tid] = state[i];
|
| 61 |
+
}
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
void ggml_cuda_op_gated_linear_attn(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 65 |
+
const float * k_d = (const float *)dst->src[0]->data;
|
| 66 |
+
const float * v_d = (const float *)dst->src[1]->data;
|
| 67 |
+
const float * r_d = (const float *)dst->src[2]->data;
|
| 68 |
+
const float * td_d = (const float *)dst->src[3]->data;
|
| 69 |
+
const float * s_d = (const float *)dst->src[4]->data;
|
| 70 |
+
|
| 71 |
+
const int64_t B = dst->src[4]->ne[1];
|
| 72 |
+
const int64_t T = dst->src[0]->ne[2];
|
| 73 |
+
const int64_t C = dst->ne[0];
|
| 74 |
+
const int64_t H = dst->src[0]->ne[1];
|
| 75 |
+
|
| 76 |
+
float scale;
|
| 77 |
+
memcpy(&scale, (float*)dst->op_params, sizeof(float));
|
| 78 |
+
|
| 79 |
+
float * dst_d = (float *)dst->data;
|
| 80 |
+
|
| 81 |
+
cudaStream_t stream = ctx.stream();
|
| 82 |
+
|
| 83 |
+
GGML_ASSERT(dst->src[4]->type == GGML_TYPE_F32);
|
| 84 |
+
GGML_ASSERT(C % H == 0);
|
| 85 |
+
GGML_ASSERT(C / H == 64 || C / H == 128);
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
if (C / H == 64) {
|
| 89 |
+
gated_linear_attn_f32<64><<<B * H, C / H, 0, stream>>>(B, T, C, H, scale, k_d, v_d, r_d, td_d, s_d, dst_d);
|
| 90 |
+
} else {
|
| 91 |
+
gated_linear_attn_f32<128><<<B * H, C / H, 0, stream>>>(B, T, C, H, scale, k_d, v_d, r_d, td_d, s_d, dst_d);
|
| 92 |
+
}
|
| 93 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/gla.cuh
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
|
| 3 |
+
void ggml_cuda_op_gated_linear_attn(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
backend/llama.cpp/ggml/src/ggml-cuda/im2col.cu
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "im2col.cuh"
|
| 2 |
+
|
| 3 |
+
#define MAX_GRIDDIM_Y 65535
|
| 4 |
+
#define MAX_GRIDDIM_Z 65535
|
| 5 |
+
|
| 6 |
+
template <typename T>
|
| 7 |
+
static __global__ void im2col_kernel(
|
| 8 |
+
const float * x, T * dst,
|
| 9 |
+
int64_t IC, int64_t IW, int64_t IH, int64_t OH, int64_t OW, int64_t KW, int64_t KH,
|
| 10 |
+
int64_t IC_IH_IW, int64_t IH_IW, int64_t N_OH, int64_t KH_KW, int64_t IC_KH_KW,
|
| 11 |
+
int s0, int s1, int p0, int p1, int d0, int d1) {
|
| 12 |
+
const int64_t i = threadIdx.x + blockIdx.x * blockDim.x;
|
| 13 |
+
if (i >= IC_KH_KW) {
|
| 14 |
+
return;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
const int64_t iic = i / (KH_KW);
|
| 18 |
+
const int64_t rem = i - iic * KH_KW;
|
| 19 |
+
const int64_t ikh = rem / KW;
|
| 20 |
+
const int64_t ikw = rem - ikh * KW;
|
| 21 |
+
|
| 22 |
+
for (int64_t iow = blockIdx.y; iow < OW; iow += MAX_GRIDDIM_Y) {
|
| 23 |
+
for (int64_t iz = blockIdx.z; iz < N_OH; iz += MAX_GRIDDIM_Z) {
|
| 24 |
+
const int64_t in = iz / OH;
|
| 25 |
+
const int64_t ioh = iz - in * OH;
|
| 26 |
+
|
| 27 |
+
const int64_t iiw = iow * s0 + ikw * d0 - p0;
|
| 28 |
+
const int64_t iih = ioh * s1 + ikh * d1 - p1;
|
| 29 |
+
|
| 30 |
+
const int64_t offset_dst =
|
| 31 |
+
((in * OH + ioh) * OW + iow) * IC_KH_KW + iic * KH_KW + ikh * KW + ikw;
|
| 32 |
+
|
| 33 |
+
if (iih < 0 || iih >= IH || iiw < 0 || iiw >= IW) {
|
| 34 |
+
dst[offset_dst] = 0.0f;
|
| 35 |
+
} else {
|
| 36 |
+
const int64_t offset_src = iic * IC_IH_IW + in * IH_IW;
|
| 37 |
+
dst[offset_dst] = x[offset_src + iih * IW + iiw];
|
| 38 |
+
}
|
| 39 |
+
}
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
GGML_UNUSED(IC);
|
| 43 |
+
GGML_UNUSED(KH);
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
// im2col: [N, IC, IH, IW] => [N, OH, OW, IC*KH*KW]
|
| 47 |
+
template <typename T>
|
| 48 |
+
static void im2col_cuda(const float * x, T* dst,
|
| 49 |
+
int64_t IW, int64_t IH, int64_t OW, int64_t OH, int64_t KW, int64_t KH, int64_t IC,
|
| 50 |
+
int64_t N, int64_t IC_IH_IW, int64_t IH_IW,
|
| 51 |
+
int s0,int s1,int p0,int p1,int d0,int d1, cudaStream_t stream) {
|
| 52 |
+
const int64_t IC_KH_KW = IC * KH * KW;
|
| 53 |
+
const int64_t num_blocks = (IC_KH_KW + CUDA_IM2COL_BLOCK_SIZE - 1) / CUDA_IM2COL_BLOCK_SIZE;
|
| 54 |
+
const int64_t N_OH = N * OH;
|
| 55 |
+
const int64_t KH_KW = KW*KH;
|
| 56 |
+
dim3 block_nums(num_blocks, MIN(OW, MAX_GRIDDIM_Y), MIN(N_OH, MAX_GRIDDIM_Z));
|
| 57 |
+
im2col_kernel<<<block_nums, MIN(IC_KH_KW, CUDA_IM2COL_BLOCK_SIZE) , 0, stream>>>(x, dst, IC, IW, IH, OH, OW, KW, KH,
|
| 58 |
+
IC_IH_IW, IH_IW, N_OH, KH_KW, IC_KH_KW,
|
| 59 |
+
s0, s1, p0, p1, d0, d1);
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
static void im2col_cuda_f16(const float * x, half * dst,
|
| 63 |
+
int64_t IW, int64_t IH, int64_t OW, int64_t OH, int64_t KW, int64_t KH, int64_t IC,
|
| 64 |
+
int64_t N, int64_t IC_IH_IW, int64_t IH_IW,
|
| 65 |
+
int s0,int s1,int p0,int p1,int d0,int d1, cudaStream_t stream) {
|
| 66 |
+
|
| 67 |
+
im2col_cuda<half>(x, dst, IW, IH, OW, OH, KW, KH, IC, N, IC_IH_IW, IH_IW, s0, s1, p0, p1, d0, d1, stream);
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
static void im2col_cuda_f32(const float * x, float * dst,
|
| 71 |
+
int64_t IW, int64_t IH, int64_t OW, int64_t OH, int64_t KW, int64_t KH, int64_t IC,
|
| 72 |
+
int64_t N, int64_t IC_IH_IW, int64_t IH_IW,
|
| 73 |
+
int s0,int s1,int p0,int p1,int d0,int d1, cudaStream_t stream) {
|
| 74 |
+
|
| 75 |
+
im2col_cuda<float>(x, dst, IW, IH, OW, OH, KW, KH, IC, N, IC_IH_IW, IH_IW, s0, s1, p0, p1, d0, d1, stream);
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
void ggml_cuda_op_im2col(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 79 |
+
const ggml_tensor * src0 = dst->src[0];
|
| 80 |
+
const ggml_tensor * src1 = dst->src[1];
|
| 81 |
+
const float * src1_d = (const float *)src1->data;
|
| 82 |
+
float * dst_d = (float *)dst->data;
|
| 83 |
+
cudaStream_t stream = ctx.stream();
|
| 84 |
+
|
| 85 |
+
GGML_ASSERT(src1->type == GGML_TYPE_F32);
|
| 86 |
+
GGML_ASSERT( dst->type == GGML_TYPE_F16 || dst->type == GGML_TYPE_F32);
|
| 87 |
+
|
| 88 |
+
const int32_t s0 = ((const int32_t*)(dst->op_params))[0];
|
| 89 |
+
const int32_t s1 = ((const int32_t*)(dst->op_params))[1];
|
| 90 |
+
const int32_t p0 = ((const int32_t*)(dst->op_params))[2];
|
| 91 |
+
const int32_t p1 = ((const int32_t*)(dst->op_params))[3];
|
| 92 |
+
const int32_t d0 = ((const int32_t*)(dst->op_params))[4];
|
| 93 |
+
const int32_t d1 = ((const int32_t*)(dst->op_params))[5];
|
| 94 |
+
|
| 95 |
+
const bool is_2D = ((const int32_t*)(dst->op_params))[6] == 1;
|
| 96 |
+
|
| 97 |
+
const int64_t IC = src1->ne[is_2D ? 2 : 1];
|
| 98 |
+
const int64_t IH = is_2D ? src1->ne[1] : 1;
|
| 99 |
+
const int64_t IW = src1->ne[0];
|
| 100 |
+
|
| 101 |
+
const int64_t KH = is_2D ? src0->ne[1] : 1;
|
| 102 |
+
const int64_t KW = src0->ne[0];
|
| 103 |
+
|
| 104 |
+
const int64_t OH = is_2D ? dst->ne[2] : 1;
|
| 105 |
+
const int64_t OW = dst->ne[1];
|
| 106 |
+
|
| 107 |
+
const int64_t IC_IH_IW = src1->nb[is_2D ? 2 : 1] / 4; // nb is byte offset, src is type float32
|
| 108 |
+
const int64_t N = src1->ne[is_2D ? 3 : 2];
|
| 109 |
+
const int64_t IH_IW = src1->nb[is_2D ? 3 : 2] / 4; // nb is byte offset, src is type float32
|
| 110 |
+
|
| 111 |
+
if(dst->type == GGML_TYPE_F16) {
|
| 112 |
+
im2col_cuda_f16(src1_d, (half *) dst_d, IW, IH, OW, OH, KW, KH, IC, N, IC_IH_IW, IH_IW, s0, s1, p0, p1, d0, d1, stream);
|
| 113 |
+
} else {
|
| 114 |
+
im2col_cuda_f32(src1_d, (float *) dst_d, IW, IH, OW, OH, KW, KH, IC, N, IC_IH_IW, IH_IW, s0, s1, p0, p1, d0, d1, stream);
|
| 115 |
+
}
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
// [N*IC, ID, IH, IW] => [N*OD, OH, OW, IC * KD * KH * KW]
|
| 119 |
+
template <typename T>
|
| 120 |
+
static __global__ void im2col_3d_kernel(
|
| 121 |
+
const float * src, T * dst,
|
| 122 |
+
int64_t N, int64_t IC, int64_t ID, int64_t IH, int64_t IW, int64_t OC,
|
| 123 |
+
int64_t KD, int64_t KH, int64_t KW, int64_t OD, int64_t OH, int64_t OW,
|
| 124 |
+
int64_t OH_OW, int64_t KD_KH_KW, int64_t ID_IH_IW, int64_t KH_KW, int64_t IH_IW, int64_t IC_ID_IH_IW,
|
| 125 |
+
int64_t IC_KD_KH_KW, int64_t OW_KD_KH_KW, int64_t OD_OH_OW_IC_KD_KH_KW, int64_t OH_OW_IC_KD_KH_KW,
|
| 126 |
+
int64_t OW_IC_KD_KH_KW, int64_t N_OD_OH, int64_t OD_OH,
|
| 127 |
+
int64_t stride_q, int64_t stride_z, int64_t stride_y, int64_t stride_x,
|
| 128 |
+
int s0, int s1, int s2, int p0, int p1, int p2, int d0, int d1, int d2) {
|
| 129 |
+
const int64_t i = threadIdx.x + blockIdx.x * blockDim.x;
|
| 130 |
+
if (i >= IC_KD_KH_KW) {
|
| 131 |
+
return;
|
| 132 |
+
}
|
| 133 |
+
GGML_UNUSED(N); GGML_UNUSED(OC); GGML_UNUSED(OH_OW); GGML_UNUSED(OD); GGML_UNUSED(OW); GGML_UNUSED(KD); GGML_UNUSED(KH);
|
| 134 |
+
GGML_UNUSED(ID_IH_IW); GGML_UNUSED(IH_IW); GGML_UNUSED(IC_ID_IH_IW); GGML_UNUSED(OW_KD_KH_KW);
|
| 135 |
+
|
| 136 |
+
const int64_t iic = i / KD_KH_KW;
|
| 137 |
+
const int64_t ikd = (i - iic * KD_KH_KW) / KH_KW;
|
| 138 |
+
const int64_t ikh = (i - iic * KD_KH_KW - ikd * KH_KW) / KW;
|
| 139 |
+
const int64_t ikw = i % KW;
|
| 140 |
+
|
| 141 |
+
for (int64_t iow = blockIdx.y; iow < OW; iow += MAX_GRIDDIM_Y) {
|
| 142 |
+
for (int64_t iz = blockIdx.z; iz < N_OD_OH; iz += MAX_GRIDDIM_Z) {
|
| 143 |
+
const int64_t in = iz / OD_OH;
|
| 144 |
+
const int64_t iod = (iz - in*OD_OH) / OH;
|
| 145 |
+
const int64_t ioh = iz % OH;
|
| 146 |
+
|
| 147 |
+
const int64_t iiw = iow * s0 + ikw * d0 - p0;
|
| 148 |
+
const int64_t iih = ioh * s1 + ikh * d1 - p1;
|
| 149 |
+
const int64_t iid = iod * s2 + ikd * d2 - p2;
|
| 150 |
+
|
| 151 |
+
const int64_t offset_dst = in*OD_OH_OW_IC_KD_KH_KW + iod*OH_OW_IC_KD_KH_KW + ioh*OW_IC_KD_KH_KW + iow*IC_KD_KH_KW + iic*KD_KH_KW + ikd * KH_KW + ikh*KW + ikw;
|
| 152 |
+
|
| 153 |
+
if (iih < 0 || iih >= IH || iiw < 0 || iiw >= IW || iid < 0 || iid >= ID) {
|
| 154 |
+
dst[offset_dst] = 0.0f;
|
| 155 |
+
} else {
|
| 156 |
+
const int64_t offset_src = ((in * IC + iic) * stride_q) + (iid * stride_z) + (iih * stride_y) + (iiw * stride_x);
|
| 157 |
+
dst[offset_dst] = src[offset_src];
|
| 158 |
+
}
|
| 159 |
+
}
|
| 160 |
+
}
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
// [N*IC, ID, IH, IW] => [N*OD, OH, OW, IC * KD * KH * KW]
|
| 164 |
+
template <typename T>
|
| 165 |
+
static void im2col_3d_cuda(const float * src, T* dst,
|
| 166 |
+
int64_t N, int64_t IC, int64_t ID, int64_t IH, int64_t IW, int64_t OC,
|
| 167 |
+
int64_t KD, int64_t KH, int64_t KW, int64_t OD, int64_t OH, int64_t OW,
|
| 168 |
+
int64_t stride_q, int64_t stride_z, int64_t stride_y, int64_t stride_x,
|
| 169 |
+
int s0, int s1, int s2, int p0, int p1, int p2, int d0, int d1, int d2, cudaStream_t stream) {
|
| 170 |
+
const int64_t OH_OW = OH*OW;
|
| 171 |
+
const int64_t KD_KH_KW = KD*KH*KW;
|
| 172 |
+
const int64_t ID_IH_IW = ID*IH*IW;
|
| 173 |
+
const int64_t KH_KW = KH*KW;
|
| 174 |
+
const int64_t IH_IW = IH*IW;
|
| 175 |
+
const int64_t IC_KD_KH_KW = IC*KD*KH*KW;
|
| 176 |
+
const int64_t OW_KD_KH_KW = OW*KD*KH*KW;
|
| 177 |
+
const int64_t N_OD_OH = N*OD*OH;
|
| 178 |
+
const int64_t OD_OH = OD*OH;
|
| 179 |
+
const int64_t IC_ID_IH_IW = IC*ID*IH*IW;
|
| 180 |
+
const int64_t OD_OH_OW_IC_KD_KH_KW = OD*OH*OW*IC*KD*KH*KW;
|
| 181 |
+
const int64_t OH_OW_IC_KD_KH_KW = OH*OW*IC*KD*KH*KW;
|
| 182 |
+
const int64_t OW_IC_KD_KH_KW = OW*IC*KD*KH*KW;
|
| 183 |
+
const int64_t num_blocks = (IC_KD_KH_KW + CUDA_IM2COL_BLOCK_SIZE - 1) / CUDA_IM2COL_BLOCK_SIZE;
|
| 184 |
+
dim3 block_nums(num_blocks, MIN(OW, MAX_GRIDDIM_Y), MIN(N_OD_OH, MAX_GRIDDIM_Z));
|
| 185 |
+
im2col_3d_kernel<<<block_nums, MIN(IC_KD_KH_KW, CUDA_IM2COL_BLOCK_SIZE) , 0, stream>>>(src, dst, N, IC, ID, IH, IW, OC, KD, KH, KW, OD, OH, OW,
|
| 186 |
+
OH_OW, KD_KH_KW, ID_IH_IW, KH_KW, IH_IW, IC_ID_IH_IW,
|
| 187 |
+
IC_KD_KH_KW, OW_KD_KH_KW, OD_OH_OW_IC_KD_KH_KW,
|
| 188 |
+
OH_OW_IC_KD_KH_KW, OW_IC_KD_KH_KW, N_OD_OH, OD_OH,
|
| 189 |
+
stride_q, stride_z, stride_y, stride_x,
|
| 190 |
+
s0, s1, s2, p0, p1, p2, d0, d1, d2);
|
| 191 |
+
}
|
| 192 |
+
|
| 193 |
+
static void im2col_3d_cuda_f16(const float * src, half * dst,
|
| 194 |
+
int64_t N, int64_t IC, int64_t ID, int64_t IH, int64_t IW, int64_t OC,
|
| 195 |
+
int64_t KD, int64_t KH, int64_t KW, int64_t OD, int64_t OH, int64_t OW,
|
| 196 |
+
int64_t stride_q, int64_t stride_z, int64_t stride_y, int64_t stride_x,
|
| 197 |
+
int s0, int s1, int s2, int p0, int p1, int p2, int d0, int d1, int d2, cudaStream_t stream) {
|
| 198 |
+
|
| 199 |
+
im2col_3d_cuda<half>(src, dst, N, IC, ID, IH, IW, OC, KD, KH, KW, OD, OH, OW,
|
| 200 |
+
stride_q, stride_z, stride_y, stride_x,
|
| 201 |
+
s0, s1, s2, p0, p1, p2, d0, d1, d2, stream);
|
| 202 |
+
}
|
| 203 |
+
|
| 204 |
+
static void im2col_3d_cuda_f32(const float * src, float * dst,
|
| 205 |
+
int64_t N, int64_t IC, int64_t ID, int64_t IH, int64_t IW, int64_t OC,
|
| 206 |
+
int64_t KD, int64_t KH, int64_t KW, int64_t OD, int64_t OH, int64_t OW,
|
| 207 |
+
int64_t stride_q, int64_t stride_z, int64_t stride_y, int64_t stride_x,
|
| 208 |
+
int s0, int s1, int s2, int p0, int p1, int p2, int d0, int d1, int d2, cudaStream_t stream) {
|
| 209 |
+
|
| 210 |
+
im2col_3d_cuda<float>(src, dst, N, IC, ID, IH, IW, OC, KD, KH, KW, OD, OH, OW,
|
| 211 |
+
stride_q, stride_z, stride_y, stride_x,
|
| 212 |
+
s0, s1, s2, p0, p1, p2, d0, d1, d2, stream);
|
| 213 |
+
}
|
| 214 |
+
|
| 215 |
+
void ggml_cuda_op_im2col_3d(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 216 |
+
const ggml_tensor * src0 = dst->src[0];
|
| 217 |
+
const ggml_tensor * src1 = dst->src[1];
|
| 218 |
+
const float * src1_d = (const float *)src1->data;
|
| 219 |
+
float * dst_d = (float *)dst->data;
|
| 220 |
+
cudaStream_t stream = ctx.stream();
|
| 221 |
+
|
| 222 |
+
GGML_ASSERT(src1->type == GGML_TYPE_F32);
|
| 223 |
+
GGML_ASSERT( dst->type == GGML_TYPE_F16 || dst->type == GGML_TYPE_F32);
|
| 224 |
+
|
| 225 |
+
GGML_TENSOR_BINARY_OP_LOCALS
|
| 226 |
+
|
| 227 |
+
const int32_t s0 = ((const int32_t *)(dst->op_params))[0];
|
| 228 |
+
const int32_t s1 = ((const int32_t *)(dst->op_params))[1];
|
| 229 |
+
const int32_t s2 = ((const int32_t *)(dst->op_params))[2];
|
| 230 |
+
const int32_t p0 = ((const int32_t *)(dst->op_params))[3];
|
| 231 |
+
const int32_t p1 = ((const int32_t *)(dst->op_params))[4];
|
| 232 |
+
const int32_t p2 = ((const int32_t *)(dst->op_params))[5];
|
| 233 |
+
const int32_t d0 = ((const int32_t *)(dst->op_params))[6];
|
| 234 |
+
const int32_t d1 = ((const int32_t *)(dst->op_params))[7];
|
| 235 |
+
const int32_t d2 = ((const int32_t *)(dst->op_params))[8];
|
| 236 |
+
const int32_t IC = ((const int32_t *)(dst->op_params))[9];
|
| 237 |
+
|
| 238 |
+
const int64_t N = ne13 / IC;
|
| 239 |
+
const int64_t ID = ne12;
|
| 240 |
+
const int64_t IH = ne11;
|
| 241 |
+
const int64_t IW = ne10;
|
| 242 |
+
|
| 243 |
+
const int64_t OC = ne03 / IC;
|
| 244 |
+
const int64_t KD = ne02;
|
| 245 |
+
const int64_t KH = ne01;
|
| 246 |
+
const int64_t KW = ne00;
|
| 247 |
+
|
| 248 |
+
const int64_t OD = ne3 / N;
|
| 249 |
+
const int64_t OH = ne2;
|
| 250 |
+
const int64_t OW = ne1;
|
| 251 |
+
|
| 252 |
+
const size_t es = ggml_element_size(src1);
|
| 253 |
+
const int64_t stride_x = src1->nb[0] / es;
|
| 254 |
+
const int64_t stride_y = src1->nb[1] / es;
|
| 255 |
+
const int64_t stride_z = src1->nb[2] / es;
|
| 256 |
+
const int64_t stride_q = src1->nb[3] / es;
|
| 257 |
+
|
| 258 |
+
if(dst->type == GGML_TYPE_F16) {
|
| 259 |
+
im2col_3d_cuda_f16(src1_d, (half *) dst_d, N, IC, ID, IH, IW, OC, KD, KH, KW, OD, OH, OW,
|
| 260 |
+
stride_q, stride_z, stride_y, stride_x,
|
| 261 |
+
s0, s1, s2, p0, p1, p2, d0, d1, d2, stream);
|
| 262 |
+
} else {
|
| 263 |
+
im2col_3d_cuda_f32(src1_d, (float *) dst_d, N, IC, ID, IH, IW, OC, KD, KH, KW, OD, OH, OW,
|
| 264 |
+
stride_q, stride_z, stride_y, stride_x,
|
| 265 |
+
s0, s1, s2, p0, p1, p2, d0, d1, d2, stream);
|
| 266 |
+
}
|
| 267 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/im2col.cuh
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
|
| 3 |
+
#define CUDA_IM2COL_BLOCK_SIZE 256
|
| 4 |
+
|
| 5 |
+
void ggml_cuda_op_im2col(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
| 6 |
+
void ggml_cuda_op_im2col_3d(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
backend/llama.cpp/ggml/src/ggml-cuda/mean.cu
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "mean.cuh"
|
| 2 |
+
#include "reduce_rows.cuh"
|
| 3 |
+
|
| 4 |
+
#ifdef GGML_CUDA_USE_CUB
|
| 5 |
+
#include <cub/cub.cuh>
|
| 6 |
+
using namespace cub;
|
| 7 |
+
#endif // GGML_CUDA_USE_CUB
|
| 8 |
+
|
| 9 |
+
template <typename T> __global__ void divide_by_count(T * result, size_t count) {
|
| 10 |
+
*result /= static_cast<T>(count);
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
void ggml_cuda_op_mean(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 14 |
+
const ggml_tensor * src0 = dst->src[0];
|
| 15 |
+
const float * src0_d = (const float *) src0->data;
|
| 16 |
+
float * dst_d = (float *) dst->data;
|
| 17 |
+
cudaStream_t stream = ctx.stream();
|
| 18 |
+
|
| 19 |
+
GGML_ASSERT(src0->type == GGML_TYPE_F32);
|
| 20 |
+
GGML_ASSERT(dst->type == GGML_TYPE_F32);
|
| 21 |
+
GGML_ASSERT(ggml_is_contiguous(src0));
|
| 22 |
+
|
| 23 |
+
const int64_t ncols = src0->ne[0];
|
| 24 |
+
const int64_t nrows = ggml_nrows(src0);
|
| 25 |
+
|
| 26 |
+
// Special case for reducing vectors
|
| 27 |
+
#ifdef GGML_CUDA_USE_CUB
|
| 28 |
+
#ifdef USE_CUDA_GRAPH
|
| 29 |
+
cudaStreamCaptureStatus iscapturing;
|
| 30 |
+
CUDA_CHECK(cudaStreamIsCapturing(stream, &iscapturing));
|
| 31 |
+
#endif // USE_CUDA_GRAPH
|
| 32 |
+
if ((nrows == 1) &&
|
| 33 |
+
#ifdef USE_CUDA_GRAPH
|
| 34 |
+
// Determine if CUDA graphs are effectively disabled for this context
|
| 35 |
+
// (no graph instance exists and we're not capturing, OR graphs are explicitly enabled)
|
| 36 |
+
(((ncols > 65536) &&
|
| 37 |
+
(((!ctx.any_cuda_graph_has_instance()) && (iscapturing == cudaStreamCaptureStatusNone)) ||
|
| 38 |
+
ctx.any_cuda_graph_enabled())) ||
|
| 39 |
+
// CUDA graphs are enabled - use lower threshold
|
| 40 |
+
((ncols > 32768) &&
|
| 41 |
+
!(((!ctx.any_cuda_graph_has_instance()) && (iscapturing == cudaStreamCaptureStatusNone)) ||
|
| 42 |
+
ctx.any_cuda_graph_enabled())))) {
|
| 43 |
+
#else
|
| 44 |
+
(ncols > 65536)) {
|
| 45 |
+
#endif // USE_CUDA_GRAPH
|
| 46 |
+
// Single row - use device-wide reduction
|
| 47 |
+
size_t tmp_size = 0;
|
| 48 |
+
ggml_cuda_pool & pool = ctx.pool();
|
| 49 |
+
|
| 50 |
+
DeviceReduce::Sum(nullptr, tmp_size, src0_d, dst_d, ncols, stream);
|
| 51 |
+
|
| 52 |
+
ggml_cuda_pool_alloc<uint8_t> tmp_alloc(pool, tmp_size);
|
| 53 |
+
DeviceReduce::Sum(tmp_alloc.ptr, tmp_size, src0_d, dst_d, ncols, stream);
|
| 54 |
+
|
| 55 |
+
// Divide by ncols
|
| 56 |
+
divide_by_count<float><<<1, 1, 0, stream>>>(dst_d, ncols);
|
| 57 |
+
return;
|
| 58 |
+
}
|
| 59 |
+
#endif // GGML_CUDA_USE_CUB
|
| 60 |
+
|
| 61 |
+
const dim3 block_nums(nrows, 1, 1);
|
| 62 |
+
|
| 63 |
+
const int id = ggml_cuda_get_device();
|
| 64 |
+
const int nsm = ggml_cuda_info().devices[id].nsm;
|
| 65 |
+
|
| 66 |
+
// Heuristic for block size selection to optimize occupancy.
|
| 67 |
+
// See discussion in: https://github.com/ggml-org/llama.cpp/pull/15132
|
| 68 |
+
if ((nrows / nsm) < 2) {
|
| 69 |
+
const dim3 block_dims(512, 1, 1);
|
| 70 |
+
const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params(block_nums, block_dims, 0, stream);
|
| 71 |
+
ggml_cuda_kernel_launch(reduce_rows_f32</*norm=*/true>, launch_params, src0_d, dst_d, ncols);
|
| 72 |
+
} else {
|
| 73 |
+
const dim3 block_dims(ncols < 1024 ? 32 : 128, 1, 1);
|
| 74 |
+
const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params(block_nums, block_dims, 0, stream);
|
| 75 |
+
ggml_cuda_kernel_launch(reduce_rows_f32</*norm=*/true>, launch_params, src0_d, dst_d, ncols);
|
| 76 |
+
}
|
| 77 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/mean.cuh
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
|
| 3 |
+
void ggml_cuda_op_mean(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
backend/llama.cpp/ggml/src/ggml-cuda/mma.cuh
ADDED
|
@@ -0,0 +1,1456 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
// This file contains primitives that expose the tensor core PTX instructions for CUDA code.
|
| 3 |
+
// The primitives can be used in a similar way as the nvcuda::wmma interface but with a well-defined memory layout.
|
| 4 |
+
// The documentation for the PTX instructions can be found under:
|
| 5 |
+
// https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#matrix-multiply-accumulate-operation-using-mma-instruction
|
| 6 |
+
//
|
| 7 |
+
// Like with nvcuda::wmma there are three types of matrix tiles: A, B, and C with A @ B = C.
|
| 8 |
+
// A is a row-major matrix with shape M x K.
|
| 9 |
+
// B is a column-major matrix with shape K x N.
|
| 10 |
+
// C is a column-major matrix with shape M x N.
|
| 11 |
+
// A, B, and C are represented using the same fundamental data type: a row-major matrix with I rows and J columns.
|
| 12 |
+
// Note that J is measured in physical 32 bit elements instead of logical elements.
|
| 13 |
+
// The methods get_i and get_j can be used to get the physical 32 bit index of the lth element of a thread within a tile.
|
| 14 |
+
// All matrix tiles have ne physical 32 bit elements per warp.
|
| 15 |
+
//
|
| 16 |
+
// As described in the PTX documentation, all pointers for load_ldmatrix must be to shared memory and aligned to 16 bytes.
|
| 17 |
+
// The API in this file also assumes that the pointers for load_generic are aligned to 16 bytes, unaligned pointers are considered undefined behavior.
|
| 18 |
+
|
| 19 |
+
#include "common.cuh"
|
| 20 |
+
|
| 21 |
+
// On Volta each warp is doing 4 8x8 mma operations in parallel.
|
| 22 |
+
// The basic memory layout for a 32x8 output tile is to stack 4 input tiles in I direction and to mirror the B tile.
|
| 23 |
+
// However, the i indices in this file are by default permuted to simplify the index calculations.
|
| 24 |
+
// #define GGML_CUDA_MMA_NO_VOLTA_PERM
|
| 25 |
+
|
| 26 |
+
#if CUDART_VERSION >= 11080
|
| 27 |
+
|
| 28 |
+
static __device__ __forceinline__ int ggml_cuda_movmatrix(const int x) {
|
| 29 |
+
int ret = 0;
|
| 30 |
+
|
| 31 |
+
#ifdef TURING_MMA_AVAILABLE
|
| 32 |
+
asm("movmatrix.sync.aligned.m8n8.trans.b16 %0, %1;"
|
| 33 |
+
: "=r"(ret) : "r"(x));
|
| 34 |
+
#else
|
| 35 |
+
GGML_UNUSED(x);
|
| 36 |
+
NO_DEVICE_CODE;
|
| 37 |
+
#endif // defined(TURING_MMA_AVAILABLE)
|
| 38 |
+
return ret;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
#else
|
| 42 |
+
|
| 43 |
+
static __device__ __forceinline__ int ggml_cuda_movmatrix(const int x) {
|
| 44 |
+
// Imagine transposing row-major matrix to column-major matrix.
|
| 45 |
+
const int src_i_low = 2 * (threadIdx.x % 4);
|
| 46 |
+
const int src_i_high = src_i_low + 1;
|
| 47 |
+
const int src_j = threadIdx.x / 4;
|
| 48 |
+
|
| 49 |
+
const int src_laneid_low = src_i_low * 4 + src_j / 2;
|
| 50 |
+
const int src_laneid_high = src_i_high * 4 + src_j / 2;
|
| 51 |
+
|
| 52 |
+
const int shift_low = ((src_j + 0) % 2) * 16;
|
| 53 |
+
const int shift_high = ((src_j + 1) % 2) * 16;
|
| 54 |
+
|
| 55 |
+
const int ret_low = (__shfl_sync(0xFFFFFFFF, x, src_laneid_low, WARP_SIZE) >> shift_low) & 0x0000FFFF;
|
| 56 |
+
const int ret_high = (__shfl_sync(0xFFFFFFFF, x, src_laneid_high, WARP_SIZE) << shift_high) & 0xFFFF0000;
|
| 57 |
+
|
| 58 |
+
return ret_low | ret_high;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
#endif // CUDART_VERSION >= 11080
|
| 62 |
+
|
| 63 |
+
static __device__ __forceinline__ half2 ggml_cuda_movmatrix(const half2 x) {
|
| 64 |
+
half2 ret;
|
| 65 |
+
*((int *) &ret) = ggml_cuda_movmatrix(*((const int *) &x));
|
| 66 |
+
return ret;
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
namespace ggml_cuda_mma {
|
| 70 |
+
|
| 71 |
+
// Some architectures like Volta or CDNA3 perform multiple matrix multiplications per warp in parallel,
|
| 72 |
+
// effectively the warp is being split into subgroups of threads that each perform a single mma instruction.
|
| 73 |
+
// In those cases the data can be split in different ways across the warp.
|
| 74 |
+
enum data_layout {
|
| 75 |
+
// By default the data uses the I direction as its major dimension and the J direction as its minor dimension.
|
| 76 |
+
// For the A/C matrices this means I major == row major, J major == column major.
|
| 77 |
+
// For the B matrix this means I major == column major, J major == row major.
|
| 78 |
+
// MIRRORED == Each data value is held exactly once per thread subgroup.
|
| 79 |
+
DATA_LAYOUT_I_MAJOR = 0, // Always used for Turing, Ampere, Ada Lovelace, consumer Blackwell, matrix A&B for RDNA4 and CDNA.
|
| 80 |
+
DATA_LAYOUT_J_MAJOR = 10, // Matrix C for CDNA and RDNA4, int and float matrix C for RDNA3.
|
| 81 |
+
DATA_LAYOUT_I_MAJOR_MIRRORED = 20, // Volta, matrix A&B for RDNA3.
|
| 82 |
+
DATA_LAYOUT_J_MAJOR_MIRRORED = 30,
|
| 83 |
+
DATA_LAYOUT_I_MAJOR_SCRAMBLED = 40, // Scrambled matrix C for faster transposition (RDNA4/CDNA), convert to float to unscramble.
|
| 84 |
+
};
|
| 85 |
+
// Implemented mma combinations are:
|
| 86 |
+
// - (I_MAJOR, I_MAJOR) -> I_MAJOR
|
| 87 |
+
// - (I_MAJOR, I_MAJOR_MIRRORED) -> I_MAJOR
|
| 88 |
+
// - (I_MAJOR, J_MAJOR_MIRRORED) -> I_MAJOR
|
| 89 |
+
|
| 90 |
+
static constexpr __device__ data_layout get_input_data_layout() {
|
| 91 |
+
#if defined(RDNA3) || defined(VOLTA_MMA_AVAILABLE)
|
| 92 |
+
return DATA_LAYOUT_I_MAJOR_MIRRORED;
|
| 93 |
+
#else
|
| 94 |
+
return DATA_LAYOUT_I_MAJOR;
|
| 95 |
+
#endif // defined(RDNA3) || defined(VOLTA_MMA_AVAILABLE)
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
template <int I_, int J_, typename T, data_layout ds_=DATA_LAYOUT_I_MAJOR>
|
| 99 |
+
struct tile {};
|
| 100 |
+
|
| 101 |
+
template <int I_, int J_, typename T>
|
| 102 |
+
struct tile<I_, J_, T, DATA_LAYOUT_I_MAJOR> {
|
| 103 |
+
static constexpr int I = I_;
|
| 104 |
+
static constexpr int J = J_;
|
| 105 |
+
static constexpr data_layout dl = DATA_LAYOUT_I_MAJOR;
|
| 106 |
+
|
| 107 |
+
#if defined(AMD_MFMA_AVAILABLE)
|
| 108 |
+
static constexpr int ne = I * J / 64;
|
| 109 |
+
T x[ne] = {0};
|
| 110 |
+
|
| 111 |
+
static constexpr __device__ bool supported() {
|
| 112 |
+
if (I == 16 && J == 8) return true;
|
| 113 |
+
if (I == 32 && J == 4) return true;
|
| 114 |
+
if (I == 16 && J == 16) return true;
|
| 115 |
+
if (I == 32 && J == 32) return true;
|
| 116 |
+
return false;
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
static __device__ __forceinline__ int get_i(const int l) {
|
| 120 |
+
if constexpr (I == 16 && J == 4) {
|
| 121 |
+
return threadIdx.x % 16;
|
| 122 |
+
} else if constexpr (I == 16 && J == 8) {
|
| 123 |
+
return threadIdx.x % 16;
|
| 124 |
+
} else if constexpr (I == 32 && J == 4) {
|
| 125 |
+
return threadIdx.x % 32;
|
| 126 |
+
} else if constexpr (I == 16 && J == 16) {
|
| 127 |
+
return threadIdx.x % 16;
|
| 128 |
+
} else if constexpr (I == 32 && J == 32) {
|
| 129 |
+
return threadIdx.x % 32;
|
| 130 |
+
} else {
|
| 131 |
+
NO_DEVICE_CODE;
|
| 132 |
+
return -1;
|
| 133 |
+
}
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
static __device__ __forceinline__ int get_j(const int l) {
|
| 137 |
+
if constexpr (I == 16 && J == 4) {
|
| 138 |
+
return threadIdx.x / 16;
|
| 139 |
+
} else if constexpr (I == 16 && J == 8) {
|
| 140 |
+
return 2 * (threadIdx.x / 16) + l;
|
| 141 |
+
} else if constexpr (I == 32 && J == 4) {
|
| 142 |
+
return 2 * (threadIdx.x / 32) + l;
|
| 143 |
+
} else if constexpr (I == 16 && J == 16) {
|
| 144 |
+
return 4 * (threadIdx.x / 16) + l;
|
| 145 |
+
} else if constexpr (I == 32 && J == 32) {
|
| 146 |
+
return 4 * (threadIdx.x / 32) + 8 * (l / 4) + (l % 4);
|
| 147 |
+
} else {
|
| 148 |
+
NO_DEVICE_CODE;
|
| 149 |
+
return -1;
|
| 150 |
+
}
|
| 151 |
+
}
|
| 152 |
+
#elif defined(VOLTA_MMA_AVAILABLE)
|
| 153 |
+
static constexpr int ne = I * J / 32;
|
| 154 |
+
T x[ne] = {0};
|
| 155 |
+
|
| 156 |
+
static constexpr __device__ bool supported() {
|
| 157 |
+
if (I == 32 && J == 8) return true;
|
| 158 |
+
return false;
|
| 159 |
+
}
|
| 160 |
+
|
| 161 |
+
static __device__ __forceinline__ int get_i(const int l) {
|
| 162 |
+
if constexpr (I == 32 && J == 8) {
|
| 163 |
+
#ifdef GGML_CUDA_MMA_NO_VOLTA_PERM
|
| 164 |
+
return (((threadIdx.x % 16) / 4) * 8) + ((threadIdx.x / 16) * 4) + (l & 2) + (threadIdx.x % 2);
|
| 165 |
+
#else
|
| 166 |
+
return (l & 2) + (threadIdx.x & ~2);
|
| 167 |
+
#endif // GGML_CUDA_MMA_NO_VOLTA_PERM
|
| 168 |
+
} else {
|
| 169 |
+
NO_DEVICE_CODE;
|
| 170 |
+
return -1;
|
| 171 |
+
}
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
static __device__ __forceinline__ int get_j(const int l) {
|
| 175 |
+
if constexpr (I == 32 && J == 8) {
|
| 176 |
+
return (threadIdx.x & 2) + (l & (4 + 1));
|
| 177 |
+
} else {
|
| 178 |
+
NO_DEVICE_CODE;
|
| 179 |
+
return -1;
|
| 180 |
+
}
|
| 181 |
+
}
|
| 182 |
+
#elif defined(AMD_WMMA_AVAILABLE)
|
| 183 |
+
static constexpr int ne = I * J / 32;
|
| 184 |
+
T x[ne] = {0};
|
| 185 |
+
|
| 186 |
+
static constexpr __device__ bool supported() {
|
| 187 |
+
if (I == 16 && J == 16) return true;
|
| 188 |
+
if (I == 16 && J == 8) return true;
|
| 189 |
+
if (I == 16 && J == 4) return true;
|
| 190 |
+
return false;
|
| 191 |
+
}
|
| 192 |
+
|
| 193 |
+
static __device__ __forceinline__ int get_i(const int l) {
|
| 194 |
+
if constexpr (supported()) {
|
| 195 |
+
return threadIdx.x % 16;
|
| 196 |
+
} else {
|
| 197 |
+
NO_DEVICE_CODE;
|
| 198 |
+
return -1;
|
| 199 |
+
}
|
| 200 |
+
}
|
| 201 |
+
|
| 202 |
+
static __device__ __forceinline__ int get_j(const int l) {
|
| 203 |
+
if constexpr (I == 16 && J == 16) {
|
| 204 |
+
#if defined(RDNA3)
|
| 205 |
+
if constexpr (std::is_same_v<T, float> || std::is_same_v<T, int>) {
|
| 206 |
+
// matrix C
|
| 207 |
+
return 2 * l + (threadIdx.x / 16);
|
| 208 |
+
} else {
|
| 209 |
+
// matrix A&B
|
| 210 |
+
return l;
|
| 211 |
+
}
|
| 212 |
+
#else
|
| 213 |
+
// matrix C is the transposed matrix A&B on RDNA4
|
| 214 |
+
return ne * (threadIdx.x / 16) + l;
|
| 215 |
+
#endif // defined(RDNA3)
|
| 216 |
+
} else if constexpr (I == 16 && J == 8) {
|
| 217 |
+
// mmq input for RDNA4
|
| 218 |
+
return ne * (threadIdx.x / 16) + l;
|
| 219 |
+
} else if constexpr (I == 16 && J == 4) {
|
| 220 |
+
return ne * (threadIdx.x / 16) + l;
|
| 221 |
+
} else {
|
| 222 |
+
NO_DEVICE_CODE;
|
| 223 |
+
return -1;
|
| 224 |
+
}
|
| 225 |
+
}
|
| 226 |
+
#else
|
| 227 |
+
static constexpr int ne = I * J / 32;
|
| 228 |
+
T x[ne] = {0};
|
| 229 |
+
|
| 230 |
+
static constexpr __device__ bool supported() {
|
| 231 |
+
if (I == 8 && J == 4) return true;
|
| 232 |
+
if (I == 8 && J == 8) return true;
|
| 233 |
+
if (I == 16 && J == 8) return true;
|
| 234 |
+
if (I == 16 && J == 16) return true;
|
| 235 |
+
if (I == 32 && J == 8) return true;
|
| 236 |
+
return false;
|
| 237 |
+
}
|
| 238 |
+
|
| 239 |
+
static __device__ __forceinline__ int get_i(const int l) {
|
| 240 |
+
if constexpr (I == 8 && J == 4) {
|
| 241 |
+
return threadIdx.x / 4;
|
| 242 |
+
} else if constexpr (I == 8 && J == 8) {
|
| 243 |
+
return threadIdx.x / 4;
|
| 244 |
+
} else if constexpr (I == 16 && J == 8) {
|
| 245 |
+
return ((l / 2) * 8) + (threadIdx.x / 4);
|
| 246 |
+
} else if constexpr (I == 16 && J == 16) {
|
| 247 |
+
return (((l / 2) % 2) * 8) + (threadIdx.x / 4);
|
| 248 |
+
} else if constexpr (I == 32 && J == 8) {
|
| 249 |
+
return tile<16, 8, T>::get_i(l); // Memory layout simply repeated with same pattern in i direction.
|
| 250 |
+
} else {
|
| 251 |
+
NO_DEVICE_CODE;
|
| 252 |
+
return -1;
|
| 253 |
+
}
|
| 254 |
+
}
|
| 255 |
+
|
| 256 |
+
static __device__ __forceinline__ int get_j(const int l) {
|
| 257 |
+
if constexpr (I == 8 && J == 4) {
|
| 258 |
+
return threadIdx.x % 4;
|
| 259 |
+
} else if constexpr (I == 8 && J == 8) {
|
| 260 |
+
return (l * 4) + (threadIdx.x % 4);
|
| 261 |
+
} else if constexpr (I == 16 && J == 8) {
|
| 262 |
+
return ((threadIdx.x % 4) * 2) + (l % 2);
|
| 263 |
+
} else if constexpr (I == 16 && J == 16) {
|
| 264 |
+
return ((l / 4) * 8) + ((threadIdx.x % 4) * 2) + (l % 2);
|
| 265 |
+
} else if constexpr (I == 32 && J == 8) {
|
| 266 |
+
return tile<16, 8, T>::get_j(l); // Memory layout simply repeated with same pattern in i direction.
|
| 267 |
+
} else {
|
| 268 |
+
NO_DEVICE_CODE;
|
| 269 |
+
return -1;
|
| 270 |
+
}
|
| 271 |
+
}
|
| 272 |
+
#endif // defined(GGML_USE_HIP)
|
| 273 |
+
};
|
| 274 |
+
|
| 275 |
+
template <int I_, int J_>
|
| 276 |
+
struct tile<I_, J_, half2, DATA_LAYOUT_I_MAJOR> {
|
| 277 |
+
static constexpr int I = I_;
|
| 278 |
+
static constexpr int J = J_;
|
| 279 |
+
static constexpr data_layout dl = DATA_LAYOUT_I_MAJOR;
|
| 280 |
+
|
| 281 |
+
#if defined(VOLTA_MMA_AVAILABLE)
|
| 282 |
+
static constexpr int ne = I * J / WARP_SIZE;
|
| 283 |
+
half2 x[ne] = {{0.0f, 0.0f}};
|
| 284 |
+
|
| 285 |
+
static constexpr __device__ bool supported() {
|
| 286 |
+
if (I == 32 && J == 4) return true;
|
| 287 |
+
return false;
|
| 288 |
+
}
|
| 289 |
+
|
| 290 |
+
static __device__ __forceinline__ int get_i(const int l) {
|
| 291 |
+
if constexpr (I == 32 && J == 4) {
|
| 292 |
+
#ifdef GGML_CUDA_MMA_NO_VOLTA_PERM
|
| 293 |
+
return (((threadIdx.x % 16) / 4) * 8) + ((threadIdx.x / 16) * 4) + (threadIdx.x % 4);
|
| 294 |
+
#else
|
| 295 |
+
return threadIdx.x;
|
| 296 |
+
#endif // GGML_CUDA_MMA_NO_VOLTA_PERM
|
| 297 |
+
} else {
|
| 298 |
+
NO_DEVICE_CODE;
|
| 299 |
+
return -1;
|
| 300 |
+
}
|
| 301 |
+
}
|
| 302 |
+
|
| 303 |
+
static __device__ __forceinline__ int get_j(const int l) {
|
| 304 |
+
if constexpr (I == 32 && J == 4) {
|
| 305 |
+
return l;
|
| 306 |
+
} else {
|
| 307 |
+
NO_DEVICE_CODE;
|
| 308 |
+
return -1;
|
| 309 |
+
}
|
| 310 |
+
}
|
| 311 |
+
#elif defined(AMD_WMMA_AVAILABLE)
|
| 312 |
+
static constexpr int ne = I * J / 32;
|
| 313 |
+
half2 x[ne] = {{0.0f, 0.0f}};
|
| 314 |
+
|
| 315 |
+
static constexpr __device__ bool supported() {
|
| 316 |
+
if (I == 16 && J == 8) return true;
|
| 317 |
+
if (I == 16 && J == 16) return true;
|
| 318 |
+
if (I == 32 && J == 8) return true;
|
| 319 |
+
return false;
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
static __device__ __forceinline__ int get_i(const int l) {
|
| 323 |
+
if constexpr (I == 16 && J == 8) {
|
| 324 |
+
return threadIdx.x % 16;
|
| 325 |
+
} else if constexpr (I == 16 && J == 16) {
|
| 326 |
+
return threadIdx.x % 16;
|
| 327 |
+
} else if constexpr (I == 32 && J == 8) {
|
| 328 |
+
return (threadIdx.x % 16) * 2 + l / (ne/2);
|
| 329 |
+
} else {
|
| 330 |
+
NO_DEVICE_CODE;
|
| 331 |
+
return -1;
|
| 332 |
+
}
|
| 333 |
+
}
|
| 334 |
+
|
| 335 |
+
static __device__ __forceinline__ int get_j(const int l) {
|
| 336 |
+
if constexpr (I == 16 && J == 8) {
|
| 337 |
+
return (threadIdx.x / 16) * ne + l;
|
| 338 |
+
} else if constexpr (I == 16 && J == 16) {
|
| 339 |
+
#ifdef RDNA3
|
| 340 |
+
return l*2 + (threadIdx.x / 16);
|
| 341 |
+
#else
|
| 342 |
+
return (threadIdx.x / 16) * ne + l;
|
| 343 |
+
#endif // RDNA3
|
| 344 |
+
} else if constexpr (I == 32 && J == 8) {
|
| 345 |
+
return (threadIdx.x / 16) * (ne/2) + l % (ne/2);
|
| 346 |
+
} else {
|
| 347 |
+
NO_DEVICE_CODE;
|
| 348 |
+
return -1;
|
| 349 |
+
}
|
| 350 |
+
}
|
| 351 |
+
#elif defined(AMD_MFMA_AVAILABLE)
|
| 352 |
+
static constexpr int ne = I * J / 64;
|
| 353 |
+
half2 x[ne] = {{0.0f, 0.0f}};
|
| 354 |
+
|
| 355 |
+
static constexpr __device__ bool supported() {
|
| 356 |
+
if (I == 16 && J == 8) return true;
|
| 357 |
+
if (I == 16 && J == 16) return true;
|
| 358 |
+
if (I == 32 && J == 8) return true;
|
| 359 |
+
return false;
|
| 360 |
+
}
|
| 361 |
+
|
| 362 |
+
static __device__ __forceinline__ int get_i(const int l) {
|
| 363 |
+
if constexpr (I == 16 && J == 8) {
|
| 364 |
+
return threadIdx.x % 16;
|
| 365 |
+
} else if constexpr (I == 16 && J == 16) {
|
| 366 |
+
return threadIdx.x % 16;
|
| 367 |
+
} else if constexpr (I == 32 && J == 8) {
|
| 368 |
+
return (threadIdx.x % 16) * 2 + l / (ne/2);
|
| 369 |
+
} else {
|
| 370 |
+
NO_DEVICE_CODE;
|
| 371 |
+
return -1;
|
| 372 |
+
}
|
| 373 |
+
}
|
| 374 |
+
|
| 375 |
+
static __device__ __forceinline__ int get_j(const int l) {
|
| 376 |
+
if constexpr (I == 16 && J == 8) {
|
| 377 |
+
return (threadIdx.x / 16) * ne + l;
|
| 378 |
+
} else if constexpr (I == 16 && J == 16) {
|
| 379 |
+
return (threadIdx.x / 16) * ne + l;
|
| 380 |
+
} else if constexpr (I == 32 && J == 8) {
|
| 381 |
+
return (threadIdx.x / 16) * (ne/2) + l % (ne/2);
|
| 382 |
+
} else {
|
| 383 |
+
NO_DEVICE_CODE;
|
| 384 |
+
return -1;
|
| 385 |
+
}
|
| 386 |
+
}
|
| 387 |
+
#else
|
| 388 |
+
static constexpr int ne = I * J / WARP_SIZE;
|
| 389 |
+
half2 x[ne] = {{0.0f, 0.0f}};
|
| 390 |
+
|
| 391 |
+
static constexpr __device__ bool supported() {
|
| 392 |
+
if (I == 8 && J == 4) return true;
|
| 393 |
+
if (I == 8 && J == 8) return true;
|
| 394 |
+
if (I == 16 && J == 8) return true;
|
| 395 |
+
if (I == 16 && J == 16) return true;
|
| 396 |
+
if (I == 32 && J == 8) return true;
|
| 397 |
+
return false;
|
| 398 |
+
}
|
| 399 |
+
|
| 400 |
+
static __device__ __forceinline__ int get_i(const int l) {
|
| 401 |
+
if constexpr (I == 8 && J == 8) {
|
| 402 |
+
return threadIdx.x / 4;
|
| 403 |
+
} else if constexpr (I == 16 && J == 4) {
|
| 404 |
+
return (l * 8) + (threadIdx.x / 4);
|
| 405 |
+
} else if constexpr (I == 16 && J == 8) {
|
| 406 |
+
return ((l % 2) * 8) + (threadIdx.x / 4);
|
| 407 |
+
} else if constexpr (I == 32 && J == 8) {
|
| 408 |
+
return ((l / 4) * 16) + ((l % 2) * 8) + (threadIdx.x / 4);
|
| 409 |
+
} else {
|
| 410 |
+
NO_DEVICE_CODE;
|
| 411 |
+
return -1;
|
| 412 |
+
}
|
| 413 |
+
}
|
| 414 |
+
|
| 415 |
+
static __device__ __forceinline__ int get_j(const int l) {
|
| 416 |
+
if constexpr (I == 8 && J == 8) {
|
| 417 |
+
return (l * 4) + (threadIdx.x % 4);
|
| 418 |
+
} else if constexpr (I == 16 && J == 4) {
|
| 419 |
+
return threadIdx.x % 4;
|
| 420 |
+
} else if constexpr (I == 16 && J == 8) {
|
| 421 |
+
return ((l / 2) * 4) + (threadIdx.x % 4);
|
| 422 |
+
} else if constexpr (I == 32 && J == 8) {
|
| 423 |
+
return ((l & 2) * 2) + (threadIdx.x % 4);
|
| 424 |
+
} else {
|
| 425 |
+
NO_DEVICE_CODE;
|
| 426 |
+
return -1;
|
| 427 |
+
}
|
| 428 |
+
}
|
| 429 |
+
#endif // defined(VOLTA_MMA_AVAILABLE)
|
| 430 |
+
};
|
| 431 |
+
|
| 432 |
+
template <int I_, int J_>
|
| 433 |
+
struct tile<I_, J_, nv_bfloat162, DATA_LAYOUT_I_MAJOR> {
|
| 434 |
+
static constexpr int I = I_;
|
| 435 |
+
static constexpr int J = J_;
|
| 436 |
+
static constexpr data_layout dl = DATA_LAYOUT_I_MAJOR;
|
| 437 |
+
|
| 438 |
+
#if defined(AMD_WMMA_AVAILABLE)
|
| 439 |
+
static constexpr int ne = tile<I_, J_, half2, DATA_LAYOUT_I_MAJOR>::ne;
|
| 440 |
+
nv_bfloat162 x[ne] = {{0.0f, 0.0f}};
|
| 441 |
+
|
| 442 |
+
static constexpr __device__ bool supported() {
|
| 443 |
+
return tile<I_, J_, half2, DATA_LAYOUT_I_MAJOR>::supported();
|
| 444 |
+
}
|
| 445 |
+
|
| 446 |
+
static __device__ __forceinline__ int get_i(const int l) {
|
| 447 |
+
return tile<I_, J_, half2, DATA_LAYOUT_I_MAJOR>::get_i(l);
|
| 448 |
+
}
|
| 449 |
+
|
| 450 |
+
static __device__ __forceinline__ int get_j(const int l) {
|
| 451 |
+
return tile<I_, J_, half2, DATA_LAYOUT_I_MAJOR>::get_j(l);
|
| 452 |
+
}
|
| 453 |
+
#elif defined(AMD_MFMA_AVAILABLE)
|
| 454 |
+
static constexpr int ne = tile<I_, J_, half2, DATA_LAYOUT_I_MAJOR>::ne;
|
| 455 |
+
nv_bfloat162 x[ne] = {{0.0f, 0.0f}};
|
| 456 |
+
|
| 457 |
+
static constexpr __device__ bool supported() {
|
| 458 |
+
return tile<I_, J_, half2, DATA_LAYOUT_I_MAJOR>::supported();
|
| 459 |
+
}
|
| 460 |
+
|
| 461 |
+
static __device__ __forceinline__ int get_i(const int l) {
|
| 462 |
+
return tile<I_, J_, half2, DATA_LAYOUT_I_MAJOR>::get_i(l);
|
| 463 |
+
}
|
| 464 |
+
|
| 465 |
+
static __device__ __forceinline__ int get_j(const int l) {
|
| 466 |
+
return tile<I_, J_, half2, DATA_LAYOUT_I_MAJOR>::get_j(l);
|
| 467 |
+
}
|
| 468 |
+
#else
|
| 469 |
+
static constexpr int ne = I * J / WARP_SIZE;
|
| 470 |
+
nv_bfloat162 x[ne] = {{0.0f, 0.0f}};
|
| 471 |
+
|
| 472 |
+
static constexpr __device__ bool supported() {
|
| 473 |
+
if (I == 8 && J == 8) return true;
|
| 474 |
+
if (I == 16 && J == 4) return true;
|
| 475 |
+
if (I == 16 && J == 8) return true;
|
| 476 |
+
return false;
|
| 477 |
+
}
|
| 478 |
+
|
| 479 |
+
static __device__ __forceinline__ int get_i(const int l) {
|
| 480 |
+
if constexpr (I == 8 && J == 8) {
|
| 481 |
+
return threadIdx.x / 4;
|
| 482 |
+
} else if constexpr (I == 16 && J == 4) {
|
| 483 |
+
return (l * 8) + (threadIdx.x / 4);
|
| 484 |
+
} else if constexpr (I == 16 && J == 8) {
|
| 485 |
+
return ((l % 2) * 8) + (threadIdx.x / 4);
|
| 486 |
+
} else {
|
| 487 |
+
NO_DEVICE_CODE;
|
| 488 |
+
return -1;
|
| 489 |
+
}
|
| 490 |
+
}
|
| 491 |
+
|
| 492 |
+
static __device__ __forceinline__ int get_j(const int l) {
|
| 493 |
+
if constexpr (I == 8 && J == 8) {
|
| 494 |
+
return (l * 4) + (threadIdx.x % 4);
|
| 495 |
+
} else if constexpr (I == 16 && J == 4) {
|
| 496 |
+
return threadIdx.x % 4;
|
| 497 |
+
} else if constexpr (I == 16 && J == 8) {
|
| 498 |
+
return ((l / 2) * 4) + (threadIdx.x % 4);
|
| 499 |
+
} else {
|
| 500 |
+
NO_DEVICE_CODE;
|
| 501 |
+
return -1;
|
| 502 |
+
}
|
| 503 |
+
}
|
| 504 |
+
#endif // defined(AMD_WMMA_AVAILABLE)
|
| 505 |
+
};
|
| 506 |
+
|
| 507 |
+
template <int I_, int J_, typename T>
|
| 508 |
+
struct tile<I_, J_, T, DATA_LAYOUT_J_MAJOR> {
|
| 509 |
+
static constexpr int I = I_;
|
| 510 |
+
static constexpr int J = J_;
|
| 511 |
+
static constexpr data_layout dl = DATA_LAYOUT_J_MAJOR;
|
| 512 |
+
|
| 513 |
+
static constexpr int ne = tile<I_, J_, T, DATA_LAYOUT_I_MAJOR>::ne;
|
| 514 |
+
T x[ne] = {0};
|
| 515 |
+
|
| 516 |
+
static constexpr __device__ bool supported() {
|
| 517 |
+
return tile<I_, J_, T, DATA_LAYOUT_I_MAJOR>::supported();
|
| 518 |
+
}
|
| 519 |
+
|
| 520 |
+
static __device__ __forceinline__ int get_i(const int l) {
|
| 521 |
+
return tile<I_, J_, T, DATA_LAYOUT_I_MAJOR>::get_j(l);
|
| 522 |
+
}
|
| 523 |
+
|
| 524 |
+
static __device__ __forceinline__ int get_j(const int l) {
|
| 525 |
+
return tile<I_, J_, T, DATA_LAYOUT_I_MAJOR>::get_i(l);
|
| 526 |
+
}
|
| 527 |
+
};
|
| 528 |
+
|
| 529 |
+
template <int I_, int J_, typename T>
|
| 530 |
+
struct tile<I_, J_, T, DATA_LAYOUT_I_MAJOR_MIRRORED> {
|
| 531 |
+
static constexpr int I = I_;
|
| 532 |
+
static constexpr int J = J_;
|
| 533 |
+
static constexpr data_layout dl = DATA_LAYOUT_I_MAJOR_MIRRORED;
|
| 534 |
+
|
| 535 |
+
// RDNA3
|
| 536 |
+
static constexpr int ne = I * J / 32 * 2;
|
| 537 |
+
|
| 538 |
+
T x[ne] = {0};
|
| 539 |
+
|
| 540 |
+
static constexpr __device__ bool supported() {
|
| 541 |
+
if (I == 16 && J == 16) return true;
|
| 542 |
+
if (I == 16 && J == 8) return true;
|
| 543 |
+
if (I == 16 && J == 4) return true;
|
| 544 |
+
if (I == 32 && J == 8) return true;
|
| 545 |
+
return false;
|
| 546 |
+
}
|
| 547 |
+
|
| 548 |
+
static __device__ __forceinline__ int get_i(const int l) {
|
| 549 |
+
if constexpr (I == 16) {
|
| 550 |
+
return threadIdx.x % 16;
|
| 551 |
+
} else if constexpr (I == 32) {
|
| 552 |
+
return (threadIdx.x % 16) * 2 + l / (ne/2);
|
| 553 |
+
} else {
|
| 554 |
+
NO_DEVICE_CODE;
|
| 555 |
+
return -1;
|
| 556 |
+
}
|
| 557 |
+
}
|
| 558 |
+
|
| 559 |
+
static __device__ __forceinline__ int get_j(const int l) {
|
| 560 |
+
if constexpr (I == 16) {
|
| 561 |
+
return l;
|
| 562 |
+
} else if constexpr (I == 32) {
|
| 563 |
+
return l % (ne/2);
|
| 564 |
+
} else {
|
| 565 |
+
NO_DEVICE_CODE;
|
| 566 |
+
return -1;
|
| 567 |
+
}
|
| 568 |
+
}
|
| 569 |
+
};
|
| 570 |
+
|
| 571 |
+
template <int I_, int J_>
|
| 572 |
+
struct tile<I_, J_, half2, DATA_LAYOUT_I_MAJOR_MIRRORED> {
|
| 573 |
+
static constexpr int I = I_;
|
| 574 |
+
static constexpr int J = J_;
|
| 575 |
+
static constexpr data_layout dl = DATA_LAYOUT_I_MAJOR_MIRRORED;
|
| 576 |
+
#if defined(RDNA3)
|
| 577 |
+
static constexpr int ne = tile<I_, J_, float, DATA_LAYOUT_I_MAJOR_MIRRORED>::ne;
|
| 578 |
+
|
| 579 |
+
half2 x[ne] = {{0.0f, 0.0f}};
|
| 580 |
+
|
| 581 |
+
static constexpr __device__ bool supported() {
|
| 582 |
+
return tile<I_, J_, float, DATA_LAYOUT_I_MAJOR_MIRRORED>::supported();
|
| 583 |
+
}
|
| 584 |
+
|
| 585 |
+
static __device__ __forceinline__ int get_i(const int l) {
|
| 586 |
+
return tile<I_, J_, float, DATA_LAYOUT_I_MAJOR_MIRRORED>::get_i(l);
|
| 587 |
+
}
|
| 588 |
+
|
| 589 |
+
static __device__ __forceinline__ int get_j(const int l) {
|
| 590 |
+
return tile<I_, J_, float, DATA_LAYOUT_I_MAJOR_MIRRORED>::get_j(l);
|
| 591 |
+
}
|
| 592 |
+
#else // Volta
|
| 593 |
+
static constexpr int ne = I * J / (WARP_SIZE/4);
|
| 594 |
+
|
| 595 |
+
half2 x[ne] = {{0.0f, 0.0f}};
|
| 596 |
+
|
| 597 |
+
static constexpr __device__ bool supported() {
|
| 598 |
+
if (I == 8 && J == 4) return true;
|
| 599 |
+
return false;
|
| 600 |
+
}
|
| 601 |
+
|
| 602 |
+
static __device__ __forceinline__ int get_i(const int /*l*/) {
|
| 603 |
+
if constexpr (I == 8 && J == 4) {
|
| 604 |
+
return ((threadIdx.x / 16) * 4) + (threadIdx.x % 4);
|
| 605 |
+
} else {
|
| 606 |
+
NO_DEVICE_CODE;
|
| 607 |
+
return -1;
|
| 608 |
+
}
|
| 609 |
+
}
|
| 610 |
+
|
| 611 |
+
static __device__ __forceinline__ int get_j(const int l) {
|
| 612 |
+
if constexpr (I == 8 && J == 4) {
|
| 613 |
+
return l;
|
| 614 |
+
} else {
|
| 615 |
+
NO_DEVICE_CODE;
|
| 616 |
+
return -1;
|
| 617 |
+
}
|
| 618 |
+
}
|
| 619 |
+
#endif // defined(RDNA3)
|
| 620 |
+
};
|
| 621 |
+
|
| 622 |
+
template <int I_, int J_>
|
| 623 |
+
struct tile<I_, J_, nv_bfloat162, DATA_LAYOUT_I_MAJOR_MIRRORED> {
|
| 624 |
+
static constexpr int I = I_;
|
| 625 |
+
static constexpr int J = J_;
|
| 626 |
+
static constexpr data_layout dl = DATA_LAYOUT_I_MAJOR_MIRRORED;
|
| 627 |
+
static constexpr int ne = tile<I_, J_, float, DATA_LAYOUT_I_MAJOR_MIRRORED>::ne;
|
| 628 |
+
|
| 629 |
+
nv_bfloat162 x[ne] = {{0.0f, 0.0f}};
|
| 630 |
+
|
| 631 |
+
static constexpr __device__ bool supported() {
|
| 632 |
+
return tile<I_, J_, float, DATA_LAYOUT_I_MAJOR_MIRRORED>::supported();
|
| 633 |
+
}
|
| 634 |
+
|
| 635 |
+
static __device__ __forceinline__ int get_i(const int l) {
|
| 636 |
+
return tile<I_, J_, float, DATA_LAYOUT_I_MAJOR_MIRRORED>::get_i(l);
|
| 637 |
+
}
|
| 638 |
+
|
| 639 |
+
static __device__ __forceinline__ int get_j(const int l) {
|
| 640 |
+
return tile<I_, J_, float, DATA_LAYOUT_I_MAJOR_MIRRORED>::get_j(l);
|
| 641 |
+
}
|
| 642 |
+
};
|
| 643 |
+
|
| 644 |
+
template <int I_, int J_>
|
| 645 |
+
struct tile<I_, J_, half2, DATA_LAYOUT_J_MAJOR_MIRRORED> {
|
| 646 |
+
static constexpr int I = I_;
|
| 647 |
+
static constexpr int J = J_;
|
| 648 |
+
static constexpr data_layout dl = DATA_LAYOUT_J_MAJOR_MIRRORED;
|
| 649 |
+
static constexpr int ne = I * J / (WARP_SIZE/4);
|
| 650 |
+
|
| 651 |
+
half2 x[ne] = {{0.0f, 0.0f}};
|
| 652 |
+
|
| 653 |
+
static constexpr __device__ bool supported() {
|
| 654 |
+
if (I == 8 && J == 4) return true;
|
| 655 |
+
return false;
|
| 656 |
+
}
|
| 657 |
+
|
| 658 |
+
static __device__ __forceinline__ int get_i(const int l) {
|
| 659 |
+
if constexpr (I == 8 && J == 4) {
|
| 660 |
+
return ((l / 2) * 4) + (threadIdx.x % 4);
|
| 661 |
+
} else {
|
| 662 |
+
NO_DEVICE_CODE;
|
| 663 |
+
return -1;
|
| 664 |
+
}
|
| 665 |
+
}
|
| 666 |
+
|
| 667 |
+
static __device__ __forceinline__ int get_j(const int l) {
|
| 668 |
+
if constexpr (I == 8 && J == 4) {
|
| 669 |
+
return ((threadIdx.x / 16) * 2) + (l % 2);
|
| 670 |
+
} else {
|
| 671 |
+
NO_DEVICE_CODE;
|
| 672 |
+
return -1;
|
| 673 |
+
}
|
| 674 |
+
}
|
| 675 |
+
};
|
| 676 |
+
|
| 677 |
+
template <int I_, int J_>
|
| 678 |
+
struct tile<I_, J_, half2, DATA_LAYOUT_I_MAJOR_SCRAMBLED> {
|
| 679 |
+
static constexpr int I = I_;
|
| 680 |
+
static constexpr int J = J_;
|
| 681 |
+
static constexpr data_layout dl = DATA_LAYOUT_I_MAJOR_SCRAMBLED;
|
| 682 |
+
|
| 683 |
+
static constexpr int ne = I * J / ggml_cuda_get_physical_warp_size();
|
| 684 |
+
half2 x[ne] = {{0.0f, 0.0f}};
|
| 685 |
+
|
| 686 |
+
static constexpr __device__ bool supported() {
|
| 687 |
+
if (I == 16 && J == 16) return true;
|
| 688 |
+
return false;
|
| 689 |
+
}
|
| 690 |
+
|
| 691 |
+
static __device__ __forceinline__ int get_i(const int l) {
|
| 692 |
+
return tile<I_, J_, half2, DATA_LAYOUT_I_MAJOR>::get_i(l);
|
| 693 |
+
}
|
| 694 |
+
};
|
| 695 |
+
|
| 696 |
+
static __device__ __forceinline__ tile<16, 16, half2, DATA_LAYOUT_I_MAJOR> unscramble(const tile<16, 16, half2, DATA_LAYOUT_I_MAJOR_SCRAMBLED> & t) {
|
| 697 |
+
#if defined(AMD_MFMA_AVAILABLE) || (defined(AMD_WMMA_AVAILABLE) && defined(RDNA4))
|
| 698 |
+
tile<16, 16, half2, DATA_LAYOUT_I_MAJOR> ret;
|
| 699 |
+
#pragma unroll
|
| 700 |
+
for (int l0 = 0; l0 < t.ne/2; ++l0) {
|
| 701 |
+
ret.x[2*l0 + 0] = __lows2half2(t.x[l0], t.x[l0 + t.ne/2]);
|
| 702 |
+
ret.x[2*l0 + 1] = __highs2half2(t.x[l0], t.x[l0 + t.ne/2]);
|
| 703 |
+
}
|
| 704 |
+
return ret;
|
| 705 |
+
#else
|
| 706 |
+
NO_DEVICE_CODE;
|
| 707 |
+
GGML_UNUSED(t);
|
| 708 |
+
#endif // defined(AMD_MFMA_AVAILABLE) || (defined(AMD_WMMA_AVAILABLE) && defined(RDNA4))
|
| 709 |
+
}
|
| 710 |
+
|
| 711 |
+
#if defined(TURING_MMA_AVAILABLE)
|
| 712 |
+
template <int I, int J>
|
| 713 |
+
static __device__ __forceinline__ tile<I, J/2, half2> get_half2(const tile<I, J, float> & tile_float) {
|
| 714 |
+
tile<I, J/2, half2> ret;
|
| 715 |
+
#pragma unroll
|
| 716 |
+
for (int l0 = 0; l0 < tile_float.ne; l0 += 2) {
|
| 717 |
+
ret.x[l0/2] = make_half2(tile_float.x[l0 + 0], tile_float.x[l0 + 1]);
|
| 718 |
+
}
|
| 719 |
+
return ret;
|
| 720 |
+
}
|
| 721 |
+
|
| 722 |
+
static __device__ __forceinline__ tile<8, 8, half2> get_transposed(const tile<16, 4, half2> & t) {
|
| 723 |
+
tile<8, 8, half2> ret;
|
| 724 |
+
ret.x[0] = ggml_cuda_movmatrix(t.x[0]);
|
| 725 |
+
ret.x[1] = ggml_cuda_movmatrix(t.x[1]);
|
| 726 |
+
|
| 727 |
+
return ret;
|
| 728 |
+
}
|
| 729 |
+
#elif defined(AMD_WMMA_AVAILABLE) && defined(RDNA3)
|
| 730 |
+
static __device__ __forceinline__ tile<16, 8, half2, DATA_LAYOUT_I_MAJOR_MIRRORED> get_half2(
|
| 731 |
+
const tile<16, 16, float, DATA_LAYOUT_I_MAJOR> & tile_float) {
|
| 732 |
+
tile<16, 8, half2, DATA_LAYOUT_I_MAJOR_MIRRORED> ret;
|
| 733 |
+
#pragma unroll
|
| 734 |
+
for (int l = 0; l < tile_float.ne; ++l) {
|
| 735 |
+
float tmp[2];
|
| 736 |
+
int i = threadIdx.x / 16;
|
| 737 |
+
tmp[i] = tile_float.x[l];
|
| 738 |
+
i ^= 1;
|
| 739 |
+
tmp[i] = __shfl_xor_sync(0xFFFFFFFF, tile_float.x[l], 16, WARP_SIZE);
|
| 740 |
+
ret.x[l] = make_half2(tmp[0], tmp[1]);
|
| 741 |
+
}
|
| 742 |
+
return ret;
|
| 743 |
+
}
|
| 744 |
+
#elif defined(AMD_WMMA_AVAILABLE) || defined(AMD_MFMA_AVAILABLE)
|
| 745 |
+
template <int I, int J>
|
| 746 |
+
static __device__ __forceinline__ tile<I, J/2, half2> get_half2(const tile<I, J, float> & tile_float) {
|
| 747 |
+
tile<I, J/2, half2> ret;
|
| 748 |
+
#pragma unroll
|
| 749 |
+
for (int l0 = 0; l0 < tile_float.ne; l0 += 2) {
|
| 750 |
+
ret.x[l0/2] = make_half2(tile_float.x[l0 + 0], tile_float.x[l0 + 1]);
|
| 751 |
+
}
|
| 752 |
+
return ret;
|
| 753 |
+
}
|
| 754 |
+
|
| 755 |
+
static __device__ __forceinline__ tile<8, 8, half2> get_transposed(const tile<16, 4, half2> & t) {
|
| 756 |
+
NO_DEVICE_CODE;
|
| 757 |
+
return tile<8, 8, half2>{};
|
| 758 |
+
}
|
| 759 |
+
#else // Volta
|
| 760 |
+
template <int I, int J>
|
| 761 |
+
static __device__ __forceinline__ tile<I, J/2, half2> get_half2(const tile<I, J, float> & tile_float) {
|
| 762 |
+
tile<I, J/2, half2> ret;
|
| 763 |
+
#pragma unroll
|
| 764 |
+
for (int l0 = 0; l0 < tile_float.ne; l0 += 4) {
|
| 765 |
+
ret.x[l0/2 + 0] = make_half2(tile_float.x[l0 + 0], tile_float.x[l0 + 1]);
|
| 766 |
+
ret.x[l0/2 + 1] = make_half2(tile_float.x[l0 + 2], tile_float.x[l0 + 3]);
|
| 767 |
+
|
| 768 |
+
// On Volta FP16 and FP32 tiles have a different memory layout,
|
| 769 |
+
// for the conversion threads with an offset of 2 need to exchange half their values:
|
| 770 |
+
ret.x[l0/2 + (((threadIdx.x % 4) / 2) ^ 1)] = __shfl_xor_sync(
|
| 771 |
+
0xFFFFFFFF, ret.x[l0/2 + (((threadIdx.x % 4) / 2) ^ 1)], 2, WARP_SIZE);
|
| 772 |
+
}
|
| 773 |
+
return ret;
|
| 774 |
+
}
|
| 775 |
+
#endif // defined(TURING_MMA_AVAILABLE)
|
| 776 |
+
|
| 777 |
+
template <int I, int J, typename T, data_layout dl>
|
| 778 |
+
static __device__ __forceinline__ void load_generic(tile<I, J, T, dl> & t, const T * __restrict__ xs0, const int stride) {
|
| 779 |
+
#pragma unroll
|
| 780 |
+
for (int l = 0; l < t.ne; ++l) {
|
| 781 |
+
t.x[l] = xs0[t.get_i(l)*stride + t.get_j(l)];
|
| 782 |
+
}
|
| 783 |
+
}
|
| 784 |
+
|
| 785 |
+
template <typename T>
|
| 786 |
+
static __device__ __forceinline__ void load_ldmatrix(
|
| 787 |
+
tile<8, 8, T> & t, const T * __restrict__ xs0, const int stride) {
|
| 788 |
+
#ifdef TURING_MMA_AVAILABLE
|
| 789 |
+
int * xi = (int *) t.x;
|
| 790 |
+
const int * xs = (const int *) xs0 + (threadIdx.x % t.I) * stride + ((threadIdx.x / t.I) * (t.J / 2)) % t.J;
|
| 791 |
+
asm volatile("ldmatrix.sync.aligned.m8n8.x2.b16 {%0, %1}, [%2];"
|
| 792 |
+
: "=r"(xi[0]), "=r"(xi[1])
|
| 793 |
+
: "l"(xs));
|
| 794 |
+
#else
|
| 795 |
+
GGML_UNUSED_VARS(t, xs0, stride);
|
| 796 |
+
NO_DEVICE_CODE;
|
| 797 |
+
#endif // TURING_MMA_AVAILABLE
|
| 798 |
+
}
|
| 799 |
+
|
| 800 |
+
template <typename T, data_layout dl>
|
| 801 |
+
static __device__ __forceinline__ void load_ldmatrix(
|
| 802 |
+
tile<16, 4, T, dl> & t, const T * __restrict__ xs0, const int stride) {
|
| 803 |
+
#ifdef TURING_MMA_AVAILABLE
|
| 804 |
+
int * xi = (int *) t.x;
|
| 805 |
+
const int * xs = (const int *) xs0 + (threadIdx.x % t.I) * stride;
|
| 806 |
+
asm volatile("ldmatrix.sync.aligned.m8n8.x2.b16 {%0, %1}, [%2];"
|
| 807 |
+
: "=r"(xi[0]), "=r"(xi[1])
|
| 808 |
+
: "l"(xs));
|
| 809 |
+
#elif defined(AMD_WMMA_AVAILABLE)
|
| 810 |
+
#ifdef RDNA3
|
| 811 |
+
static_assert(dl == DATA_LAYOUT_I_MAJOR_MIRRORED, "bad data layout");
|
| 812 |
+
static_assert(sizeof(t.x) == 16, "bad ne");
|
| 813 |
+
ggml_cuda_memcpy_1<8>(t.x + 0, xs0 + t.get_i(0)*stride + 0);
|
| 814 |
+
ggml_cuda_memcpy_1<8>(t.x + 2, xs0 + t.get_i(0)*stride + 2);
|
| 815 |
+
#else
|
| 816 |
+
static_assert(dl == DATA_LAYOUT_I_MAJOR, "bad data layout");
|
| 817 |
+
static_assert(sizeof(t.x) == 8, "bad ne");
|
| 818 |
+
ggml_cuda_memcpy_1<8>(t.x, xs0 + t.get_i(0)*stride + t.get_j(0));
|
| 819 |
+
#endif // RDNA3
|
| 820 |
+
#elif defined(AMD_MFMA_AVAILABLE)
|
| 821 |
+
static_assert(sizeof(t.x) == 4, "bad ne");
|
| 822 |
+
ggml_cuda_memcpy_1<4>(t.x, xs0 + t.get_i(0)*stride + t.get_j(0));
|
| 823 |
+
#else
|
| 824 |
+
GGML_UNUSED_VARS(t, xs0, stride);
|
| 825 |
+
NO_DEVICE_CODE;
|
| 826 |
+
#endif // TURING_MMA_AVAILABLE
|
| 827 |
+
}
|
| 828 |
+
|
| 829 |
+
template <typename T, data_layout dl>
|
| 830 |
+
static __device__ __forceinline__ void load_ldmatrix(
|
| 831 |
+
tile<16, 8, T, dl> & t, const T * __restrict__ xs0, const int stride) {
|
| 832 |
+
#if defined(TURING_MMA_AVAILABLE)
|
| 833 |
+
int * xi = (int * ) t.x;
|
| 834 |
+
const int * xs = (const int *) xs0 + (threadIdx.x % t.I) * stride + (threadIdx.x / t.I) * (t.J / 2);
|
| 835 |
+
asm volatile("ldmatrix.sync.aligned.m8n8.x4.b16 {%0, %1, %2, %3}, [%4];"
|
| 836 |
+
: "=r"(xi[0]), "=r"(xi[1]), "=r"(xi[2]), "=r"(xi[3])
|
| 837 |
+
: "l"(xs));
|
| 838 |
+
#elif defined(VOLTA_MMA_AVAILABLE)
|
| 839 |
+
ggml_cuda_memcpy_1<4*sizeof(T)>(t.x + 0, xs0 + t.get_i(0)*stride + 0);
|
| 840 |
+
ggml_cuda_memcpy_1<4*sizeof(T)>(t.x + 4, xs0 + t.get_i(4)*stride + 4);
|
| 841 |
+
#elif defined(AMD_WMMA_AVAILABLE)
|
| 842 |
+
#ifdef RDNA3
|
| 843 |
+
static_assert(dl == DATA_LAYOUT_I_MAJOR_MIRRORED, "bad data layout");
|
| 844 |
+
static_assert(sizeof(t.x) == 32, "bad ne");
|
| 845 |
+
ggml_cuda_memcpy_1<16>(t.x + 0, xs0 + t.get_i(0)*stride + 0);
|
| 846 |
+
ggml_cuda_memcpy_1<16>(t.x + 4, xs0 + t.get_i(0)*stride + 4);
|
| 847 |
+
#else
|
| 848 |
+
static_assert(dl == DATA_LAYOUT_I_MAJOR, "bad data layout");
|
| 849 |
+
static_assert(sizeof(t.x) == 16, "bad ne");
|
| 850 |
+
ggml_cuda_memcpy_1<16>(t.x, xs0 + t.get_i(0)*stride + t.get_j(0));
|
| 851 |
+
#endif // RDNA3
|
| 852 |
+
#elif defined(AMD_MFMA_AVAILABLE)
|
| 853 |
+
static_assert(sizeof(t.x) == 8, "bad ne");
|
| 854 |
+
ggml_cuda_memcpy_1<8>(t.x, xs0 + t.get_i(0)*stride + t.get_j(0));
|
| 855 |
+
#else
|
| 856 |
+
GGML_UNUSED_VARS(t, xs0, stride);
|
| 857 |
+
NO_DEVICE_CODE;
|
| 858 |
+
#endif // TURING_MMA_AVAILABLE
|
| 859 |
+
}
|
| 860 |
+
|
| 861 |
+
static __device__ __forceinline__ void load_ldmatrix(
|
| 862 |
+
tile<8, 4, half2, DATA_LAYOUT_I_MAJOR_MIRRORED> & t, const half2 * __restrict__ xs0, const int stride) {
|
| 863 |
+
ggml_cuda_memcpy_1<4*sizeof(half2)>(t.x, xs0 + t.get_i(0)*stride);
|
| 864 |
+
}
|
| 865 |
+
|
| 866 |
+
static __device__ __forceinline__ void load_ldmatrix(
|
| 867 |
+
tile<8, 4, half2, DATA_LAYOUT_J_MAJOR_MIRRORED> & t, const half2 * __restrict__ xs0, const int stride) {
|
| 868 |
+
#pragma unroll
|
| 869 |
+
for (int l0 = 0; l0 < t.ne; l0 += 2) {
|
| 870 |
+
ggml_cuda_memcpy_1<2*sizeof(half2)>(t.x + l0, xs0 + t.get_i(l0)*stride + t.get_j(l0));
|
| 871 |
+
}
|
| 872 |
+
}
|
| 873 |
+
|
| 874 |
+
static __device__ __forceinline__ void load_ldmatrix(
|
| 875 |
+
tile<32, 4, half2> & t, const half2 * __restrict__ xs0, const int stride) {
|
| 876 |
+
#if defined(VOLTA_MMA_AVAILABLE)
|
| 877 |
+
ggml_cuda_memcpy_1<4*sizeof(half2)>(t.x, xs0 + t.get_i(0)*stride);
|
| 878 |
+
#else
|
| 879 |
+
GGML_UNUSED_VARS(t, xs0, stride);
|
| 880 |
+
NO_DEVICE_CODE;
|
| 881 |
+
#endif // defined(VOLTA_MMA_AVAILABLE)
|
| 882 |
+
}
|
| 883 |
+
|
| 884 |
+
template <int I, typename T, data_layout dl>
|
| 885 |
+
static __device__ __forceinline__ void load_ldmatrix_trans(
|
| 886 |
+
tile<I, 8, T, dl> & t, const T * __restrict__ xs0, const int stride) {
|
| 887 |
+
#ifdef TURING_MMA_AVAILABLE
|
| 888 |
+
static_assert(I == 16, "bad tile width");
|
| 889 |
+
static_assert(dl == DATA_LAYOUT_I_MAJOR, "bad data layout");
|
| 890 |
+
int * xi = (int *) t.x;
|
| 891 |
+
const int * xs = (const int *) xs0 + (threadIdx.x % t.I) * stride + (threadIdx.x / t.I) * (t.J / 2);
|
| 892 |
+
asm volatile("ldmatrix.sync.aligned.m8n8.x4.trans.b16 {%0, %1, %2, %3}, [%4];"
|
| 893 |
+
: "=r"(xi[0]), "=r"(xi[2]), "=r"(xi[1]), "=r"(xi[3])
|
| 894 |
+
: "l"(xs));
|
| 895 |
+
#elif defined(AMD_MFMA_AVAILABLE) || defined(AMD_WMMA_AVAILABLE)
|
| 896 |
+
static_assert(dl == DATA_LAYOUT_I_MAJOR || dl == DATA_LAYOUT_I_MAJOR_MIRRORED, "bad data layout");
|
| 897 |
+
if constexpr (I == 32) {
|
| 898 |
+
#pragma unroll
|
| 899 |
+
for (int l0 = 0; l0 < t.ne/2; ++l0) {
|
| 900 |
+
const half2 tmp0 = xs0[(2*t.get_j(l0) + 0)*stride + t.get_i(l0)/2];
|
| 901 |
+
const half2 tmp1 = xs0[(2*t.get_j(l0) + 1)*stride + t.get_i(l0)/2];
|
| 902 |
+
|
| 903 |
+
t.x[l0] = __lows2half2(tmp0, tmp1);
|
| 904 |
+
t.x[l0 + t.ne/2] = __highs2half2(tmp0, tmp1);
|
| 905 |
+
}
|
| 906 |
+
} else {
|
| 907 |
+
half * xh = (half *) t.x;
|
| 908 |
+
#pragma unroll
|
| 909 |
+
for (int l = 0; l < t.ne; ++l) {
|
| 910 |
+
xh[2*l + 0] = ((const half *) xs0)[(2*t.get_j(l) + 0)*(2*stride) + t.get_i(l)];
|
| 911 |
+
xh[2*l + 1] = ((const half *) xs0)[(2*t.get_j(l) + 1)*(2*stride) + t.get_i(l)];
|
| 912 |
+
}
|
| 913 |
+
}
|
| 914 |
+
#else
|
| 915 |
+
GGML_UNUSED_VARS(t, xs0, stride);
|
| 916 |
+
NO_DEVICE_CODE;
|
| 917 |
+
#endif // TURING_MMA_AVAILABLE
|
| 918 |
+
}
|
| 919 |
+
|
| 920 |
+
static __device__ __forceinline__ void mma(
|
| 921 |
+
tile<16, 8, int> & D, const tile<16, 4, int> & A, const tile<8, 4, int> & B) {
|
| 922 |
+
#ifdef TURING_MMA_AVAILABLE
|
| 923 |
+
#if __CUDA_ARCH__ >= GGML_CUDA_CC_AMPERE
|
| 924 |
+
asm("mma.sync.aligned.m16n8k16.row.col.s32.s8.s8.s32 {%0, %1, %2, %3}, {%4, %5}, {%6}, {%0, %1, %2, %3};"
|
| 925 |
+
: "+r"(D.x[0]), "+r"(D.x[1]), "+r"(D.x[2]), "+r"(D.x[3])
|
| 926 |
+
: "r"(A.x[0]), "r"(A.x[1]), "r"(B.x[0]));
|
| 927 |
+
#else
|
| 928 |
+
// On Turing m16n8k16 mma is not available, use 2x m8n8k16 mma instead:
|
| 929 |
+
asm("mma.sync.aligned.m8n8k16.row.col.s32.s8.s8.s32 {%0, %1}, {%2}, {%3}, {%0, %1};"
|
| 930 |
+
: "+r"(D.x[0]), "+r"(D.x[1])
|
| 931 |
+
: "r"(A.x[0]), "r"(B.x[0]));
|
| 932 |
+
asm("mma.sync.aligned.m8n8k16.row.col.s32.s8.s8.s32 {%0, %1}, {%2}, {%3}, {%0, %1};"
|
| 933 |
+
: "+r"(D.x[2]), "+r"(D.x[3])
|
| 934 |
+
: "r"(A.x[1]), "r"(B.x[0]));
|
| 935 |
+
#endif // __CUDA_ARCH__ >= GGML_CUDA_CC_AMPERE
|
| 936 |
+
#else
|
| 937 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 938 |
+
NO_DEVICE_CODE;
|
| 939 |
+
#endif // TURING_MMA_AVAILABLE
|
| 940 |
+
}
|
| 941 |
+
|
| 942 |
+
static __device__ __forceinline__ void mma(
|
| 943 |
+
tile<16, 8, int> & D, const tile<16, 8, int> & A, const tile<8, 8, int> & B) {
|
| 944 |
+
#ifdef TURING_MMA_AVAILABLE
|
| 945 |
+
#if __CUDA_ARCH__ >= GGML_CUDA_CC_AMPERE
|
| 946 |
+
asm("mma.sync.aligned.m16n8k32.row.col.s32.s8.s8.s32 {%0, %1, %2, %3}, {%4, %5, %6, %7}, {%8, %9}, {%0, %1, %2, %3};"
|
| 947 |
+
: "+r"(D.x[0]), "+r"(D.x[1]), "+r"(D.x[2]), "+r"(D.x[3])
|
| 948 |
+
: "r"(A.x[0]), "r"(A.x[1]), "r"(A.x[2]), "r"(A.x[3]), "r"(B.x[0]), "r"(B.x[1]));
|
| 949 |
+
#else
|
| 950 |
+
// On Turing m16n8k32 mma is not available, use 4x m8n8k16 mma instead:
|
| 951 |
+
asm("mma.sync.aligned.m8n8k16.row.col.s32.s8.s8.s32 {%0, %1}, {%2}, {%3}, {%0, %1};"
|
| 952 |
+
: "+r"(D.x[0]), "+r"(D.x[1])
|
| 953 |
+
: "r"(A.x[0]), "r"(B.x[0]));
|
| 954 |
+
asm("mma.sync.aligned.m8n8k16.row.col.s32.s8.s8.s32 {%0, %1}, {%2}, {%3}, {%0, %1};"
|
| 955 |
+
: "+r"(D.x[2]), "+r"(D.x[3])
|
| 956 |
+
: "r"(A.x[1]), "r"(B.x[0]));
|
| 957 |
+
asm("mma.sync.aligned.m8n8k16.row.col.s32.s8.s8.s32 {%0, %1}, {%2}, {%3}, {%0, %1};"
|
| 958 |
+
: "+r"(D.x[0]), "+r"(D.x[1])
|
| 959 |
+
: "r"(A.x[2]), "r"(B.x[1]));
|
| 960 |
+
asm("mma.sync.aligned.m8n8k16.row.col.s32.s8.s8.s32 {%0, %1}, {%2}, {%3}, {%0, %1};"
|
| 961 |
+
: "+r"(D.x[2]), "+r"(D.x[3])
|
| 962 |
+
: "r"(A.x[3]), "r"(B.x[1]));
|
| 963 |
+
#endif // __CUDA_ARCH__ >= GGML_CUDA_CC_AMPERE
|
| 964 |
+
#else
|
| 965 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 966 |
+
NO_DEVICE_CODE;
|
| 967 |
+
#endif // TURING_MMA_AVAILABLE
|
| 968 |
+
}
|
| 969 |
+
|
| 970 |
+
static __device__ __forceinline__ void mma(
|
| 971 |
+
tile<16, 4, half2> & D, const tile<16, 8, half2> & A, const tile<8, 8, half2> & B) {
|
| 972 |
+
#ifdef TURING_MMA_AVAILABLE
|
| 973 |
+
const int * Axi = (const int *) A.x;
|
| 974 |
+
const int * Bxi = (const int *) B.x;
|
| 975 |
+
int * Dxi = (int *) D.x;
|
| 976 |
+
#if __CUDA_ARCH__ >= GGML_CUDA_CC_AMPERE
|
| 977 |
+
asm("mma.sync.aligned.m16n8k16.row.col.f16.f16.f16.f16 {%0, %1}, {%2, %3, %4, %5}, {%6, %7}, {%0, %1};"
|
| 978 |
+
: "+r"(Dxi[0]), "+r"(Dxi[1])
|
| 979 |
+
: "r"(Axi[0]), "r"(Axi[1]), "r"(Axi[2]), "r"(Axi[3]), "r"(Bxi[0]), "r"(Bxi[1]));
|
| 980 |
+
#else
|
| 981 |
+
// On Turing m16n8k16 mma is not available, use 2x m8n8k8 mma instead:
|
| 982 |
+
asm("mma.sync.aligned.m16n8k8.row.col.f16.f16.f16.f16 {%0, %1}, {%2, %3}, {%4}, {%0, %1};"
|
| 983 |
+
: "+r"(Dxi[0]), "+r"(Dxi[1])
|
| 984 |
+
: "r"(Axi[0]), "r"(Axi[1]), "r"(Bxi[0]));
|
| 985 |
+
asm("mma.sync.aligned.m16n8k8.row.col.f16.f16.f16.f16 {%0, %1}, {%2, %3}, {%4}, {%0, %1};"
|
| 986 |
+
: "+r"(Dxi[0]), "+r"(Dxi[1])
|
| 987 |
+
: "r"(Axi[2]), "r"(Axi[3]), "r"(Bxi[1]));
|
| 988 |
+
#endif // __CUDA_ARCH__ >= GGML_CUDA_CC_AMPERE
|
| 989 |
+
#else
|
| 990 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 991 |
+
NO_DEVICE_CODE;
|
| 992 |
+
#endif // TURING_MMA_AVAILABLE
|
| 993 |
+
}
|
| 994 |
+
|
| 995 |
+
static __device__ __forceinline__ void mma(
|
| 996 |
+
tile<16, 8, half2> & D, const tile<16, 8, half2> & A, const tile<16, 8, half2> & B) {
|
| 997 |
+
#ifdef TURING_MMA_AVAILABLE
|
| 998 |
+
const int * Axi = (const int *) A.x;
|
| 999 |
+
const int * Bxi = (const int *) B.x;
|
| 1000 |
+
int * Dxi = (int *) D.x;
|
| 1001 |
+
#if __CUDA_ARCH__ >= GGML_CUDA_CC_AMPERE
|
| 1002 |
+
asm("mma.sync.aligned.m16n8k16.row.col.f16.f16.f16.f16 {%0, %1}, {%2, %3, %4, %5}, {%6, %7}, {%0, %1};"
|
| 1003 |
+
: "+r"(Dxi[0]), "+r"(Dxi[1])
|
| 1004 |
+
: "r"(Axi[0]), "r"(Axi[1]), "r"(Axi[2]), "r"(Axi[3]), "r"(Bxi[0]), "r"(Bxi[2]));
|
| 1005 |
+
asm("mma.sync.aligned.m16n8k16.row.col.f16.f16.f16.f16 {%0, %1}, {%2, %3, %4, %5}, {%6, %7}, {%0, %1};"
|
| 1006 |
+
: "+r"(Dxi[2]), "+r"(Dxi[3])
|
| 1007 |
+
: "r"(Axi[0]), "r"(Axi[1]), "r"(Axi[2]), "r"(Axi[3]), "r"(Bxi[1]), "r"(Bxi[3]));
|
| 1008 |
+
#else
|
| 1009 |
+
// On Turing m16n8k16 mma is not available, use 4x m8n8k8 mma instead:
|
| 1010 |
+
asm("mma.sync.aligned.m16n8k8.row.col.f16.f16.f16.f16 {%0, %1}, {%2, %3}, {%4}, {%0, %1};"
|
| 1011 |
+
: "+r"(Dxi[0]), "+r"(Dxi[1])
|
| 1012 |
+
: "r"(Axi[0]), "r"(Axi[1]), "r"(Bxi[0]));
|
| 1013 |
+
asm("mma.sync.aligned.m16n8k8.row.col.f16.f16.f16.f16 {%0, %1}, {%2, %3}, {%4}, {%0, %1};"
|
| 1014 |
+
: "+r"(Dxi[0]), "+r"(Dxi[1])
|
| 1015 |
+
: "r"(Axi[2]), "r"(Axi[3]), "r"(Bxi[2]));
|
| 1016 |
+
asm("mma.sync.aligned.m16n8k8.row.col.f16.f16.f16.f16 {%0, %1}, {%2, %3}, {%4}, {%0, %1};"
|
| 1017 |
+
: "+r"(Dxi[2]), "+r"(Dxi[3])
|
| 1018 |
+
: "r"(Axi[0]), "r"(Axi[1]), "r"(Bxi[1]));
|
| 1019 |
+
asm("mma.sync.aligned.m16n8k8.row.col.f16.f16.f16.f16 {%0, %1}, {%2, %3}, {%4}, {%0, %1};"
|
| 1020 |
+
: "+r"(Dxi[2]), "+r"(Dxi[3])
|
| 1021 |
+
: "r"(Axi[2]), "r"(Axi[3]), "r"(Bxi[3]));
|
| 1022 |
+
#endif // __CUDA_ARCH__ >= GGML_CUDA_CC_AMPERE
|
| 1023 |
+
#elif defined(AMD_WMMA_AVAILABLE)
|
| 1024 |
+
#if defined(RDNA4)
|
| 1025 |
+
using halfx8_t = __attribute__((ext_vector_type(8))) _Float16;
|
| 1026 |
+
halfx8_t& acc_frag = reinterpret_cast<halfx8_t&>(D.x[0]);
|
| 1027 |
+
const halfx8_t& a_frag = reinterpret_cast<const halfx8_t&>(A.x[0]);
|
| 1028 |
+
const halfx8_t& b_frag = reinterpret_cast<const halfx8_t&>(B.x[0]);
|
| 1029 |
+
acc_frag = __builtin_amdgcn_wmma_f16_16x16x16_f16_w32_gfx12(a_frag, b_frag, acc_frag);
|
| 1030 |
+
#else
|
| 1031 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 1032 |
+
NO_DEVICE_CODE;
|
| 1033 |
+
#endif // defined(RDNA4)
|
| 1034 |
+
#elif defined(AMD_MFMA_AVAILABLE)
|
| 1035 |
+
// MFMA: FP16 input, FP32 accumulate, convert back to half2.
|
| 1036 |
+
using halfx4_t = __attribute__((ext_vector_type(4))) _Float16;
|
| 1037 |
+
using floatx4_t = __attribute__((ext_vector_type(4))) float;
|
| 1038 |
+
|
| 1039 |
+
// Convert existing half2 accumulator to float for MFMA:
|
| 1040 |
+
floatx4_t acc_f32;
|
| 1041 |
+
{
|
| 1042 |
+
const halfx4_t acc_h = reinterpret_cast<const halfx4_t&>(D.x[0]);
|
| 1043 |
+
#pragma unroll
|
| 1044 |
+
for (int i = 0; i < 4; ++i) {
|
| 1045 |
+
acc_f32[i] = (float)acc_h[i];
|
| 1046 |
+
}
|
| 1047 |
+
}
|
| 1048 |
+
|
| 1049 |
+
const halfx4_t& a_frag = reinterpret_cast<const halfx4_t&>(A.x[0]);
|
| 1050 |
+
const halfx4_t& b_frag = reinterpret_cast<const halfx4_t&>(B.x[0]);
|
| 1051 |
+
acc_f32 = __builtin_amdgcn_mfma_f32_16x16x16f16(a_frag, b_frag, acc_f32, 0, 0, 0);
|
| 1052 |
+
|
| 1053 |
+
// Convert back to half2:
|
| 1054 |
+
{
|
| 1055 |
+
halfx4_t result_h;
|
| 1056 |
+
#pragma unroll
|
| 1057 |
+
for (int i = 0; i < 4; ++i) {
|
| 1058 |
+
result_h[i] = (_Float16)acc_f32[i];
|
| 1059 |
+
}
|
| 1060 |
+
reinterpret_cast<halfx4_t&>(D.x[0]) = result_h;
|
| 1061 |
+
}
|
| 1062 |
+
#else
|
| 1063 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 1064 |
+
NO_DEVICE_CODE;
|
| 1065 |
+
#endif // TURING_MMA_AVAILABLE
|
| 1066 |
+
}
|
| 1067 |
+
|
| 1068 |
+
static __device__ __forceinline__ void mma(
|
| 1069 |
+
tile<16, 16, half2, DATA_LAYOUT_I_MAJOR_SCRAMBLED> & D, const tile<32, 8, half2, DATA_LAYOUT_I_MAJOR> & A,
|
| 1070 |
+
const tile<16, 8, half2, DATA_LAYOUT_I_MAJOR> & B) {
|
| 1071 |
+
#if defined(AMD_MFMA_AVAILABLE) || (defined(AMD_WMMA_AVAILABLE) && defined(RDNA4))
|
| 1072 |
+
tile<16, 8, half2> * D16 = (tile<16, 8, half2> *) &D;
|
| 1073 |
+
const tile<16, 8, half2> * A16 = (const tile<16, 8, half2> *) &A;
|
| 1074 |
+
mma(D16[0], A16[0], B);
|
| 1075 |
+
mma(D16[1], A16[1], B);
|
| 1076 |
+
#else
|
| 1077 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 1078 |
+
NO_DEVICE_CODE;
|
| 1079 |
+
#endif // defined(AMD_MFMA_AVAILABLE) || defined(AMD_WMMA_AVAILABLE) && defined(RDNA4)
|
| 1080 |
+
}
|
| 1081 |
+
|
| 1082 |
+
template <data_layout dl_ab, data_layout dl_d>
|
| 1083 |
+
static __device__ __forceinline__ void mma(
|
| 1084 |
+
tile<16, 8, float, dl_d> & D, const tile<16, 8, float, dl_ab> & A, const tile<8, 8, float, dl_ab> & B) {
|
| 1085 |
+
#ifdef AMPERE_MMA_AVAILABLE
|
| 1086 |
+
const int * Axi = (const int *) A.x;
|
| 1087 |
+
const int * Bxi = (const int *) B.x;
|
| 1088 |
+
int * Dxi = (int *) D.x;
|
| 1089 |
+
asm("mma.sync.aligned.m16n8k8.row.col.f32.tf32.tf32.f32 {%0, %1, %2, %3}, {%4, %5, %6, %7}, {%8, %9}, {%0, %1, %2, %3};"
|
| 1090 |
+
: "+r"(Dxi[0]), "+r"(Dxi[1]), "+r"(Dxi[2]), "+r"(Dxi[3])
|
| 1091 |
+
: "r"(Axi[0]), "r"(Axi[1]), "r"(Axi[2]), "r"(Axi[3]), "r"(Bxi[0]), "r"(Bxi[1]));
|
| 1092 |
+
#else
|
| 1093 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 1094 |
+
NO_DEVICE_CODE;
|
| 1095 |
+
#endif // AMPERE_MMA_AVAILABLE
|
| 1096 |
+
}
|
| 1097 |
+
|
| 1098 |
+
template <data_layout dl_ab, data_layout dl_d>
|
| 1099 |
+
static __device__ __forceinline__ void mma(
|
| 1100 |
+
tile<16, 16, float, dl_d> & D, const tile<16, 8, float, dl_ab> & A, const tile<16, 8, float, dl_ab> & B) {
|
| 1101 |
+
#ifdef AMD_MFMA_AVAILABLE
|
| 1102 |
+
using floatx4_t = __attribute__((ext_vector_type(4))) float;
|
| 1103 |
+
floatx4_t& acc_frag = reinterpret_cast<floatx4_t&>(D.x[0]);
|
| 1104 |
+
#if defined(CDNA3)
|
| 1105 |
+
using floatx2_t = __attribute__((ext_vector_type(2))) float;
|
| 1106 |
+
const floatx2_t& a_frag = reinterpret_cast<const floatx2_t&>(A.x[0]);
|
| 1107 |
+
const floatx2_t& b_frag = reinterpret_cast<const floatx2_t&>(B.x[0]);
|
| 1108 |
+
acc_frag = __builtin_amdgcn_mfma_f32_16x16x8_xf32(a_frag, b_frag, acc_frag, 0, 0, 0);
|
| 1109 |
+
#elif defined(CDNA4) || defined(CDNA2) || defined(CDNA1)
|
| 1110 |
+
// CDNA4 (gfx950) does not support xf32 MFMA, use f32 path like CDNA2/CDNA1
|
| 1111 |
+
#pragma unroll
|
| 1112 |
+
for (int i = 0; i < 2; ++i) {
|
| 1113 |
+
acc_frag = __builtin_amdgcn_mfma_f32_16x16x4f32(A.x[i], B.x[i], acc_frag, 0, 0, 0);
|
| 1114 |
+
}
|
| 1115 |
+
#else
|
| 1116 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 1117 |
+
NO_DEVICE_CODE;
|
| 1118 |
+
#endif // defined(CDNA3)
|
| 1119 |
+
#else
|
| 1120 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 1121 |
+
NO_DEVICE_CODE;
|
| 1122 |
+
#endif // AMD_MFMA_AVAILABLE
|
| 1123 |
+
}
|
| 1124 |
+
|
| 1125 |
+
template <ggml_type type>
|
| 1126 |
+
static __device__ __forceinline__ void mma_block_scaled_fp4(tile<16, 8, float> & D,
|
| 1127 |
+
const tile<16, 8, int> & A,
|
| 1128 |
+
const tile<8, 8, int> & B,
|
| 1129 |
+
uint32_t a_scale,
|
| 1130 |
+
uint32_t b_scale) {
|
| 1131 |
+
#ifdef BLACKWELL_MMA_AVAILABLE
|
| 1132 |
+
const int * Axi = (const int *) A.x;
|
| 1133 |
+
const int * Bxi = (const int *) B.x;
|
| 1134 |
+
float * Dxi = (float *) D.x;
|
| 1135 |
+
|
| 1136 |
+
if constexpr (type == GGML_TYPE_MXFP4) {
|
| 1137 |
+
asm volatile(
|
| 1138 |
+
"mma.sync.aligned.kind::mxf4.block_scale.scale_vec::2X.m16n8k64.row.col.f32.e2m1.e2m1.f32.ue8m0 "
|
| 1139 |
+
"{%0, %1, %2, %3}, {%4, %5, %6, %7}, {%8, %9}, {%0, %1, %2, %3}, "
|
| 1140 |
+
"%10, {0, 0}, %11, {0, 0};"
|
| 1141 |
+
: "+f"(Dxi[0]), "+f"(Dxi[1]), "+f"(Dxi[2]), "+f"(Dxi[3])
|
| 1142 |
+
: "r"(Axi[0]), "r"(Axi[1]), "r"(Axi[2]), "r"(Axi[3]), "r"(Bxi[0]), "r"(Bxi[1]), "r"(a_scale), "r"(b_scale));
|
| 1143 |
+
} else {
|
| 1144 |
+
asm volatile(
|
| 1145 |
+
"mma.sync.aligned.kind::mxf4nvf4.block_scale.scale_vec::4X.m16n8k64.row.col.f32.e2m1.e2m1.f32.ue4m3 "
|
| 1146 |
+
"{%0, %1, %2, %3}, {%4, %5, %6, %7}, {%8, %9}, {%0, %1, %2, %3}, "
|
| 1147 |
+
"%10, {0, 0}, %11, {0, 0};"
|
| 1148 |
+
: "+f"(Dxi[0]), "+f"(Dxi[1]), "+f"(Dxi[2]), "+f"(Dxi[3])
|
| 1149 |
+
: "r"(Axi[0]), "r"(Axi[1]), "r"(Axi[2]), "r"(Axi[3]), "r"(Bxi[0]), "r"(Bxi[1]), "r"(a_scale), "r"(b_scale));
|
| 1150 |
+
}
|
| 1151 |
+
#else
|
| 1152 |
+
GGML_UNUSED_VARS(D, A, B, a_scale, b_scale);
|
| 1153 |
+
#endif // BLACKWELL_MMA_AVAILABLE
|
| 1154 |
+
}
|
| 1155 |
+
|
| 1156 |
+
static __device__ __forceinline__ void mma(
|
| 1157 |
+
tile<16, 8, float> & D, const tile<16, 8, half2> & A, const tile<8, 8, half2> & B) {
|
| 1158 |
+
#ifdef TURING_MMA_AVAILABLE
|
| 1159 |
+
const int * Axi = (const int *) A.x;
|
| 1160 |
+
const int * Bxi = (const int *) B.x;
|
| 1161 |
+
int * Dxi = (int *) D.x;
|
| 1162 |
+
#if __CUDA_ARCH__ >= GGML_CUDA_CC_AMPERE
|
| 1163 |
+
asm("mma.sync.aligned.m16n8k16.row.col.f32.f16.f16.f32 {%0, %1, %2, %3}, {%4, %5, %6, %7}, {%8, %9}, {%0, %1, %2, %3};"
|
| 1164 |
+
: "+r"(Dxi[0]), "+r"(Dxi[1]), "+r"(Dxi[2]), "+r"(Dxi[3])
|
| 1165 |
+
: "r"(Axi[0]), "r"(Axi[1]), "r"(Axi[2]), "r"(Axi[3]), "r"(Bxi[0]), "r"(Bxi[1]));
|
| 1166 |
+
#else
|
| 1167 |
+
// On Turing m16n8k16 mma is not available, use 2x m8n8k8 mma instead:
|
| 1168 |
+
asm("mma.sync.aligned.m16n8k8.row.col.f32.f16.f16.f32 {%0, %1, %2, %3}, {%4, %5}, {%6}, {%0, %1, %2, %3};"
|
| 1169 |
+
: "+r"(Dxi[0]), "+r"(Dxi[1]), "+r"(Dxi[2]), "+r"(Dxi[3])
|
| 1170 |
+
: "r"(Axi[0]), "r"(Axi[1]), "r"(Bxi[0]));
|
| 1171 |
+
asm("mma.sync.aligned.m16n8k8.row.col.f32.f16.f16.f32 {%0, %1, %2, %3}, {%4, %5}, {%6}, {%0, %1, %2, %3};"
|
| 1172 |
+
: "+r"(Dxi[0]), "+r"(Dxi[1]), "+r"(Dxi[2]), "+r"(Dxi[3])
|
| 1173 |
+
: "r"(Axi[2]), "r"(Axi[3]), "r"(Bxi[1]));
|
| 1174 |
+
#endif // __CUDA_ARCH__ >= GGML_CUDA_CC_AMPERE
|
| 1175 |
+
#else
|
| 1176 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 1177 |
+
NO_DEVICE_CODE;
|
| 1178 |
+
#endif // TURING_MMA_AVAILABLE
|
| 1179 |
+
}
|
| 1180 |
+
|
| 1181 |
+
static __device__ __forceinline__ void mma(
|
| 1182 |
+
tile<16, 8, float> & D, const tile<16, 8, nv_bfloat162> & A, const tile<8, 8, nv_bfloat162> & B) {
|
| 1183 |
+
#ifdef AMPERE_MMA_AVAILABLE
|
| 1184 |
+
const int * Axi = (const int *) A.x;
|
| 1185 |
+
const int * Bxi = (const int *) B.x;
|
| 1186 |
+
int * Dxi = (int *) D.x;
|
| 1187 |
+
asm("mma.sync.aligned.m16n8k16.row.col.f32.bf16.bf16.f32 {%0, %1, %2, %3}, {%4, %5, %6, %7}, {%8, %9}, {%0, %1, %2, %3};"
|
| 1188 |
+
: "+r"(Dxi[0]), "+r"(Dxi[1]), "+r"(Dxi[2]), "+r"(Dxi[3])
|
| 1189 |
+
: "r"(Axi[0]), "r"(Axi[1]), "r"(Axi[2]), "r"(Axi[3]), "r"(Bxi[0]), "r"(Bxi[1]));
|
| 1190 |
+
#else
|
| 1191 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 1192 |
+
NO_DEVICE_CODE;
|
| 1193 |
+
#endif // AMPERE_MMA_AVAILABLE
|
| 1194 |
+
}
|
| 1195 |
+
|
| 1196 |
+
template <data_layout dl_ab, data_layout dl_d>
|
| 1197 |
+
static __device__ __forceinline__ void mma(
|
| 1198 |
+
tile<16, 16, float, dl_d> & D, const tile<16, 8, half2, dl_ab> & A, const tile<16, 8, half2, dl_ab> & B) {
|
| 1199 |
+
#ifdef TURING_MMA_AVAILABLE
|
| 1200 |
+
const int * Axi = (const int *) A.x;
|
| 1201 |
+
const int * Bxi = (const int *) B.x;
|
| 1202 |
+
int * Dxi = (int *) D.x;
|
| 1203 |
+
#if __CUDA_ARCH__ >= GGML_CUDA_CC_AMPERE
|
| 1204 |
+
asm("mma.sync.aligned.m16n8k16.row.col.f32.f16.f16.f32 {%0, %1, %2, %3}, {%4, %5, %6, %7}, {%8, %9}, {%0, %1, %2, %3};"
|
| 1205 |
+
: "+r"(Dxi[0]), "+r"(Dxi[1]), "+r"(Dxi[2]), "+r"(Dxi[3])
|
| 1206 |
+
: "r"(Axi[0]), "r"(Axi[1]), "r"(Axi[2]), "r"(Axi[3]), "r"(Bxi[0]), "r"(Bxi[2]));
|
| 1207 |
+
asm("mma.sync.aligned.m16n8k16.row.col.f32.f16.f16.f32 {%0, %1, %2, %3}, {%4, %5, %6, %7}, {%8, %9}, {%0, %1, %2, %3};"
|
| 1208 |
+
: "+r"(Dxi[4]), "+r"(Dxi[5]), "+r"(Dxi[6]), "+r"(Dxi[7])
|
| 1209 |
+
: "r"(Axi[0]), "r"(Axi[1]), "r"(Axi[2]), "r"(Axi[3]), "r"(Bxi[1]), "r"(Bxi[3]));
|
| 1210 |
+
#else
|
| 1211 |
+
// On Turing m16n8k16 mma is not available, use 4x m8n8k8 mma instead:
|
| 1212 |
+
asm("mma.sync.aligned.m16n8k8.row.col.f32.f16.f16.f32 {%0, %1, %2, %3}, {%4, %5}, {%6}, {%0, %1, %2, %3};"
|
| 1213 |
+
: "+r"(Dxi[0]), "+r"(Dxi[1]), "+r"(Dxi[2]), "+r"(Dxi[3])
|
| 1214 |
+
: "r"(Axi[0]), "r"(Axi[1]), "r"(Bxi[0]));
|
| 1215 |
+
asm("mma.sync.aligned.m16n8k8.row.col.f32.f16.f16.f32 {%0, %1, %2, %3}, {%4, %5}, {%6}, {%0, %1, %2, %3};"
|
| 1216 |
+
: "+r"(Dxi[0]), "+r"(Dxi[1]), "+r"(Dxi[2]), "+r"(Dxi[3])
|
| 1217 |
+
: "r"(Axi[2]), "r"(Axi[3]), "r"(Bxi[2]));
|
| 1218 |
+
asm("mma.sync.aligned.m16n8k8.row.col.f32.f16.f16.f32 {%0, %1, %2, %3}, {%4, %5}, {%6}, {%0, %1, %2, %3};"
|
| 1219 |
+
: "+r"(Dxi[4]), "+r"(Dxi[5]), "+r"(Dxi[6]), "+r"(Dxi[7])
|
| 1220 |
+
: "r"(Axi[0]), "r"(Axi[1]), "r"(Bxi[1]));
|
| 1221 |
+
asm("mma.sync.aligned.m16n8k8.row.col.f32.f16.f16.f32 {%0, %1, %2, %3}, {%4, %5}, {%6}, {%0, %1, %2, %3};"
|
| 1222 |
+
: "+r"(Dxi[4]), "+r"(Dxi[5]), "+r"(Dxi[6]), "+r"(Dxi[7])
|
| 1223 |
+
: "r"(Axi[2]), "r"(Axi[3]), "r"(Bxi[3]));
|
| 1224 |
+
#endif // __CUDA_ARCH__ >= GGML_CUDA_CC_AMPERE
|
| 1225 |
+
#elif defined(AMD_WMMA_AVAILABLE)
|
| 1226 |
+
#if defined(RDNA4)
|
| 1227 |
+
using halfx8_t = __attribute__((ext_vector_type(8))) _Float16;
|
| 1228 |
+
using floatx8_t = __attribute__((ext_vector_type(8))) float;
|
| 1229 |
+
floatx8_t& acc_frag = reinterpret_cast<floatx8_t&>(D.x[0]);
|
| 1230 |
+
const halfx8_t& a_frag = reinterpret_cast<const halfx8_t&>(A.x[0]);
|
| 1231 |
+
const halfx8_t& b_frag = reinterpret_cast<const halfx8_t&>(B.x[0]);
|
| 1232 |
+
acc_frag = __builtin_amdgcn_wmma_f32_16x16x16_f16_w32_gfx12(a_frag, b_frag, acc_frag);
|
| 1233 |
+
#elif defined(RDNA3)
|
| 1234 |
+
using halfx16_t = __attribute__((ext_vector_type(16))) _Float16;
|
| 1235 |
+
using floatx8_t = __attribute__((ext_vector_type(8))) float;
|
| 1236 |
+
floatx8_t& acc_frag = reinterpret_cast<floatx8_t&>(D.x[0]);
|
| 1237 |
+
const halfx16_t& a_frag = reinterpret_cast<const halfx16_t&>(A.x[0]);
|
| 1238 |
+
const halfx16_t& b_frag = reinterpret_cast<const halfx16_t&>(B.x[0]);
|
| 1239 |
+
acc_frag = __builtin_amdgcn_wmma_f32_16x16x16_f16_w32(a_frag, b_frag, acc_frag);
|
| 1240 |
+
#else
|
| 1241 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 1242 |
+
NO_DEVICE_CODE;
|
| 1243 |
+
#endif // RDNA4
|
| 1244 |
+
#elif defined(AMD_MFMA_AVAILABLE)
|
| 1245 |
+
using halfx4_t = __attribute__((ext_vector_type(4))) _Float16;
|
| 1246 |
+
using floatx4_t = __attribute__((ext_vector_type(4))) float;
|
| 1247 |
+
floatx4_t& acc_frag = reinterpret_cast<floatx4_t&>(D.x[0]);
|
| 1248 |
+
const halfx4_t& a_frag = reinterpret_cast<const halfx4_t&>(A.x[0]);
|
| 1249 |
+
const halfx4_t& b_frag = reinterpret_cast<const halfx4_t&>(B.x[0]);
|
| 1250 |
+
acc_frag = __builtin_amdgcn_mfma_f32_16x16x16f16(a_frag, b_frag, acc_frag, 0, 0, 0);
|
| 1251 |
+
#else
|
| 1252 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 1253 |
+
NO_DEVICE_CODE;
|
| 1254 |
+
#endif // TURING_MMA_AVAILABLE
|
| 1255 |
+
}
|
| 1256 |
+
|
| 1257 |
+
template <data_layout dl_ab, data_layout dl_d>
|
| 1258 |
+
static __device__ __forceinline__ void mma(
|
| 1259 |
+
tile<16, 16, float, dl_d> & D, const tile<16, 8, nv_bfloat162, dl_ab> & A, const tile<16, 8, nv_bfloat162, dl_ab> & B) {
|
| 1260 |
+
#if defined(AMD_WMMA_AVAILABLE)
|
| 1261 |
+
#if defined(RDNA4)
|
| 1262 |
+
using bf16x8_t = __attribute__((ext_vector_type(8))) __bf16;
|
| 1263 |
+
using floatx8_t = __attribute__((ext_vector_type(8))) float;
|
| 1264 |
+
floatx8_t& acc_frag = reinterpret_cast<floatx8_t&>(D.x[0]);
|
| 1265 |
+
const bf16x8_t& a_frag = reinterpret_cast<const bf16x8_t&>(A.x[0]);
|
| 1266 |
+
const bf16x8_t& b_frag = reinterpret_cast<const bf16x8_t&>(B.x[0]);
|
| 1267 |
+
acc_frag = __builtin_amdgcn_wmma_f32_16x16x16_bf16_w32_gfx12(a_frag, b_frag, acc_frag);
|
| 1268 |
+
#elif defined(RDNA3)
|
| 1269 |
+
using bf16x16_t = __attribute__((ext_vector_type(16))) __bf16;
|
| 1270 |
+
using floatx8_t = __attribute__((ext_vector_type(8))) float;
|
| 1271 |
+
floatx8_t& acc_frag = reinterpret_cast<floatx8_t&>(D.x[0]);
|
| 1272 |
+
const bf16x16_t& a_frag = reinterpret_cast<const bf16x16_t&>(A.x[0]);
|
| 1273 |
+
const bf16x16_t& b_frag = reinterpret_cast<const bf16x16_t&>(B.x[0]);
|
| 1274 |
+
acc_frag = __builtin_amdgcn_wmma_f32_16x16x16_bf16_w32(a_frag, b_frag, acc_frag);
|
| 1275 |
+
#else
|
| 1276 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 1277 |
+
NO_DEVICE_CODE;
|
| 1278 |
+
#endif // defined(RDNA4)
|
| 1279 |
+
#elif defined(AMD_MFMA_AVAILABLE)
|
| 1280 |
+
using floatx4_t = __attribute__((ext_vector_type(4))) float;
|
| 1281 |
+
floatx4_t& acc_frag = reinterpret_cast<floatx4_t&>(D.x[0]);
|
| 1282 |
+
#if defined(CDNA4) || defined(CDNA3) || defined(CDNA2)
|
| 1283 |
+
using bf16x4_t = __attribute__((ext_vector_type(4))) __bf16;
|
| 1284 |
+
const bf16x4_t& a_frag = reinterpret_cast<const bf16x4_t&>(A.x[0]);
|
| 1285 |
+
const bf16x4_t& b_frag = reinterpret_cast<const bf16x4_t&>(B.x[0]);
|
| 1286 |
+
acc_frag = __builtin_amdgcn_mfma_f32_16x16x16bf16_1k(a_frag, b_frag, acc_frag, 0, 0, 0);
|
| 1287 |
+
#elif defined(CDNA1)
|
| 1288 |
+
#pragma unroll
|
| 1289 |
+
for (int i = 0; i < 2; ++i) {
|
| 1290 |
+
using bf16x2_t = __attribute__((ext_vector_type(2))) __bf16;
|
| 1291 |
+
const bf16x2_t& a_frag = reinterpret_cast<const bf16x2_t&>(A.x[i]);
|
| 1292 |
+
const bf16x2_t& b_frag = reinterpret_cast<const bf16x2_t&>(B.x[i]);
|
| 1293 |
+
acc_frag = __builtin_amdgcn_mfma_f32_16x16x8bf16(a_frag, b_frag, acc_frag, 0, 0, 0);
|
| 1294 |
+
}
|
| 1295 |
+
#else
|
| 1296 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 1297 |
+
NO_DEVICE_CODE;
|
| 1298 |
+
#endif // defined(CDNA3) || defined(CDNA2)
|
| 1299 |
+
#else
|
| 1300 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 1301 |
+
NO_DEVICE_CODE;
|
| 1302 |
+
#endif // defined(AMD_WMMA_AVAILABLE)
|
| 1303 |
+
}
|
| 1304 |
+
|
| 1305 |
+
template <data_layout dl_d, data_layout dl_ab>
|
| 1306 |
+
static __device__ __forceinline__ void mma(
|
| 1307 |
+
tile<16, 16, int, dl_d> & D, const tile<16, 8, int, dl_ab> & A, const tile<16, 8, int, dl_ab> & B) {
|
| 1308 |
+
#if defined(AMD_MFMA_AVAILABLE)
|
| 1309 |
+
using int32x4_t = __attribute__((__vector_size__(4 * sizeof(int)))) int;
|
| 1310 |
+
int32x4_t * acc = (int32x4_t *) D.x;
|
| 1311 |
+
#if defined(CDNA4) || defined(CDNA3)
|
| 1312 |
+
acc[0] = __builtin_amdgcn_mfma_i32_16x16x32_i8(((int64_t *) A.x)[0], ((int64_t *) B.x)[0], acc[0], 0, 0, 0);
|
| 1313 |
+
#elif defined(CDNA2) || defined(CDNA1)
|
| 1314 |
+
acc[0] = __builtin_amdgcn_mfma_i32_16x16x16i8(A.x[0], B.x[0], acc[0], 0, 0, 0);
|
| 1315 |
+
acc[0] = __builtin_amdgcn_mfma_i32_16x16x16i8(A.x[1], B.x[1], acc[0], 0, 0, 0);
|
| 1316 |
+
#endif // defined(CDNA4) || defined(CDNA3)
|
| 1317 |
+
#elif defined(AMD_WMMA_AVAILABLE)
|
| 1318 |
+
using int32x8_t = __attribute__((__vector_size__(8 * sizeof(int)))) int;
|
| 1319 |
+
int32x8_t * acc = (int32x8_t *) D.x;
|
| 1320 |
+
#if defined(RDNA4)
|
| 1321 |
+
using int32x2_t = __attribute__((__vector_size__(2 * sizeof(int)))) int;
|
| 1322 |
+
int32x2_t * a_vec = (int32x2_t *) A.x;
|
| 1323 |
+
int32x2_t * b_vec = (int32x2_t *) B.x;
|
| 1324 |
+
acc[0] = __builtin_amdgcn_wmma_i32_16x16x16_iu8_w32_gfx12(true, a_vec[0], true, b_vec[0], acc[0], true);
|
| 1325 |
+
acc[0] = __builtin_amdgcn_wmma_i32_16x16x16_iu8_w32_gfx12(true, a_vec[1], true, b_vec[1], acc[0], true);
|
| 1326 |
+
#elif defined(RDNA3)
|
| 1327 |
+
using int32x4_t = __attribute__((__vector_size__(4 * sizeof(int)))) int;
|
| 1328 |
+
int32x4_t * a_vec = (int32x4_t *) A.x;
|
| 1329 |
+
int32x4_t * b_vec = (int32x4_t *) B.x;
|
| 1330 |
+
acc[0] = __builtin_amdgcn_wmma_i32_16x16x16_iu8_w32(true, a_vec[0], true, b_vec[0], acc[0], true);
|
| 1331 |
+
acc[0] = __builtin_amdgcn_wmma_i32_16x16x16_iu8_w32(true, a_vec[1], true, b_vec[1], acc[0], true);
|
| 1332 |
+
#endif // RDNA4
|
| 1333 |
+
#else
|
| 1334 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 1335 |
+
NO_DEVICE_CODE;
|
| 1336 |
+
#endif // AMD_MFMA_AVAILABLE
|
| 1337 |
+
}
|
| 1338 |
+
|
| 1339 |
+
static __device__ __forceinline__ void mma(
|
| 1340 |
+
tile<32, 32, int> & D, const tile<32, 4, int> & A, const tile<32, 4, int> & B) {
|
| 1341 |
+
#if defined(AMD_MFMA_AVAILABLE)
|
| 1342 |
+
using int32x16_t = __attribute__((__vector_size__(16 * sizeof(int)))) int;
|
| 1343 |
+
int32x16_t * acc = (int32x16_t *) D.x;
|
| 1344 |
+
#if defined(CDNA4) || defined(CDNA3)
|
| 1345 |
+
acc[0] = __builtin_amdgcn_mfma_i32_32x32x16_i8(((int64_t *) A.x)[0], ((int64_t *) B.x)[0], acc[0], 0, 0, 0);
|
| 1346 |
+
#elif defined(CDNA2) || defined(CDNA1)
|
| 1347 |
+
acc[0] = __builtin_amdgcn_mfma_i32_32x32x8i8(A.x[0], B.x[0], acc[0], 0, 0, 0);
|
| 1348 |
+
acc[0] = __builtin_amdgcn_mfma_i32_32x32x8i8(A.x[1], B.x[1], acc[0], 0, 0, 0);
|
| 1349 |
+
#endif // defined(CDNA4) || defined(CDNA3)
|
| 1350 |
+
|
| 1351 |
+
#else
|
| 1352 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 1353 |
+
NO_DEVICE_CODE;
|
| 1354 |
+
#endif // AMD_MFMA_AVAILABLE
|
| 1355 |
+
}
|
| 1356 |
+
|
| 1357 |
+
template <typename T1, typename T2, int J, int K>
|
| 1358 |
+
static __device__ __forceinline__ void mma(
|
| 1359 |
+
tile<32, J, T1> & D, const tile<32, K, T2> & A, const tile<J, K, T2> & B) {
|
| 1360 |
+
tile <16, J, T1> * D16 = reinterpret_cast< tile<16, J, T1> *>(&D);
|
| 1361 |
+
const tile<16, K, T2> * A16 = reinterpret_cast<const tile<16, K, T2> *>(&A);
|
| 1362 |
+
mma(D16[0], A16[0], B);
|
| 1363 |
+
mma(D16[1], A16[1], B);
|
| 1364 |
+
}
|
| 1365 |
+
|
| 1366 |
+
static __device__ __forceinline__ void mma(
|
| 1367 |
+
tile<32, 8, float> & D, const tile<32, 4, half2> & A, const tile<8, 4, half2, DATA_LAYOUT_I_MAJOR_MIRRORED> & B) {
|
| 1368 |
+
#if defined(VOLTA_MMA_AVAILABLE)
|
| 1369 |
+
const int * Axi = (const int *) A.x;
|
| 1370 |
+
const int * Bxi = (const int *) B.x;
|
| 1371 |
+
int * Dxi = (int *) D.x;
|
| 1372 |
+
asm("mma.sync.aligned.m8n8k4.row.col.f32.f16.f16.f32 "
|
| 1373 |
+
"{%0, %1, %2, %3, %4, %5, %6, %7}, {%8, %9}, {%10, %11}, {%0, %1, %2, %3, %4, %5, %6, %7};"
|
| 1374 |
+
: "+r"(Dxi[0]), "+r"(Dxi[1]), "+r"(Dxi[2]), "+r"(Dxi[3]), "+r"(Dxi[4]), "+r"(Dxi[5]), "+r"(Dxi[6]), "+r"(Dxi[7])
|
| 1375 |
+
: "r"(Axi[0]), "r"(Axi[1]), "r"(Bxi[0]), "r"(Bxi[1]));
|
| 1376 |
+
asm("mma.sync.aligned.m8n8k4.row.col.f32.f16.f16.f32 "
|
| 1377 |
+
"{%0, %1, %2, %3, %4, %5, %6, %7}, {%8, %9}, {%10, %11}, {%0, %1, %2, %3, %4, %5, %6, %7};"
|
| 1378 |
+
: "+r"(Dxi[0]), "+r"(Dxi[1]), "+r"(Dxi[2]), "+r"(Dxi[3]), "+r"(Dxi[4]), "+r"(Dxi[5]), "+r"(Dxi[6]), "+r"(Dxi[7])
|
| 1379 |
+
: "r"(Axi[2]), "r"(Axi[3]), "r"(Bxi[2]), "r"(Bxi[3]));
|
| 1380 |
+
#else
|
| 1381 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 1382 |
+
NO_DEVICE_CODE;
|
| 1383 |
+
#endif // defined(VOLTA_MMA_AVAILABLE)
|
| 1384 |
+
}
|
| 1385 |
+
|
| 1386 |
+
static __device__ __forceinline__ void mma(
|
| 1387 |
+
tile<32, 4, half2> & D, const tile<32, 4, half2> & A, const tile<8, 4, half2, DATA_LAYOUT_J_MAJOR_MIRRORED> & B) {
|
| 1388 |
+
#if defined(VOLTA_MMA_AVAILABLE)
|
| 1389 |
+
const int * Axi = (const int *) A.x;
|
| 1390 |
+
const int * Bxi = (const int *) B.x;
|
| 1391 |
+
int * Dxi = (int *) D.x;
|
| 1392 |
+
asm("mma.sync.aligned.m8n8k4.row.row.f16.f16.f16.f16 "
|
| 1393 |
+
"{%0, %1, %2, %3}, {%4, %5}, {%6, %7}, {%0, %1, %2, %3};"
|
| 1394 |
+
: "+r"(Dxi[0]), "+r"(Dxi[1]), "+r"(Dxi[2]), "+r"(Dxi[3])
|
| 1395 |
+
: "r"(Axi[0]), "r"(Axi[1]), "r"(Bxi[0]), "r"(Bxi[1]));
|
| 1396 |
+
asm("mma.sync.aligned.m8n8k4.row.row.f16.f16.f16.f16 "
|
| 1397 |
+
"{%0, %1, %2, %3}, {%4, %5}, {%6, %7}, {%0, %1, %2, %3};"
|
| 1398 |
+
: "+r"(Dxi[0]), "+r"(Dxi[1]), "+r"(Dxi[2]), "+r"(Dxi[3])
|
| 1399 |
+
: "r"(Axi[2]), "r"(Axi[3]), "r"(Bxi[2]), "r"(Bxi[3]));
|
| 1400 |
+
#else
|
| 1401 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 1402 |
+
NO_DEVICE_CODE;
|
| 1403 |
+
#endif // defined(VOLTA_MMA_AVAILABLE)
|
| 1404 |
+
}
|
| 1405 |
+
|
| 1406 |
+
static __device__ __forceinline__ void mma(
|
| 1407 |
+
tile<16, 16, half2, DATA_LAYOUT_I_MAJOR> & D, const tile<32, 8, half2, DATA_LAYOUT_I_MAJOR_MIRRORED> & A,
|
| 1408 |
+
const tile<16, 8, half2, DATA_LAYOUT_I_MAJOR_MIRRORED> & B) {
|
| 1409 |
+
#if defined(AMD_WMMA_AVAILABLE) && defined(RDNA3)
|
| 1410 |
+
using halfx16_t = __attribute__((ext_vector_type(16))) _Float16;
|
| 1411 |
+
halfx16_t * xD = (halfx16_t *) D.x;
|
| 1412 |
+
const halfx16_t * xA = (const halfx16_t *) A.x;
|
| 1413 |
+
const halfx16_t * xB = (const halfx16_t *) B.x;
|
| 1414 |
+
xD[0] = __builtin_amdgcn_wmma_f16_16x16x16_f16_w32(xA[0], xB[0], xD[0], /*opsel =*/ 0);
|
| 1415 |
+
xD[0] = __builtin_amdgcn_wmma_f16_16x16x16_f16_w32(xA[1], xB[0], xD[0], /*opsel =*/ 1);
|
| 1416 |
+
#else
|
| 1417 |
+
GGML_UNUSED_VARS(D, A, B);
|
| 1418 |
+
NO_DEVICE_CODE;
|
| 1419 |
+
#endif // TURING_MMA_AVAILABLE
|
| 1420 |
+
}
|
| 1421 |
+
|
| 1422 |
+
template <data_layout dl_d, data_layout dl_ab>
|
| 1423 |
+
static __device__ __forceinline__ void mma(
|
| 1424 |
+
tile<16, 16, int, dl_d> & D, const tile<16, 4, int, dl_ab> & A, const tile<16, 4, int, dl_ab> & B) {
|
| 1425 |
+
#if defined(AMD_MFMA_AVAILABLE)
|
| 1426 |
+
using int32x4_t = __attribute__((__vector_size__(4 * sizeof(int)))) int;
|
| 1427 |
+
int32x4_t * acc = (int32x4_t *) D.x;
|
| 1428 |
+
#if defined(CDNA4) || defined(CDNA3)
|
| 1429 |
+
const int64_t xA = uint32_t(A.x[0]);
|
| 1430 |
+
const int64_t xB = uint32_t(B.x[0]);
|
| 1431 |
+
acc[0] = __builtin_amdgcn_mfma_i32_16x16x32_i8(xA, xB, acc[0], 0, 0, 0);
|
| 1432 |
+
#elif defined(CDNA2) || defined(CDNA1)
|
| 1433 |
+
acc[0] = __builtin_amdgcn_mfma_i32_16x16x16i8(A.x[0], B.x[0], acc[0], 0, 0, 0);
|
| 1434 |
+
#endif // defined(CDNA4) || defined(CDNA3)
|
| 1435 |
+
#elif defined(AMD_WMMA_AVAILABLE)
|
| 1436 |
+
using int32x8_t = __attribute__((__vector_size__(8 * sizeof(int)))) int;
|
| 1437 |
+
int32x8_t * acc = (int32x8_t *) D.x;
|
| 1438 |
+
#if defined(RDNA4)
|
| 1439 |
+
using int32x2_t = __attribute__((__vector_size__(2 * sizeof(int)))) int;
|
| 1440 |
+
int32x2_t * a_vec = (int32x2_t *) A.x;
|
| 1441 |
+
int32x2_t * b_vec = (int32x2_t *) B.x;
|
| 1442 |
+
acc[0] = __builtin_amdgcn_wmma_i32_16x16x16_iu8_w32_gfx12(true, a_vec[0], true, b_vec[0], acc[0], false);
|
| 1443 |
+
#elif defined(RDNA3)
|
| 1444 |
+
using int32x4_t = __attribute__((__vector_size__(4 * sizeof(int)))) int;
|
| 1445 |
+
int32x4_t * a_vec = (int32x4_t *) A.x;
|
| 1446 |
+
int32x4_t * b_vec = (int32x4_t *) B.x;
|
| 1447 |
+
acc[0] = __builtin_amdgcn_wmma_i32_16x16x16_iu8_w32(true, a_vec[0], true, b_vec[0], acc[0], false);
|
| 1448 |
+
#endif // RDNA4
|
| 1449 |
+
#else
|
| 1450 |
+
GGML_UNUSED(D);
|
| 1451 |
+
GGML_UNUSED(A);
|
| 1452 |
+
GGML_UNUSED(B);
|
| 1453 |
+
NO_DEVICE_CODE;
|
| 1454 |
+
#endif // AMD_WMMA_AVAILABLE
|
| 1455 |
+
}
|
| 1456 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/mmf.cu
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "ggml.h"
|
| 2 |
+
#include "mmf.cuh"
|
| 3 |
+
#include "mmid.cuh"
|
| 4 |
+
|
| 5 |
+
static __forceinline__ int mmf_get_rows_per_block(const int cc) {
|
| 6 |
+
if (GGML_CUDA_CC_IS_CDNA(cc)) {
|
| 7 |
+
return MMF_ROWS_PER_BLOCK_CDNA;
|
| 8 |
+
} else {
|
| 9 |
+
return MMF_ROWS_PER_BLOCK;
|
| 10 |
+
}
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
void ggml_cuda_mul_mat_f(ggml_backend_cuda_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * ids, ggml_tensor * dst) {
|
| 14 |
+
GGML_ASSERT( src1->type == GGML_TYPE_F32);
|
| 15 |
+
GGML_ASSERT(!ids || ids->type == GGML_TYPE_I32);
|
| 16 |
+
GGML_ASSERT( dst->type == GGML_TYPE_F32);
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
GGML_TENSOR_BINARY_OP_LOCALS;
|
| 20 |
+
|
| 21 |
+
const size_t ts_src0 = ggml_type_size(src0->type);
|
| 22 |
+
const size_t ts_src1 = ggml_type_size(src1->type);
|
| 23 |
+
const size_t ts_dst = ggml_type_size(dst->type);
|
| 24 |
+
|
| 25 |
+
GGML_ASSERT(ne13 == ne3);
|
| 26 |
+
|
| 27 |
+
GGML_ASSERT( nb00 == ts_src0);
|
| 28 |
+
GGML_ASSERT( nb10 == ts_src1);
|
| 29 |
+
GGML_ASSERT(!ids || ids->nb[0] == ggml_type_size(ids->type));
|
| 30 |
+
GGML_ASSERT( nb0 == ts_dst);
|
| 31 |
+
|
| 32 |
+
const float * src1_d = (const float *) src1->data;
|
| 33 |
+
const int32_t * ids_d = ids ? (const int32_t *) ids->data : nullptr;
|
| 34 |
+
float * dst_d = (float *) dst->data;
|
| 35 |
+
|
| 36 |
+
const int64_t s01 = src0->nb[1] / ts_src0;
|
| 37 |
+
const int64_t s11 = src1->nb[1] / ts_src1;
|
| 38 |
+
const int64_t s1 = dst->nb[1] / ts_dst;
|
| 39 |
+
const int64_t s02 = src0->nb[2] / ts_src0;
|
| 40 |
+
const int64_t s12 = src1->nb[2] / ts_src1;
|
| 41 |
+
const int64_t s2 = dst->nb[2] / ts_dst;
|
| 42 |
+
const int64_t s03 = src0->nb[3] / ts_src0;
|
| 43 |
+
const int64_t s13 = src1->nb[3] / ts_src1;
|
| 44 |
+
const int64_t s3 = dst->nb[3] / ts_dst;
|
| 45 |
+
|
| 46 |
+
const int64_t ids_s0 = ids ? ids->nb[0] / ggml_type_size(ids->type) : 0;
|
| 47 |
+
const int64_t ids_s1 = ids ? ids->nb[1] / ggml_type_size(ids->type) : 0;
|
| 48 |
+
|
| 49 |
+
mmf_ids_data ids_info{};
|
| 50 |
+
mmf_ids_data * ids_info_ptr = nullptr;
|
| 51 |
+
ggml_cuda_pool_alloc<int32_t> ids_src_compact_dev;
|
| 52 |
+
ggml_cuda_pool_alloc<int32_t> ids_dst_compact_dev;
|
| 53 |
+
ggml_cuda_pool_alloc<int32_t> expert_bounds_dev;
|
| 54 |
+
|
| 55 |
+
// For MUL_MAT_ID the memory layout is different than for MUL_MAT:
|
| 56 |
+
const int64_t ncols_dst = ids ? ne2 : ne1;
|
| 57 |
+
const int64_t nchannels_dst = ids ? ne1 : ne2;
|
| 58 |
+
|
| 59 |
+
const int64_t stride_col_dst = ids ? s2 : s1;
|
| 60 |
+
const int64_t stride_col_y = ids ? s12 : s11;
|
| 61 |
+
const int64_t stride_channel_dst = ids ? s1 : s2;
|
| 62 |
+
|
| 63 |
+
int64_t stride_channel_y = ids ? s11 : s12;
|
| 64 |
+
int64_t nchannels_y = ids ? ne11 : ne12;
|
| 65 |
+
|
| 66 |
+
//mul_mat_id: handle broadcast
|
| 67 |
+
if (ids && nchannels_y == 1) {
|
| 68 |
+
stride_channel_y = 0;
|
| 69 |
+
nchannels_y = ids->ne[0];
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
if (ids && ncols_dst > 16) {
|
| 73 |
+
const int64_t n_expert_used = ids->ne[0];
|
| 74 |
+
const int64_t n_experts = ne02;
|
| 75 |
+
const int64_t n_tokens = ne12;
|
| 76 |
+
const int64_t ne_get_rows = n_tokens * n_expert_used;
|
| 77 |
+
|
| 78 |
+
ids_src_compact_dev.alloc(ctx.pool(), ne_get_rows);
|
| 79 |
+
ids_dst_compact_dev.alloc(ctx.pool(), ne_get_rows);
|
| 80 |
+
expert_bounds_dev.alloc(ctx.pool(), n_experts + 1);
|
| 81 |
+
|
| 82 |
+
const int si1 = static_cast<int>(ids_s1);
|
| 83 |
+
const int sis1 = static_cast<int>(src1->nb[2] / src1->nb[1]);
|
| 84 |
+
|
| 85 |
+
GGML_ASSERT(sis1 > 0);
|
| 86 |
+
|
| 87 |
+
ggml_cuda_launch_mm_ids_helper(ids_d, ids_src_compact_dev.get(), ids_dst_compact_dev.get(), expert_bounds_dev.get(),
|
| 88 |
+
static_cast<int>(n_experts), static_cast<int>(n_tokens), static_cast<int>(n_expert_used), static_cast<int>(ne11), si1, sis1, ctx.stream());
|
| 89 |
+
CUDA_CHECK(cudaGetLastError());
|
| 90 |
+
|
| 91 |
+
ids_info.ids_src_compact = ids_src_compact_dev.get();
|
| 92 |
+
ids_info.ids_dst_compact = ids_dst_compact_dev.get();
|
| 93 |
+
ids_info.expert_bounds_dev = expert_bounds_dev.get();
|
| 94 |
+
ids_info.n_experts = static_cast<int>(n_experts);
|
| 95 |
+
ids_info.sis1 = sis1;
|
| 96 |
+
ids_info_ptr = &ids_info;
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
const int device = ggml_cuda_get_device();
|
| 100 |
+
const int cc = ggml_cuda_info().devices[device].cc;
|
| 101 |
+
const int rows_per_block = mmf_get_rows_per_block(cc);
|
| 102 |
+
|
| 103 |
+
switch (src0->type) {
|
| 104 |
+
case GGML_TYPE_F32: {
|
| 105 |
+
const float * src0_d = (const float *) src0->data;
|
| 106 |
+
constexpr int vals_per_T = 1;
|
| 107 |
+
mul_mat_f_switch_rows_per_block<float>(
|
| 108 |
+
rows_per_block, src0_d, src1_d, ids_d, dst_d, ne00/vals_per_T, ne01, ncols_dst, s01/vals_per_T, stride_col_y/vals_per_T, stride_col_dst,
|
| 109 |
+
ids_s0, ids_s1, ne02, nchannels_y, nchannels_dst, s02/vals_per_T, stride_channel_y, stride_channel_dst,
|
| 110 |
+
ne03, ne3, s03/vals_per_T, s13, s3, ctx.stream(), ids_info_ptr);
|
| 111 |
+
} break;
|
| 112 |
+
case GGML_TYPE_F16: {
|
| 113 |
+
const half2 * src0_d = (const half2 *) src0->data;
|
| 114 |
+
constexpr int vals_per_T = 2;
|
| 115 |
+
mul_mat_f_switch_rows_per_block<half2>(
|
| 116 |
+
rows_per_block, src0_d, src1_d, ids_d, dst_d, ne00/vals_per_T, ne01, ncols_dst, s01/vals_per_T, stride_col_y/vals_per_T, stride_col_dst,
|
| 117 |
+
ids_s0, ids_s1, ne02, nchannels_y, nchannels_dst, s02/vals_per_T, stride_channel_y, stride_channel_dst,
|
| 118 |
+
ne03, ne3, s03/vals_per_T, s13, s3, ctx.stream(), ids_info_ptr);
|
| 119 |
+
} break;
|
| 120 |
+
case GGML_TYPE_BF16: {
|
| 121 |
+
const nv_bfloat162 * src0_d = (const nv_bfloat162 *) src0->data;
|
| 122 |
+
constexpr int vals_per_T = 2;
|
| 123 |
+
mul_mat_f_switch_rows_per_block<nv_bfloat162>(
|
| 124 |
+
rows_per_block, src0_d, src1_d, ids_d, dst_d, ne00/vals_per_T, ne01, ncols_dst, s01/vals_per_T, stride_col_y/vals_per_T, stride_col_dst,
|
| 125 |
+
ids_s0, ids_s1, ne02, nchannels_y, nchannels_dst, s02/vals_per_T, stride_channel_y, stride_channel_dst,
|
| 126 |
+
ne03, ne3, s03/vals_per_T, s13, s3, ctx.stream(), ids_info_ptr);
|
| 127 |
+
} break;
|
| 128 |
+
default:
|
| 129 |
+
GGML_ABORT("unsupported type: %s", ggml_type_name(src0->type));
|
| 130 |
+
}
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
bool ggml_cuda_should_use_mmf(enum ggml_type type, int cc, int warp_size, const int64_t * src0_ne,
|
| 134 |
+
const size_t * src0_nb, const int src1_ncols, bool mul_mat_id) {
|
| 135 |
+
if (ggml_is_quantized(type)) {
|
| 136 |
+
return false;
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
const size_t ts = ggml_type_size(type);
|
| 140 |
+
if (src0_ne[0] % (warp_size * (4/ts)) != 0) {
|
| 141 |
+
return false;
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
if (src0_nb[0] != ts) {
|
| 145 |
+
return false;
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
// Pointers not aligned to the size of half2/nv_bfloat162/float2 would result in a crash:
|
| 149 |
+
for (size_t i = 1; i < GGML_MAX_DIMS; ++i) {
|
| 150 |
+
if (src0_nb[i] % (2*ts) != 0) {
|
| 151 |
+
return false;
|
| 152 |
+
}
|
| 153 |
+
}
|
| 154 |
+
if (src0_ne[1] % mmf_get_rows_per_block(cc) != 0) {
|
| 155 |
+
return false;
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
if (GGML_CUDA_CC_IS_CDNA3(cc) && type == GGML_TYPE_BF16) {
|
| 159 |
+
return false;
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
if (mul_mat_id) {
|
| 163 |
+
if (src0_ne[1] <= 1024 && src1_ncols > 512) {
|
| 164 |
+
return false;
|
| 165 |
+
} else if(src0_ne[1] > 1024 && src1_ncols > 128) {
|
| 166 |
+
return false;
|
| 167 |
+
}
|
| 168 |
+
} else {
|
| 169 |
+
if (GGML_CUDA_CC_IS_RDNA3_0(cc) && src1_ncols > 8) {
|
| 170 |
+
return false;
|
| 171 |
+
} else if (GGML_CUDA_CC_IS_CDNA2(cc) && (type == GGML_TYPE_F16 || type == GGML_TYPE_BF16)) {
|
| 172 |
+
//TODO: truse CDNA2 as CDNA1, tune the perf when CDNA2 is available.
|
| 173 |
+
return false;
|
| 174 |
+
} else if (GGML_CUDA_CC_IS_CDNA1(cc) && (type == GGML_TYPE_F16 || type == GGML_TYPE_BF16)) {
|
| 175 |
+
return false;
|
| 176 |
+
} else if (src1_ncols > 16) {
|
| 177 |
+
return false;
|
| 178 |
+
}
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
switch (type) {
|
| 182 |
+
case GGML_TYPE_F32:
|
| 183 |
+
return ampere_mma_available(cc) || amd_mfma_available(cc);
|
| 184 |
+
case GGML_TYPE_F16:
|
| 185 |
+
return volta_mma_available(cc) || turing_mma_available(cc) || amd_wmma_available(cc) || amd_mfma_available(cc);
|
| 186 |
+
case GGML_TYPE_BF16:
|
| 187 |
+
return ampere_mma_available(cc) || amd_wmma_available(cc) || amd_mfma_available(cc);
|
| 188 |
+
default:
|
| 189 |
+
return false;
|
| 190 |
+
}
|
| 191 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/mmf.cuh
ADDED
|
@@ -0,0 +1,908 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include "mma.cuh"
|
| 4 |
+
#include "common.cuh"
|
| 5 |
+
#include "convert.cuh"
|
| 6 |
+
|
| 7 |
+
using namespace ggml_cuda_mma;
|
| 8 |
+
|
| 9 |
+
#define MMF_ROWS_PER_BLOCK 32
|
| 10 |
+
#define MMF_ROWS_PER_BLOCK_CDNA 64
|
| 11 |
+
|
| 12 |
+
static __forceinline__ int64_t mmf_get_max_block_size(int cc) {
|
| 13 |
+
if (GGML_CUDA_CC_IS_CDNA(cc)) {
|
| 14 |
+
return 512;
|
| 15 |
+
} else {
|
| 16 |
+
return 256;
|
| 17 |
+
}
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
static __forceinline__ int mmf_get_padding(int cc) {
|
| 21 |
+
if (GGML_CUDA_CC_IS_CDNA(cc)) {
|
| 22 |
+
return 2;
|
| 23 |
+
} else {
|
| 24 |
+
return 4;
|
| 25 |
+
}
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
static constexpr __device__ int mmf_get_padding() {
|
| 29 |
+
#if defined(AMD_MFMA_AVAILABLE)
|
| 30 |
+
return 2;
|
| 31 |
+
#else
|
| 32 |
+
return 4;
|
| 33 |
+
#endif // defined(AMD_MFMA_AVAILABLE)
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
struct mmf_ids_data {
|
| 37 |
+
const int32_t * ids_src_compact = nullptr;
|
| 38 |
+
const int32_t * ids_dst_compact = nullptr;
|
| 39 |
+
const int32_t * expert_bounds_dev = nullptr;
|
| 40 |
+
int n_experts = 0;
|
| 41 |
+
int sis1 = 0;
|
| 42 |
+
};
|
| 43 |
+
|
| 44 |
+
void ggml_cuda_mul_mat_f(ggml_backend_cuda_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * ids, ggml_tensor * dst);
|
| 45 |
+
|
| 46 |
+
bool ggml_cuda_should_use_mmf(enum ggml_type type, int cc, int warp_size, const int64_t * scr0_ne, const size_t * src0_nb, const int src1_ncols, bool mul_mat_id);
|
| 47 |
+
|
| 48 |
+
template <typename T, int rows_per_block, int cols_per_block, int nwarps, bool has_ids>
|
| 49 |
+
__launch_bounds__(ggml_cuda_get_physical_warp_size()*nwarps, 1)
|
| 50 |
+
static __global__ void mul_mat_f(
|
| 51 |
+
const T * __restrict__ x, const float * __restrict__ y, const int32_t * __restrict__ ids, float * __restrict__ dst,
|
| 52 |
+
const int ncols, const int ncols_dst_total, const int nchannels_dst, const int stride_row, const int stride_col_y, const int stride_col_dst,
|
| 53 |
+
const int stride_col_id, const int stride_row_id,
|
| 54 |
+
const int channel_ratio, const int stride_channel_x, const int stride_channel_y, const int stride_channel_dst,
|
| 55 |
+
const int sample_ratio, const int stride_sample_x, const int stride_sample_y, const int stride_sample_dst) {
|
| 56 |
+
// TODO: handle this in a consistent and simpler way after AMD MFMA support has been added
|
| 57 |
+
#if defined(VOLTA_MMA_AVAILABLE) || defined(TURING_MMA_AVAILABLE) || defined(AMD_WMMA_AVAILABLE) || defined(AMD_MFMA_AVAILABLE)
|
| 58 |
+
#if defined(AMD_WMMA_AVAILABLE)
|
| 59 |
+
if constexpr (!(std::is_same_v<T, half2> || std::is_same_v<T, nv_bfloat162>) || rows_per_block != MMF_ROWS_PER_BLOCK) {NO_DEVICE_CODE;} else {
|
| 60 |
+
typedef tile<16, 8, T, get_input_data_layout()> tile_A;
|
| 61 |
+
typedef tile<16, 8, T, get_input_data_layout()> tile_B;
|
| 62 |
+
typedef tile<16, 16, float, DATA_LAYOUT_J_MAJOR> tile_C;
|
| 63 |
+
#elif defined(AMD_MFMA_AVAILABLE)
|
| 64 |
+
if constexpr (rows_per_block != MMF_ROWS_PER_BLOCK_CDNA) {NO_DEVICE_CODE;} else {
|
| 65 |
+
typedef tile<16, 8, T, DATA_LAYOUT_I_MAJOR> tile_A;
|
| 66 |
+
typedef tile<16, 8, T, DATA_LAYOUT_I_MAJOR> tile_B;
|
| 67 |
+
typedef tile<16, 16, float, DATA_LAYOUT_J_MAJOR> tile_C;
|
| 68 |
+
#else
|
| 69 |
+
#ifdef VOLTA_MMA_AVAILABLE
|
| 70 |
+
if constexpr (!std::is_same_v<T, half2> || rows_per_block != MMF_ROWS_PER_BLOCK) {NO_DEVICE_CODE;} else {
|
| 71 |
+
typedef tile<32, 4, T, DATA_LAYOUT_I_MAJOR> tile_A;
|
| 72 |
+
typedef tile< 8, 4, T, DATA_LAYOUT_I_MAJOR_MIRRORED> tile_B;
|
| 73 |
+
typedef tile<32, 8, float, DATA_LAYOUT_I_MAJOR> tile_C;
|
| 74 |
+
#else
|
| 75 |
+
if constexpr (rows_per_block != MMF_ROWS_PER_BLOCK) {NO_DEVICE_CODE;} else {
|
| 76 |
+
typedef tile<16, 8, T> tile_A;
|
| 77 |
+
typedef tile<8, 8, T> tile_B;
|
| 78 |
+
typedef tile<16, 8, float> tile_C;
|
| 79 |
+
#endif // VOLTA_MMA_AVAILABLE
|
| 80 |
+
#endif // defined(AMD_WMMA_AVAILABLE)
|
| 81 |
+
if constexpr (!tile_A::supported() || !tile_B::supported() || !tile_C::supported()) {
|
| 82 |
+
NO_DEVICE_CODE;
|
| 83 |
+
return;
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
constexpr int warp_size = ggml_cuda_get_physical_warp_size();
|
| 87 |
+
constexpr int tile_k_padded = warp_size + mmf_get_padding();
|
| 88 |
+
constexpr int ntA = rows_per_block / tile_A::I;
|
| 89 |
+
constexpr int ntB = (cols_per_block + tile_B::I - 1) / tile_B::I;
|
| 90 |
+
|
| 91 |
+
const int row0 = blockIdx.x * rows_per_block;
|
| 92 |
+
|
| 93 |
+
int expert_idx = 0;
|
| 94 |
+
[[maybe_unused]] int col_base = 0;
|
| 95 |
+
|
| 96 |
+
const int channel_dst = has_ids ? 0 : blockIdx.y;
|
| 97 |
+
|
| 98 |
+
if constexpr (has_ids) {
|
| 99 |
+
// experts + tiles of ncols_dst are packed in the y dimension
|
| 100 |
+
int col_tiles = (ncols_dst_total + cols_per_block - 1) / cols_per_block;
|
| 101 |
+
const int nchannels_x = gridDim.y / col_tiles;
|
| 102 |
+
const int tile_idx = blockIdx.y / nchannels_x;
|
| 103 |
+
expert_idx = blockIdx.y - tile_idx * nchannels_x;
|
| 104 |
+
col_base = tile_idx * cols_per_block;
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
const int channel_x = has_ids ? expert_idx : (channel_dst / channel_ratio);
|
| 108 |
+
const int channel_y = channel_dst;
|
| 109 |
+
const int sample_dst = blockIdx.z;
|
| 110 |
+
const int sample_x = sample_dst / sample_ratio;
|
| 111 |
+
const int sample_y = sample_dst;
|
| 112 |
+
|
| 113 |
+
x += int64_t(sample_x) *stride_sample_x + channel_x *stride_channel_x + row0*stride_row ;
|
| 114 |
+
y += int64_t(sample_y) *stride_sample_y + (has_ids ? 0 : channel_y *stride_channel_y);
|
| 115 |
+
dst += int64_t(sample_dst)*stride_sample_dst + (has_ids ? 0 : channel_dst*stride_channel_dst);
|
| 116 |
+
|
| 117 |
+
if constexpr (has_ids) {
|
| 118 |
+
constexpr int y_stride_scale = std::is_same_v<T, float> ? 1 : 2;
|
| 119 |
+
const int64_t col_offset = col_base;
|
| 120 |
+
y += col_offset * stride_col_y * y_stride_scale;
|
| 121 |
+
dst += col_offset * stride_col_dst;
|
| 122 |
+
ids += col_offset * stride_row_id;
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
[[maybe_unused]] const float2 * y2 = (const float2 *) y;
|
| 126 |
+
|
| 127 |
+
extern __shared__ char data_mmv[];
|
| 128 |
+
|
| 129 |
+
char * shmem_base = data_mmv;
|
| 130 |
+
[[maybe_unused]] int * slot_map = (int *) shmem_base;
|
| 131 |
+
char * compute_base = has_ids ? (shmem_base + GGML_PAD(cols_per_block, 16) * sizeof(int)) : shmem_base;
|
| 132 |
+
|
| 133 |
+
tile_C C[ntA][ntB];
|
| 134 |
+
|
| 135 |
+
T * tile_xy = (T *) compute_base + threadIdx.y*(tile_A::I * tile_k_padded);
|
| 136 |
+
|
| 137 |
+
if constexpr (has_ids) {
|
| 138 |
+
int found = 0;
|
| 139 |
+
|
| 140 |
+
for (int j0 = 0; j0 < cols_per_block; j0 += nwarps) {
|
| 141 |
+
const int j = j0 + threadIdx.y;
|
| 142 |
+
|
| 143 |
+
if (threadIdx.x == 0) {
|
| 144 |
+
slot_map[j] = -1;
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
if (col_base + j >= ncols_dst_total) {
|
| 148 |
+
continue;
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
const int32_t * __restrict__ id_row = ids + j*stride_row_id;
|
| 152 |
+
|
| 153 |
+
for (int k = threadIdx.x; k < nchannels_dst; k += warp_size) {
|
| 154 |
+
int match = id_row[k*stride_col_id] == expert_idx;
|
| 155 |
+
|
| 156 |
+
if (match) {
|
| 157 |
+
slot_map[j] = k;
|
| 158 |
+
found = 1;
|
| 159 |
+
break;
|
| 160 |
+
}
|
| 161 |
+
}
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
if (!__syncthreads_or(found)) {
|
| 165 |
+
return;
|
| 166 |
+
}
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
for (int col = threadIdx.y*warp_size + threadIdx.x; col < ncols; col += nwarps*warp_size) {
|
| 171 |
+
tile_A A[ntA][warp_size / tile_A::J];
|
| 172 |
+
#pragma unroll
|
| 173 |
+
for (int itA = 0; itA < ntA; ++itA) {
|
| 174 |
+
#pragma unroll
|
| 175 |
+
for (int i = 0; i < tile_A::I; ++i) {
|
| 176 |
+
tile_xy[i*tile_k_padded + threadIdx.x] = x[(itA*tile_A::I + i)*stride_row + col];
|
| 177 |
+
}
|
| 178 |
+
#pragma unroll
|
| 179 |
+
for (int k0 = 0; k0 < warp_size; k0 += tile_A::J) {
|
| 180 |
+
load_ldmatrix(A[itA][k0/tile_A::J], tile_xy + k0, tile_k_padded);
|
| 181 |
+
}
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
#pragma unroll
|
| 185 |
+
for (int itB = 0; itB < ntB; ++itB) {
|
| 186 |
+
if constexpr (std::is_same_v<T, float>) {
|
| 187 |
+
#pragma unroll
|
| 188 |
+
for (int j0 = 0; j0 < tile_B::I; ++j0) {
|
| 189 |
+
const int j = j0 + itB*tile_B::I;
|
| 190 |
+
|
| 191 |
+
if constexpr (!has_ids) {
|
| 192 |
+
tile_xy[j0*tile_k_padded + threadIdx.x] = j < cols_per_block ? y[j*stride_col_y + col] : 0.0f;
|
| 193 |
+
} else {
|
| 194 |
+
const bool valid = j < cols_per_block && (col_base + j) < ncols_dst_total && slot_map[j] >= 0;
|
| 195 |
+
tile_xy[j0*tile_k_padded + threadIdx.x] = valid ? y[slot_map[j]*stride_channel_y + j*stride_col_y + col] : 0.0f;
|
| 196 |
+
}
|
| 197 |
+
}
|
| 198 |
+
} else if constexpr (std::is_same_v<T, half2> || std::is_same_v<T, nv_bfloat162>) {
|
| 199 |
+
#pragma unroll
|
| 200 |
+
for (int j0 = 0; j0 < tile_B::I; ++j0) {
|
| 201 |
+
const int j = j0 + itB*tile_B::I;
|
| 202 |
+
|
| 203 |
+
if constexpr (!has_ids) {
|
| 204 |
+
const float2 tmp = j < cols_per_block ? y2[j*stride_col_y + col] : make_float2(0.0f, 0.0f);
|
| 205 |
+
tile_xy[j0*tile_k_padded + threadIdx.x] = ggml_cuda_cast<T>(tmp);
|
| 206 |
+
} else {
|
| 207 |
+
const bool valid = j < cols_per_block && (col_base + j) < ncols_dst_total && slot_map[j] >= 0;
|
| 208 |
+
float2 tmp = valid ? *(const float2*) &y[slot_map[j]*stride_channel_y + 2*(j*stride_col_y + col)] : make_float2(0.0f, 0.0f);
|
| 209 |
+
tile_xy[j0*tile_k_padded + threadIdx.x] = ggml_cuda_cast<T>(tmp);
|
| 210 |
+
}
|
| 211 |
+
}
|
| 212 |
+
} else {
|
| 213 |
+
static_assert(std::is_same_v<T, void>, "unsupported type");
|
| 214 |
+
}
|
| 215 |
+
#pragma unroll
|
| 216 |
+
for (int k0 = 0; k0 < warp_size; k0 += tile_B::J) {
|
| 217 |
+
tile_B B;
|
| 218 |
+
load_ldmatrix(B, tile_xy + k0, tile_k_padded);
|
| 219 |
+
#pragma unroll
|
| 220 |
+
for (int itA = 0; itA < ntA; ++itA) {
|
| 221 |
+
mma(C[itA][itB], A[itA][k0/tile_B::J], B);
|
| 222 |
+
}
|
| 223 |
+
}
|
| 224 |
+
}
|
| 225 |
+
}
|
| 226 |
+
|
| 227 |
+
float * buf_iw = (float *) compute_base;
|
| 228 |
+
constexpr int kiw = nwarps*rows_per_block + mmf_get_padding();
|
| 229 |
+
|
| 230 |
+
if (nwarps > 1) {
|
| 231 |
+
__syncthreads();
|
| 232 |
+
}
|
| 233 |
+
#pragma unroll
|
| 234 |
+
for (int itB = 0; itB < ntB; ++itB) {
|
| 235 |
+
#pragma unroll
|
| 236 |
+
for (int itA = 0; itA < ntA; ++itA) {
|
| 237 |
+
#pragma unroll
|
| 238 |
+
for (int l = 0; l < tile_C::ne; ++l) {
|
| 239 |
+
const int i = threadIdx.y*rows_per_block + itA*tile_C::I + tile_C::get_i(l);
|
| 240 |
+
const int j = itB*tile_C::J + tile_C::get_j(l);
|
| 241 |
+
buf_iw[j*kiw + i] = C[itA][itB].x[l];
|
| 242 |
+
}
|
| 243 |
+
}
|
| 244 |
+
}
|
| 245 |
+
|
| 246 |
+
if (nwarps > 1) {
|
| 247 |
+
__syncthreads();
|
| 248 |
+
}
|
| 249 |
+
|
| 250 |
+
#pragma unroll
|
| 251 |
+
for (int j0 = 0; j0 < cols_per_block; j0 += nwarps) {
|
| 252 |
+
const int j = j0 + threadIdx.y;
|
| 253 |
+
|
| 254 |
+
if (j0 + nwarps > cols_per_block && j >= cols_per_block) {
|
| 255 |
+
return;
|
| 256 |
+
}
|
| 257 |
+
|
| 258 |
+
float sum[rows_per_block/warp_size] = {0.0f};
|
| 259 |
+
static_assert((rows_per_block % warp_size) == 0, "rows_per_block must be a multiple of warp_size.");
|
| 260 |
+
#pragma unroll
|
| 261 |
+
for (int i0 = 0; i0 < nwarps*rows_per_block; i0 += rows_per_block) {
|
| 262 |
+
#pragma unroll
|
| 263 |
+
for (int i1 = 0; i1 < sizeof(sum)/sizeof(sum[0]); ++i1) {
|
| 264 |
+
const int i = i0 + i1*warp_size + threadIdx.x;
|
| 265 |
+
|
| 266 |
+
sum[i1] += buf_iw[j*kiw + i];
|
| 267 |
+
}
|
| 268 |
+
}
|
| 269 |
+
|
| 270 |
+
if constexpr (!has_ids) {
|
| 271 |
+
#pragma unroll
|
| 272 |
+
for (int i0 = 0; i0 < sizeof(sum)/sizeof(sum[0]); ++i0) {
|
| 273 |
+
dst[j*stride_col_dst + row0 + i0*warp_size + threadIdx.x] = sum[i0];
|
| 274 |
+
}
|
| 275 |
+
} else {
|
| 276 |
+
const int slot = (j < cols_per_block) ? slot_map[j] : -1;
|
| 277 |
+
if (slot >= 0 && (col_base + j) < ncols_dst_total) {
|
| 278 |
+
#pragma unroll
|
| 279 |
+
for (int i0 = 0; i0 < sizeof(sum)/sizeof(sum[0]); ++i0) {
|
| 280 |
+
dst[slot*stride_channel_dst + j*stride_col_dst + row0 + i0*warp_size + threadIdx.x] = sum[i0];
|
| 281 |
+
}
|
| 282 |
+
}
|
| 283 |
+
}
|
| 284 |
+
}
|
| 285 |
+
}
|
| 286 |
+
#else
|
| 287 |
+
GGML_UNUSED_VARS(x, y, ids, dst,
|
| 288 |
+
ncols, ncols_dst_total, nchannels_dst, stride_row, stride_col_y, stride_col_dst,
|
| 289 |
+
stride_col_id, stride_row_id,
|
| 290 |
+
channel_ratio, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 291 |
+
sample_ratio, stride_sample_x, stride_sample_y, stride_sample_dst);
|
| 292 |
+
NO_DEVICE_CODE;
|
| 293 |
+
#endif // defined(VOLTA_MMA_AVAILABLE) || defined(TURING_MMA_AVAILABLE) || defined(AMD_WMMA_AVAILABLE) || defined(AMD_MFMA_AVAILABLE)
|
| 294 |
+
}
|
| 295 |
+
|
| 296 |
+
//This kernel is for larger batch sizes of mul_mat_id
|
| 297 |
+
template <typename T, int rows_per_block, int cols_per_block, int nwarps>
|
| 298 |
+
__launch_bounds__(ggml_cuda_get_physical_warp_size()*nwarps, 1)
|
| 299 |
+
static __global__ void mul_mat_f_ids(
|
| 300 |
+
const T * __restrict__ x, const float * __restrict__ y,
|
| 301 |
+
const int32_t * __restrict__ ids_src_compact, const int32_t * __restrict__ ids_dst_compact,
|
| 302 |
+
const int32_t * __restrict__ expert_bounds, float * __restrict__ dst,
|
| 303 |
+
const int ncols, const int ncols_dst_total, const int nchannels_dst, const int stride_row, const int stride_col_y, const int stride_col_dst,
|
| 304 |
+
const int channel_ratio, const int stride_channel_x, const int stride_channel_y, const int stride_channel_dst,
|
| 305 |
+
const int sample_ratio, const int stride_sample_x, const int stride_sample_y, const int stride_sample_dst,
|
| 306 |
+
const uint3 sis1_fd, const uint3 nch_fd) {
|
| 307 |
+
// TODO: handle this in a consistent and simpler way after AMD MFMA support has been added
|
| 308 |
+
#if defined(VOLTA_MMA_AVAILABLE) || defined(TURING_MMA_AVAILABLE) || defined(AMD_WMMA_AVAILABLE) || defined(AMD_MFMA_AVAILABLE)
|
| 309 |
+
#if defined(AMD_WMMA_AVAILABLE)
|
| 310 |
+
if constexpr (!(std::is_same_v<T, half2> || std::is_same_v<T, nv_bfloat162>) || rows_per_block != MMF_ROWS_PER_BLOCK) {NO_DEVICE_CODE;} else {
|
| 311 |
+
typedef tile<16, 8, T, get_input_data_layout()> tile_A;
|
| 312 |
+
typedef tile<16, 8, T, get_input_data_layout()> tile_B;
|
| 313 |
+
typedef tile<16, 16, float, DATA_LAYOUT_J_MAJOR> tile_C;
|
| 314 |
+
#elif defined(AMD_MFMA_AVAILABLE)
|
| 315 |
+
if constexpr (rows_per_block != MMF_ROWS_PER_BLOCK_CDNA) {NO_DEVICE_CODE;} else {
|
| 316 |
+
typedef tile<16, 8, T, DATA_LAYOUT_I_MAJOR> tile_A;
|
| 317 |
+
typedef tile<16, 8, T, DATA_LAYOUT_I_MAJOR> tile_B;
|
| 318 |
+
typedef tile<16, 16, float, DATA_LAYOUT_J_MAJOR> tile_C;
|
| 319 |
+
#else
|
| 320 |
+
#ifdef VOLTA_MMA_AVAILABLE
|
| 321 |
+
if constexpr (!std::is_same_v<T, half2> || rows_per_block != MMF_ROWS_PER_BLOCK) {NO_DEVICE_CODE;} else {
|
| 322 |
+
typedef tile<32, 4, T, DATA_LAYOUT_I_MAJOR> tile_A;
|
| 323 |
+
typedef tile< 8, 4, T, DATA_LAYOUT_I_MAJOR_MIRRORED> tile_B;
|
| 324 |
+
typedef tile<32, 8, float, DATA_LAYOUT_I_MAJOR> tile_C;
|
| 325 |
+
#else
|
| 326 |
+
if constexpr (rows_per_block != MMF_ROWS_PER_BLOCK) {NO_DEVICE_CODE;} else {
|
| 327 |
+
typedef tile<16, 8, T> tile_A;
|
| 328 |
+
typedef tile<8, 8, T> tile_B;
|
| 329 |
+
typedef tile<16, 8, float> tile_C;
|
| 330 |
+
#endif // VOLTA_MMA_AVAILABLE
|
| 331 |
+
#endif // defined(AMD_WMMA_AVAILABLE)
|
| 332 |
+
if constexpr (!tile_A::supported() || !tile_B::supported() || !tile_C::supported()) {
|
| 333 |
+
NO_DEVICE_CODE;
|
| 334 |
+
return;
|
| 335 |
+
}
|
| 336 |
+
|
| 337 |
+
|
| 338 |
+
constexpr int warp_size = ggml_cuda_get_physical_warp_size();
|
| 339 |
+
constexpr int tile_k_padded = warp_size + mmf_get_padding();
|
| 340 |
+
constexpr int ntA = rows_per_block / tile_A::I;
|
| 341 |
+
constexpr int ntB = (cols_per_block + tile_B::I - 1) / tile_B::I;
|
| 342 |
+
|
| 343 |
+
const int row0 = blockIdx.x * rows_per_block;
|
| 344 |
+
|
| 345 |
+
const int expert_idx = blockIdx.y;
|
| 346 |
+
const int expert_start = expert_bounds[expert_idx];
|
| 347 |
+
const int expert_end = expert_bounds[expert_idx + 1];
|
| 348 |
+
const int ncols_expert = expert_end - expert_start;
|
| 349 |
+
|
| 350 |
+
const int tiles_for_expert = (ncols_expert + cols_per_block - 1) / cols_per_block;
|
| 351 |
+
const int tile_idx = blockIdx.z;
|
| 352 |
+
if (tile_idx >= tiles_for_expert) {
|
| 353 |
+
return;
|
| 354 |
+
}
|
| 355 |
+
|
| 356 |
+
const int col_base = tile_idx * cols_per_block;
|
| 357 |
+
|
| 358 |
+
GGML_UNUSED(channel_ratio);
|
| 359 |
+
|
| 360 |
+
const int channel_x = expert_idx;
|
| 361 |
+
const int sample_dst = 0;
|
| 362 |
+
const int sample_x = sample_dst / sample_ratio;
|
| 363 |
+
const int sample_y = sample_dst;
|
| 364 |
+
|
| 365 |
+
x += int64_t(sample_x) *stride_sample_x + channel_x *stride_channel_x + row0*stride_row;
|
| 366 |
+
y += int64_t(sample_y) *stride_sample_y;
|
| 367 |
+
dst += int64_t(sample_dst)*stride_sample_dst;
|
| 368 |
+
|
| 369 |
+
const int32_t * ids_src_expert = ids_src_compact + expert_start;
|
| 370 |
+
const int32_t * ids_dst_expert = ids_dst_compact + expert_start;
|
| 371 |
+
|
| 372 |
+
extern __shared__ char data_mmv[];
|
| 373 |
+
char * compute_base = data_mmv;
|
| 374 |
+
|
| 375 |
+
//const float2 * y2 = (const float2 *) y;
|
| 376 |
+
|
| 377 |
+
tile_C C[ntA][ntB];
|
| 378 |
+
|
| 379 |
+
T * tile_xy = (T *) compute_base + threadIdx.y*(tile_A::I * tile_k_padded);
|
| 380 |
+
|
| 381 |
+
for (int col = threadIdx.y*warp_size + threadIdx.x; col < ncols; col += nwarps*warp_size) {
|
| 382 |
+
tile_A A[ntA][warp_size / tile_A::J];
|
| 383 |
+
#pragma unroll
|
| 384 |
+
for (int itA = 0; itA < ntA; ++itA) {
|
| 385 |
+
#pragma unroll
|
| 386 |
+
for (int i = 0; i < tile_A::I; ++i) {
|
| 387 |
+
tile_xy[i*tile_k_padded + threadIdx.x] = x[(itA*tile_A::I + i)*stride_row + col];
|
| 388 |
+
}
|
| 389 |
+
#pragma unroll
|
| 390 |
+
for (int k0 = 0; k0 < warp_size; k0 += tile_A::J) {
|
| 391 |
+
load_ldmatrix(A[itA][k0/tile_A::J], tile_xy + k0, tile_k_padded);
|
| 392 |
+
}
|
| 393 |
+
}
|
| 394 |
+
|
| 395 |
+
if constexpr (std::is_same_v<T, float>) {
|
| 396 |
+
float vals_buf[2][tile_B::I];
|
| 397 |
+
auto gather_tile = [&](int tile_idx_local, float *vals) {
|
| 398 |
+
#pragma unroll
|
| 399 |
+
for (int j0 = 0; j0 < tile_B::I; ++j0) {
|
| 400 |
+
const int j = j0 + tile_idx_local*tile_B::I;
|
| 401 |
+
const int global_j = col_base + j;
|
| 402 |
+
float val = 0.0f;
|
| 403 |
+
if (j < cols_per_block && global_j < ncols_expert) {
|
| 404 |
+
const int src_entry = ids_src_expert[global_j];
|
| 405 |
+
const uint2 qrm = fast_div_modulo((uint32_t) src_entry, sis1_fd);
|
| 406 |
+
const int token = (int) qrm.x;
|
| 407 |
+
const int channel = (int) qrm.y;
|
| 408 |
+
if (token < ncols_dst_total) {
|
| 409 |
+
val = y[channel*stride_channel_y + token*stride_col_y + col];
|
| 410 |
+
}
|
| 411 |
+
}
|
| 412 |
+
vals[j0] = val;
|
| 413 |
+
}
|
| 414 |
+
};
|
| 415 |
+
|
| 416 |
+
gather_tile(0, vals_buf[0]);
|
| 417 |
+
|
| 418 |
+
int curr_buf = 0;
|
| 419 |
+
int next_buf = 1;
|
| 420 |
+
#pragma unroll
|
| 421 |
+
for (int itB = 0; itB < ntB; ++itB) {
|
| 422 |
+
#pragma unroll
|
| 423 |
+
for (int j0 = 0; j0 < tile_B::I; ++j0) {
|
| 424 |
+
tile_xy[j0*tile_k_padded + threadIdx.x] = vals_buf[curr_buf][j0];
|
| 425 |
+
}
|
| 426 |
+
|
| 427 |
+
if (itB + 1 < ntB) {
|
| 428 |
+
gather_tile(itB + 1, vals_buf[next_buf]);
|
| 429 |
+
}
|
| 430 |
+
|
| 431 |
+
#pragma unroll
|
| 432 |
+
for (int k0 = 0; k0 < warp_size; k0 += tile_B::J) {
|
| 433 |
+
tile_B B;
|
| 434 |
+
load_ldmatrix(B, tile_xy + k0, tile_k_padded);
|
| 435 |
+
#pragma unroll
|
| 436 |
+
for (int itA = 0; itA < ntA; ++itA) {
|
| 437 |
+
mma(C[itA][itB], A[itA][k0/tile_B::J], B);
|
| 438 |
+
}
|
| 439 |
+
}
|
| 440 |
+
|
| 441 |
+
if (itB + 1 < ntB) {
|
| 442 |
+
curr_buf ^= 1;
|
| 443 |
+
next_buf ^= 1;
|
| 444 |
+
}
|
| 445 |
+
}
|
| 446 |
+
} else if constexpr (std::is_same_v<T, half2> || std::is_same_v<T, nv_bfloat162>) {
|
| 447 |
+
float2 vals_buf[2][tile_B::I];
|
| 448 |
+
auto gather_tile = [&](int tile_idx_local, float2 *vals) {
|
| 449 |
+
#pragma unroll
|
| 450 |
+
for (int j0 = 0; j0 < tile_B::I; ++j0) {
|
| 451 |
+
const int j = j0 + tile_idx_local*tile_B::I;
|
| 452 |
+
const int global_j = col_base + j;
|
| 453 |
+
float2 tmp = make_float2(0.0f, 0.0f);
|
| 454 |
+
if (j < cols_per_block && global_j < ncols_expert) {
|
| 455 |
+
const int src_entry = ids_src_expert[global_j];
|
| 456 |
+
const uint2 qrm = fast_div_modulo((uint32_t) src_entry, sis1_fd);
|
| 457 |
+
const int token = (int) qrm.x;
|
| 458 |
+
const int channel = (int) qrm.y;
|
| 459 |
+
if (token < ncols_dst_total) {
|
| 460 |
+
tmp = *(const float2*) &y[channel*stride_channel_y + 2*(token*stride_col_y + col)];
|
| 461 |
+
}
|
| 462 |
+
}
|
| 463 |
+
vals[j0] = tmp;
|
| 464 |
+
}
|
| 465 |
+
};
|
| 466 |
+
|
| 467 |
+
if (ntB > 0) {
|
| 468 |
+
gather_tile(0, vals_buf[0]);
|
| 469 |
+
}
|
| 470 |
+
|
| 471 |
+
int curr_buf = 0;
|
| 472 |
+
int next_buf = 1;
|
| 473 |
+
#pragma unroll
|
| 474 |
+
for (int itB = 0; itB < ntB; ++itB) {
|
| 475 |
+
#pragma unroll
|
| 476 |
+
for (int j0 = 0; j0 < tile_B::I; ++j0) {
|
| 477 |
+
const float2 tmp = vals_buf[curr_buf][j0];
|
| 478 |
+
tile_xy[j0*tile_k_padded + threadIdx.x] = ggml_cuda_cast<T>(tmp);
|
| 479 |
+
}
|
| 480 |
+
|
| 481 |
+
if (itB + 1 < ntB) {
|
| 482 |
+
gather_tile(itB + 1, vals_buf[next_buf]);
|
| 483 |
+
}
|
| 484 |
+
|
| 485 |
+
#pragma unroll
|
| 486 |
+
for (int k0 = 0; k0 < warp_size; k0 += tile_B::J) {
|
| 487 |
+
tile_B B;
|
| 488 |
+
load_ldmatrix(B, tile_xy + k0, tile_k_padded);
|
| 489 |
+
#pragma unroll
|
| 490 |
+
for (int itA = 0; itA < ntA; ++itA) {
|
| 491 |
+
mma(C[itA][itB], A[itA][k0/tile_B::J], B);
|
| 492 |
+
}
|
| 493 |
+
}
|
| 494 |
+
|
| 495 |
+
if (itB + 1 < ntB) {
|
| 496 |
+
curr_buf ^= 1;
|
| 497 |
+
next_buf ^= 1;
|
| 498 |
+
}
|
| 499 |
+
}
|
| 500 |
+
} else {
|
| 501 |
+
static_assert(std::is_same_v<T, void>, "unsupported type");
|
| 502 |
+
}
|
| 503 |
+
}
|
| 504 |
+
|
| 505 |
+
float * buf_iw = (float *) compute_base;
|
| 506 |
+
constexpr int kiw = nwarps*rows_per_block + mmf_get_padding();
|
| 507 |
+
|
| 508 |
+
if (nwarps > 1) {
|
| 509 |
+
__syncthreads();
|
| 510 |
+
}
|
| 511 |
+
#pragma unroll
|
| 512 |
+
for (int itB = 0; itB < ntB; ++itB) {
|
| 513 |
+
#pragma unroll
|
| 514 |
+
for (int itA = 0; itA < ntA; ++itA) {
|
| 515 |
+
#pragma unroll
|
| 516 |
+
for (int l = 0; l < tile_C::ne; ++l) {
|
| 517 |
+
const int i = threadIdx.y*rows_per_block + itA*tile_C::I + tile_C::get_i(l);
|
| 518 |
+
const int j = itB*tile_C::J + tile_C::get_j(l);
|
| 519 |
+
buf_iw[j*kiw + i] = C[itA][itB].x[l];
|
| 520 |
+
}
|
| 521 |
+
}
|
| 522 |
+
}
|
| 523 |
+
|
| 524 |
+
if (nwarps > 1) {
|
| 525 |
+
__syncthreads();
|
| 526 |
+
}
|
| 527 |
+
|
| 528 |
+
#pragma unroll
|
| 529 |
+
for (int j0 = 0; j0 < cols_per_block; j0 += nwarps) {
|
| 530 |
+
const int j = j0 + threadIdx.y;
|
| 531 |
+
|
| 532 |
+
if (j0 + nwarps > cols_per_block && j >= cols_per_block) {
|
| 533 |
+
return;
|
| 534 |
+
}
|
| 535 |
+
|
| 536 |
+
float sum[rows_per_block/warp_size] = {0.0f};
|
| 537 |
+
static_assert((rows_per_block % warp_size) == 0, "rows_per_block must be a multiple of warp_size.");
|
| 538 |
+
#pragma unroll
|
| 539 |
+
for (int i0 = 0; i0 < nwarps*rows_per_block; i0 += rows_per_block) {
|
| 540 |
+
#pragma unroll
|
| 541 |
+
for (int i1 = 0; i1 < sizeof(sum)/sizeof(sum[0]); ++i1) {
|
| 542 |
+
const int i = i0 + i1*warp_size + threadIdx.x;
|
| 543 |
+
|
| 544 |
+
sum[i1] += buf_iw[j * kiw + i];
|
| 545 |
+
}
|
| 546 |
+
}
|
| 547 |
+
|
| 548 |
+
const int global_j = col_base + j;
|
| 549 |
+
if (j < cols_per_block && global_j < ncols_expert && nchannels_dst > 0) {
|
| 550 |
+
const int dst_entry = ids_dst_expert[global_j];
|
| 551 |
+
const uint2 qrm = fast_div_modulo((uint32_t) dst_entry, nch_fd);
|
| 552 |
+
const int token = (int) qrm.x;
|
| 553 |
+
if (token < ncols_dst_total) {
|
| 554 |
+
const int slot = (int) qrm.y;
|
| 555 |
+
#pragma unroll
|
| 556 |
+
for (int i0 = 0; i0 < sizeof(sum)/sizeof(sum[0]); ++i0) {
|
| 557 |
+
dst[slot * stride_channel_dst + token * stride_col_dst + row0 + i0*warp_size + threadIdx.x] = sum[i0];
|
| 558 |
+
}
|
| 559 |
+
}
|
| 560 |
+
}
|
| 561 |
+
}
|
| 562 |
+
}
|
| 563 |
+
#else
|
| 564 |
+
GGML_UNUSED_VARS(x, y, ids_src_compact, ids_dst_compact, expert_bounds, dst,
|
| 565 |
+
ncols, ncols_dst_total, nchannels_dst, stride_row, stride_col_y, stride_col_dst,
|
| 566 |
+
channel_ratio, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 567 |
+
sample_ratio, stride_sample_x, stride_sample_y, stride_sample_dst, sis1_fd, nch_fd);
|
| 568 |
+
NO_DEVICE_CODE;
|
| 569 |
+
#endif // defined(VOLTA_MMA_AVAILABLE) || defined(TURING_MMA_AVAILABLE) || defined(AMD_WMMA_AVAILABLE) || defined(AMD_MFMA_AVAILABLE)
|
| 570 |
+
}
|
| 571 |
+
|
| 572 |
+
template<typename T, int rows_per_block, int cols_per_block, int nwarps>
|
| 573 |
+
static inline void mul_mat_f_switch_ids(
|
| 574 |
+
const T * x, const float * y, const int32_t * ids, float * dst,
|
| 575 |
+
const int64_t ncols_x, const int64_t ncols_dst, const int64_t nchannels_dst,
|
| 576 |
+
const int64_t stride_row, const int64_t stride_col_y, const int64_t stride_col_dst,
|
| 577 |
+
const int64_t stride_col_id, const int64_t stride_row_id,
|
| 578 |
+
const int64_t channel_ratio, const int64_t stride_channel_x, const int64_t stride_channel_y, const int64_t stride_channel_dst,
|
| 579 |
+
const int64_t sample_ratio, const int64_t stride_sample_x, const int64_t stride_sample_y, const int64_t stride_sample_dst,
|
| 580 |
+
const dim3 & block_nums, const dim3 & block_dims, const int nbytes_shared_total, cudaStream_t stream,
|
| 581 |
+
const mmf_ids_data * ids_data) {
|
| 582 |
+
const bool has_ids_data = ids_data && ids_data->ids_src_compact;
|
| 583 |
+
|
| 584 |
+
// Use the compact-ids kernel only for larger tiles; for small ncols_dst (< 16)
|
| 585 |
+
// we prefer the normal mul_mat_f path with has_ids=true.
|
| 586 |
+
if (has_ids_data && ncols_dst > 16) {
|
| 587 |
+
const int max_tiles = (int) ((ncols_dst + cols_per_block - 1) / cols_per_block);
|
| 588 |
+
if (max_tiles == 0) {
|
| 589 |
+
return;
|
| 590 |
+
}
|
| 591 |
+
dim3 block_nums_ids(block_nums.x, ids_data->n_experts, max_tiles);
|
| 592 |
+
|
| 593 |
+
const uint3 sis1_fd = ids_data->sis1 > 0 ? init_fastdiv_values((uint32_t) ids_data->sis1) : make_uint3(0, 0, 1);
|
| 594 |
+
const uint3 nch_fd = init_fastdiv_values((uint32_t) nchannels_dst);
|
| 595 |
+
|
| 596 |
+
mul_mat_f_ids<T, rows_per_block, cols_per_block, nwarps><<<block_nums_ids, block_dims, nbytes_shared_total, stream>>>
|
| 597 |
+
(x, y, ids_data->ids_src_compact, ids_data->ids_dst_compact, ids_data->expert_bounds_dev, dst,
|
| 598 |
+
ncols_x, ncols_dst, nchannels_dst, stride_row, stride_col_y, stride_col_dst,
|
| 599 |
+
channel_ratio, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 600 |
+
sample_ratio, stride_sample_x, stride_sample_y, stride_sample_dst,
|
| 601 |
+
sis1_fd, nch_fd);
|
| 602 |
+
} else if (ids) {
|
| 603 |
+
const int64_t col_tiles = (ncols_dst + cols_per_block - 1) / cols_per_block;
|
| 604 |
+
dim3 block_nums_ids = block_nums;
|
| 605 |
+
block_nums_ids.y *= col_tiles;
|
| 606 |
+
|
| 607 |
+
mul_mat_f<T, rows_per_block, cols_per_block, nwarps, true><<<block_nums_ids, block_dims, nbytes_shared_total, stream>>>
|
| 608 |
+
(x, y, ids, dst, ncols_x, ncols_dst, nchannels_dst, stride_row, stride_col_y, stride_col_dst,
|
| 609 |
+
stride_col_id, stride_row_id, channel_ratio, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 610 |
+
sample_ratio, stride_sample_x, stride_sample_y, stride_sample_dst);
|
| 611 |
+
} else {
|
| 612 |
+
mul_mat_f<T, rows_per_block, cols_per_block, nwarps, false><<<block_nums, block_dims, nbytes_shared_total, stream>>>
|
| 613 |
+
(x, y, ids, dst, ncols_x, cols_per_block, nchannels_dst, stride_row, stride_col_y, stride_col_dst,
|
| 614 |
+
stride_col_id, stride_row_id, channel_ratio, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 615 |
+
sample_ratio, stride_sample_x, stride_sample_y, stride_sample_dst);
|
| 616 |
+
}
|
| 617 |
+
}
|
| 618 |
+
|
| 619 |
+
template <typename T, int rows_per_block, int cols_per_block>
|
| 620 |
+
void mul_mat_f_cuda(
|
| 621 |
+
const T * x, const float * y, const int32_t * ids, float * dst,
|
| 622 |
+
const int64_t ncols_x, const int64_t nrows_x, const int64_t ncols_dst,
|
| 623 |
+
const int64_t stride_row, const int64_t stride_col_y, const int64_t stride_col_dst,
|
| 624 |
+
const int64_t stride_col_id, const int64_t stride_row_id,
|
| 625 |
+
const int64_t nchannels_x, const int64_t nchannels_y, const int64_t nchannels_dst,
|
| 626 |
+
const int64_t stride_channel_x, const int64_t stride_channel_y, const int64_t stride_channel_dst, const int64_t nsamples_x,
|
| 627 |
+
const int64_t nsamples_dst, const int64_t stride_sample_x, const int64_t stride_sample_y, const int64_t stride_sample_dst,
|
| 628 |
+
cudaStream_t stream, const mmf_ids_data * ids_data) {
|
| 629 |
+
typedef tile<16, 8, T> tile_A_16;
|
| 630 |
+
typedef tile<32, 8, T> tile_A_32;
|
| 631 |
+
typedef tile<16, 8, T> tile_B_16;
|
| 632 |
+
typedef tile< 8, 8, T> tile_B_8;
|
| 633 |
+
|
| 634 |
+
GGML_ASSERT(ncols_x % 2 == 0);
|
| 635 |
+
GGML_ASSERT(stride_row % 2 == 0);
|
| 636 |
+
GGML_ASSERT(stride_col_y % 2 == 0);
|
| 637 |
+
GGML_ASSERT(ids || nchannels_dst % nchannels_x == 0);
|
| 638 |
+
GGML_ASSERT( nsamples_dst % nsamples_x == 0);
|
| 639 |
+
const int64_t channel_ratio = nchannels_dst / nchannels_x;
|
| 640 |
+
const int64_t sample_ratio = nsamples_dst / nsamples_x;
|
| 641 |
+
|
| 642 |
+
const int device = ggml_cuda_get_device();
|
| 643 |
+
const int cc = ggml_cuda_info().devices[device].cc;
|
| 644 |
+
const int warp_size = ggml_cuda_info().devices[device].warp_size;
|
| 645 |
+
|
| 646 |
+
int64_t nwarps_best = 1;
|
| 647 |
+
int64_t niter_best = (ncols_x + warp_size*2 - 1) / (warp_size*2);
|
| 648 |
+
int64_t max_block_size = mmf_get_max_block_size(cc);
|
| 649 |
+
for (int64_t nwarps = 2; nwarps <= max_block_size/warp_size; nwarps++) {
|
| 650 |
+
const int64_t niter = (ncols_x + nwarps*warp_size*2 - 1) / (nwarps*warp_size*2);
|
| 651 |
+
if (niter < niter_best) {
|
| 652 |
+
niter_best = niter;
|
| 653 |
+
nwarps_best = nwarps;
|
| 654 |
+
}
|
| 655 |
+
}
|
| 656 |
+
|
| 657 |
+
const int nbytes_shared_iter = nwarps_best * (volta_mma_available(cc) ? tile_A_32::I : tile_A_16::I) * (warp_size + mmf_get_padding(cc)) * 4;
|
| 658 |
+
const int nbytes_cols_per_block_pad = (amd_wmma_available(cc) || amd_mfma_available(cc)) ? tile_B_16::I : tile_B_8::I;
|
| 659 |
+
const int nbytes_shared_combine = GGML_PAD(cols_per_block, nbytes_cols_per_block_pad) * (nwarps_best*rows_per_block + mmf_get_padding(cc)) * 4;
|
| 660 |
+
const int nbytes_shared = std::max(nbytes_shared_iter, nbytes_shared_combine);
|
| 661 |
+
const int nbytes_slotmap = ids ? GGML_PAD(cols_per_block, 16) * sizeof(int) : 0;
|
| 662 |
+
const int nbytes_shared_total = nbytes_shared + nbytes_slotmap;
|
| 663 |
+
const int64_t grid_y = ids ? nchannels_x : nchannels_dst;
|
| 664 |
+
|
| 665 |
+
const dim3 block_nums(nrows_x/rows_per_block, grid_y, nsamples_dst);
|
| 666 |
+
const dim3 block_dims(warp_size, nwarps_best, 1);
|
| 667 |
+
|
| 668 |
+
switch (nwarps_best) {
|
| 669 |
+
case 1: {
|
| 670 |
+
mul_mat_f_switch_ids<T, rows_per_block, cols_per_block, 1>(
|
| 671 |
+
x, y, ids, dst, ncols_x, ncols_dst, nchannels_dst, stride_row, stride_col_y, stride_col_dst,
|
| 672 |
+
stride_col_id, stride_row_id, channel_ratio, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 673 |
+
sample_ratio, stride_sample_x, stride_sample_y, stride_sample_dst, block_nums, block_dims, nbytes_shared_total, stream,
|
| 674 |
+
ids_data);
|
| 675 |
+
} break;
|
| 676 |
+
case 2: {
|
| 677 |
+
mul_mat_f_switch_ids<T, rows_per_block, cols_per_block, 2>(
|
| 678 |
+
x, y, ids, dst, ncols_x, ncols_dst, nchannels_dst, stride_row, stride_col_y, stride_col_dst,
|
| 679 |
+
stride_col_id, stride_row_id, channel_ratio, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 680 |
+
sample_ratio, stride_sample_x, stride_sample_y, stride_sample_dst, block_nums, block_dims, nbytes_shared_total, stream,
|
| 681 |
+
ids_data);
|
| 682 |
+
} break;
|
| 683 |
+
case 3: {
|
| 684 |
+
mul_mat_f_switch_ids<T, rows_per_block, cols_per_block, 3>(
|
| 685 |
+
x, y, ids, dst, ncols_x, ncols_dst, nchannels_dst, stride_row, stride_col_y, stride_col_dst,
|
| 686 |
+
stride_col_id, stride_row_id, channel_ratio, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 687 |
+
sample_ratio, stride_sample_x, stride_sample_y, stride_sample_dst, block_nums, block_dims, nbytes_shared_total, stream,
|
| 688 |
+
ids_data);
|
| 689 |
+
} break;
|
| 690 |
+
case 4: {
|
| 691 |
+
mul_mat_f_switch_ids<T, rows_per_block, cols_per_block, 4>(
|
| 692 |
+
x, y, ids, dst, ncols_x, ncols_dst, nchannels_dst, stride_row, stride_col_y, stride_col_dst,
|
| 693 |
+
stride_col_id, stride_row_id, channel_ratio, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 694 |
+
sample_ratio, stride_sample_x, stride_sample_y, stride_sample_dst, block_nums, block_dims, nbytes_shared_total, stream,
|
| 695 |
+
ids_data);
|
| 696 |
+
} break;
|
| 697 |
+
case 5: {
|
| 698 |
+
mul_mat_f_switch_ids<T, rows_per_block, cols_per_block, 5>(
|
| 699 |
+
x, y, ids, dst, ncols_x, ncols_dst, nchannels_dst, stride_row, stride_col_y, stride_col_dst,
|
| 700 |
+
stride_col_id, stride_row_id, channel_ratio, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 701 |
+
sample_ratio, stride_sample_x, stride_sample_y, stride_sample_dst, block_nums, block_dims, nbytes_shared_total, stream,
|
| 702 |
+
ids_data);
|
| 703 |
+
} break;
|
| 704 |
+
case 6: {
|
| 705 |
+
mul_mat_f_switch_ids<T, rows_per_block, cols_per_block, 6>(
|
| 706 |
+
x, y, ids, dst, ncols_x, ncols_dst, nchannels_dst, stride_row, stride_col_y, stride_col_dst,
|
| 707 |
+
stride_col_id, stride_row_id, channel_ratio, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 708 |
+
sample_ratio, stride_sample_x, stride_sample_y, stride_sample_dst, block_nums, block_dims, nbytes_shared_total, stream,
|
| 709 |
+
ids_data);
|
| 710 |
+
} break;
|
| 711 |
+
case 7: {
|
| 712 |
+
mul_mat_f_switch_ids<T, rows_per_block, cols_per_block, 7>(
|
| 713 |
+
x, y, ids, dst, ncols_x, ncols_dst, nchannels_dst, stride_row, stride_col_y, stride_col_dst,
|
| 714 |
+
stride_col_id, stride_row_id, channel_ratio, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 715 |
+
sample_ratio, stride_sample_x, stride_sample_y, stride_sample_dst, block_nums, block_dims, nbytes_shared_total, stream,
|
| 716 |
+
ids_data);
|
| 717 |
+
} break;
|
| 718 |
+
case 8: {
|
| 719 |
+
mul_mat_f_switch_ids<T, rows_per_block, cols_per_block, 8>(
|
| 720 |
+
x, y, ids, dst, ncols_x, ncols_dst, nchannels_dst, stride_row, stride_col_y, stride_col_dst,
|
| 721 |
+
stride_col_id, stride_row_id, channel_ratio, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 722 |
+
sample_ratio, stride_sample_x, stride_sample_y, stride_sample_dst, block_nums, block_dims, nbytes_shared_total, stream,
|
| 723 |
+
ids_data);
|
| 724 |
+
} break;
|
| 725 |
+
default: {
|
| 726 |
+
GGML_ABORT("fatal error");
|
| 727 |
+
} break;
|
| 728 |
+
}
|
| 729 |
+
|
| 730 |
+
GGML_UNUSED_VARS(nchannels_y);
|
| 731 |
+
}
|
| 732 |
+
|
| 733 |
+
template <typename T, int rows_per_block>
|
| 734 |
+
static void mul_mat_f_switch_cols_per_block(
|
| 735 |
+
const T * x, const float * y, const int32_t * ids, float * dst,
|
| 736 |
+
const int64_t ncols_x, const int64_t nrows_x, const int64_t ncols_dst,
|
| 737 |
+
const int64_t stride_row, const int64_t stride_col_y, const int64_t stride_col_dst,
|
| 738 |
+
const int64_t stride_col_id, const int stride_row_id,
|
| 739 |
+
const int64_t nchannels_x, const int64_t nchannels_y, const int64_t nchannels_dst,
|
| 740 |
+
const int64_t stride_channel_x, const int64_t stride_channel_y, const int64_t stride_channel_dst, const int64_t nsamples_x,
|
| 741 |
+
const int64_t nsamples_dst, const int64_t stride_sample_x, const int64_t stride_sample_y, const int64_t stride_sample_dst,
|
| 742 |
+
cudaStream_t stream, const mmf_ids_data * ids_data) {
|
| 743 |
+
|
| 744 |
+
const int ncols_case = (ids && ncols_dst > 16) ? 16 : ncols_dst;
|
| 745 |
+
|
| 746 |
+
GGML_ASSERT(ids || ncols_dst <= 16);
|
| 747 |
+
|
| 748 |
+
switch (ncols_case) {
|
| 749 |
+
case 1: {
|
| 750 |
+
mul_mat_f_cuda<T, rows_per_block, 1>(x, y, ids, dst, ncols_x, nrows_x, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 751 |
+
stride_col_id, stride_row_id, nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 752 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, stream, ids_data);
|
| 753 |
+
} break;
|
| 754 |
+
case 2: {
|
| 755 |
+
mul_mat_f_cuda<T, rows_per_block, 2>(x, y, ids, dst, ncols_x, nrows_x, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 756 |
+
stride_col_id, stride_row_id, nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 757 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, stream, ids_data);
|
| 758 |
+
} break;
|
| 759 |
+
case 3: {
|
| 760 |
+
mul_mat_f_cuda<T, rows_per_block, 3>(x, y, ids, dst, ncols_x, nrows_x, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 761 |
+
stride_col_id, stride_row_id, nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 762 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, stream, ids_data);
|
| 763 |
+
} break;
|
| 764 |
+
case 4: {
|
| 765 |
+
mul_mat_f_cuda<T, rows_per_block, 4>(x, y, ids, dst, ncols_x, nrows_x, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 766 |
+
stride_col_id, stride_row_id, nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 767 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, stream, ids_data);
|
| 768 |
+
} break;
|
| 769 |
+
case 5: {
|
| 770 |
+
mul_mat_f_cuda<T, rows_per_block, 5>(x, y, ids, dst, ncols_x, nrows_x, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 771 |
+
stride_col_id, stride_row_id, nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 772 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, stream, ids_data);
|
| 773 |
+
} break;
|
| 774 |
+
case 6: {
|
| 775 |
+
mul_mat_f_cuda<T, rows_per_block, 6>(x, y, ids, dst, ncols_x, nrows_x, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 776 |
+
stride_col_id, stride_row_id, nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 777 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, stream, ids_data);
|
| 778 |
+
} break;
|
| 779 |
+
case 7: {
|
| 780 |
+
mul_mat_f_cuda<T, rows_per_block, 7>(x, y, ids, dst, ncols_x, nrows_x, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 781 |
+
stride_col_id, stride_row_id, nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 782 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, stream, ids_data);
|
| 783 |
+
} break;
|
| 784 |
+
case 8: {
|
| 785 |
+
mul_mat_f_cuda<T, rows_per_block, 8>(x, y, ids, dst, ncols_x, nrows_x, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 786 |
+
stride_col_id, stride_row_id, nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 787 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, stream, ids_data);
|
| 788 |
+
} break;
|
| 789 |
+
case 9: {
|
| 790 |
+
mul_mat_f_cuda<T, rows_per_block, 9>(x, y, ids, dst, ncols_x, nrows_x, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 791 |
+
stride_col_id, stride_row_id, nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 792 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, stream, ids_data);
|
| 793 |
+
} break;
|
| 794 |
+
case 10: {
|
| 795 |
+
mul_mat_f_cuda<T, rows_per_block, 10>(x, y, ids, dst, ncols_x, nrows_x, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 796 |
+
stride_col_id, stride_row_id, nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 797 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, stream, ids_data);
|
| 798 |
+
} break;
|
| 799 |
+
case 11: {
|
| 800 |
+
mul_mat_f_cuda<T, rows_per_block, 11>(x, y, ids, dst, ncols_x, nrows_x, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 801 |
+
stride_col_id, stride_row_id, nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 802 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, stream, ids_data);
|
| 803 |
+
} break;
|
| 804 |
+
case 12: {
|
| 805 |
+
mul_mat_f_cuda<T, rows_per_block, 12>(x, y, ids, dst, ncols_x, nrows_x, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 806 |
+
stride_col_id, stride_row_id, nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 807 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, stream, ids_data);
|
| 808 |
+
} break;
|
| 809 |
+
case 13: {
|
| 810 |
+
mul_mat_f_cuda<T, rows_per_block, 13>(x, y, ids, dst, ncols_x, nrows_x, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 811 |
+
stride_col_id, stride_row_id, nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 812 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, stream, ids_data);
|
| 813 |
+
} break;
|
| 814 |
+
case 14: {
|
| 815 |
+
mul_mat_f_cuda<T, rows_per_block, 14>(x, y, ids, dst, ncols_x, nrows_x, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 816 |
+
stride_col_id, stride_row_id, nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 817 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, stream, ids_data);
|
| 818 |
+
} break;
|
| 819 |
+
case 15: {
|
| 820 |
+
mul_mat_f_cuda<T, rows_per_block, 15>(x, y, ids, dst, ncols_x, nrows_x, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 821 |
+
stride_col_id, stride_row_id, nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 822 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, stream, ids_data);
|
| 823 |
+
} break;
|
| 824 |
+
case 16: {
|
| 825 |
+
mul_mat_f_cuda<T, rows_per_block, 16>(x, y, ids, dst, ncols_x, nrows_x, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 826 |
+
stride_col_id, stride_row_id, nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 827 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, stream, ids_data);
|
| 828 |
+
} break;
|
| 829 |
+
default: {
|
| 830 |
+
GGML_ABORT("fatal error");
|
| 831 |
+
} break;
|
| 832 |
+
}
|
| 833 |
+
}
|
| 834 |
+
|
| 835 |
+
template <typename T>
|
| 836 |
+
static void mul_mat_f_switch_rows_per_block(
|
| 837 |
+
const int rows_per_block, const T * x, const float * y, const int32_t * ids, float * dst,
|
| 838 |
+
const int64_t ncols_x, const int64_t nrows_x, const int64_t ncols_dst,
|
| 839 |
+
const int64_t stride_row, const int64_t stride_col_y, const int64_t stride_col_dst,
|
| 840 |
+
const int64_t stride_col_id, const int stride_row_id,
|
| 841 |
+
const int64_t nchannels_x, const int64_t nchannels_y, const int64_t nchannels_dst,
|
| 842 |
+
const int64_t stride_channel_x, const int64_t stride_channel_y, const int64_t stride_channel_dst, const int64_t nsamples_x,
|
| 843 |
+
const int64_t nsamples_dst, const int64_t stride_sample_x, const int64_t stride_sample_y, const int64_t stride_sample_dst,
|
| 844 |
+
cudaStream_t stream, const mmf_ids_data * ids_data) {
|
| 845 |
+
switch (rows_per_block) {
|
| 846 |
+
case MMF_ROWS_PER_BLOCK: {
|
| 847 |
+
mul_mat_f_switch_cols_per_block<T, MMF_ROWS_PER_BLOCK>(
|
| 848 |
+
x, y, ids, dst, ncols_x, nrows_x, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 849 |
+
stride_col_id, stride_row_id, nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 850 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, stream, ids_data);
|
| 851 |
+
} break;
|
| 852 |
+
case MMF_ROWS_PER_BLOCK_CDNA: {
|
| 853 |
+
mul_mat_f_switch_cols_per_block<T, MMF_ROWS_PER_BLOCK_CDNA>(
|
| 854 |
+
x, y, ids, dst, ncols_x, nrows_x, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 855 |
+
stride_col_id, stride_row_id, nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 856 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, stream, ids_data);
|
| 857 |
+
} break;
|
| 858 |
+
default:
|
| 859 |
+
GGML_ABORT("unsupported rows_per_block: %i", rows_per_block);
|
| 860 |
+
}
|
| 861 |
+
}
|
| 862 |
+
|
| 863 |
+
#define DECL_MMF_CASE_HELPER(T, nrows_dst, ncols_dst) \
|
| 864 |
+
template void mul_mat_f_cuda<T, nrows_dst, ncols_dst>( \
|
| 865 |
+
const T * x, const float * y, const int32_t * ids, float * dst, \
|
| 866 |
+
const int64_t ncols_x, const int64_t nrows_x, int64_t ncols_dst_total, const int64_t stride_row, const int64_t stride_col_y, const int64_t stride_col_dst, \
|
| 867 |
+
const int64_t stride_col_id, const int64_t stride_row_id, \
|
| 868 |
+
const int64_t nchannels_x, const int64_t nchannels_y, const int64_t nchannels_dst, \
|
| 869 |
+
const int64_t stride_channel_x, const int64_t stride_channel_y, const int64_t stride_channel_dst, const int64_t nsamples_x,\
|
| 870 |
+
const int64_t nsamples_dst, const int64_t stride_sample_x, const int64_t stride_sample_y, const int64_t stride_sample_dst, \
|
| 871 |
+
cudaStream_t stream, const mmf_ids_data * ids_data);
|
| 872 |
+
|
| 873 |
+
#if !defined(GGML_USE_MUSA)
|
| 874 |
+
#define DECL_MMF_CASE_EXTERN(ncols_dst) \
|
| 875 |
+
extern DECL_MMF_CASE_HELPER(float, MMF_ROWS_PER_BLOCK, ncols_dst) \
|
| 876 |
+
extern DECL_MMF_CASE_HELPER(half2, MMF_ROWS_PER_BLOCK, ncols_dst) \
|
| 877 |
+
extern DECL_MMF_CASE_HELPER(nv_bfloat162, MMF_ROWS_PER_BLOCK, ncols_dst) \
|
| 878 |
+
extern DECL_MMF_CASE_HELPER(float, MMF_ROWS_PER_BLOCK_CDNA, ncols_dst) \
|
| 879 |
+
extern DECL_MMF_CASE_HELPER(half2, MMF_ROWS_PER_BLOCK_CDNA, ncols_dst) \
|
| 880 |
+
extern DECL_MMF_CASE_HELPER(nv_bfloat162, MMF_ROWS_PER_BLOCK_CDNA, ncols_dst)
|
| 881 |
+
|
| 882 |
+
#define DECL_MMF_CASE(ncols_dst) \
|
| 883 |
+
DECL_MMF_CASE_HELPER(float, MMF_ROWS_PER_BLOCK, ncols_dst) \
|
| 884 |
+
DECL_MMF_CASE_HELPER(half2, MMF_ROWS_PER_BLOCK, ncols_dst) \
|
| 885 |
+
DECL_MMF_CASE_HELPER(nv_bfloat162, MMF_ROWS_PER_BLOCK, ncols_dst) \
|
| 886 |
+
DECL_MMF_CASE_HELPER(float, MMF_ROWS_PER_BLOCK_CDNA, ncols_dst) \
|
| 887 |
+
DECL_MMF_CASE_HELPER(half2, MMF_ROWS_PER_BLOCK_CDNA, ncols_dst) \
|
| 888 |
+
DECL_MMF_CASE_HELPER(nv_bfloat162, MMF_ROWS_PER_BLOCK_CDNA, ncols_dst)
|
| 889 |
+
|
| 890 |
+
DECL_MMF_CASE_EXTERN(1);
|
| 891 |
+
DECL_MMF_CASE_EXTERN(2);
|
| 892 |
+
DECL_MMF_CASE_EXTERN(3);
|
| 893 |
+
DECL_MMF_CASE_EXTERN(4);
|
| 894 |
+
DECL_MMF_CASE_EXTERN(5);
|
| 895 |
+
DECL_MMF_CASE_EXTERN(6);
|
| 896 |
+
DECL_MMF_CASE_EXTERN(7);
|
| 897 |
+
DECL_MMF_CASE_EXTERN(8);
|
| 898 |
+
DECL_MMF_CASE_EXTERN(9);
|
| 899 |
+
DECL_MMF_CASE_EXTERN(10);
|
| 900 |
+
DECL_MMF_CASE_EXTERN(11);
|
| 901 |
+
DECL_MMF_CASE_EXTERN(12);
|
| 902 |
+
DECL_MMF_CASE_EXTERN(13);
|
| 903 |
+
DECL_MMF_CASE_EXTERN(14);
|
| 904 |
+
DECL_MMF_CASE_EXTERN(15);
|
| 905 |
+
DECL_MMF_CASE_EXTERN(16);
|
| 906 |
+
#else
|
| 907 |
+
#define DECL_MMF_CASE(ncols_dst)
|
| 908 |
+
#endif
|
backend/llama.cpp/ggml/src/ggml-cuda/mmid.cu
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
#include "mmid.cuh"
|
| 3 |
+
|
| 4 |
+
// To reduce shared memory use, store "it" and "iex_used" with 22/10 bits each.
|
| 5 |
+
struct mm_ids_helper_store {
|
| 6 |
+
uint32_t data;
|
| 7 |
+
|
| 8 |
+
__device__ mm_ids_helper_store(const uint32_t it, const uint32_t iex_used) {
|
| 9 |
+
data = (it & 0x003FFFFF) | (iex_used << 22);
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
__device__ uint32_t it() const {
|
| 13 |
+
return data & 0x003FFFFF;
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
__device__ uint32_t iex_used() const {
|
| 17 |
+
return data >> 22;
|
| 18 |
+
}
|
| 19 |
+
};
|
| 20 |
+
static_assert(sizeof(mm_ids_helper_store) == 4, "unexpected size for mm_ids_helper_store");
|
| 21 |
+
|
| 22 |
+
// Helper function for mul_mat_id, converts ids to a more convenient format.
|
| 23 |
+
// ids_src1 describes how to permute the flattened column indices of src1 in order to get a compact src1 tensor sorted by expert.
|
| 24 |
+
// ids_dst describes the same mapping but for the dst tensor.
|
| 25 |
+
// The upper and lower bounds for the ith expert in the compact src1 tensor are stored in expert_bounds[i:i+1].
|
| 26 |
+
template <int n_expert_used_template>
|
| 27 |
+
__launch_bounds__(ggml_cuda_get_physical_warp_size(), 1)
|
| 28 |
+
static __global__ void mm_ids_helper(
|
| 29 |
+
const int32_t * __restrict__ ids, int32_t * __restrict__ ids_src1, int32_t * __restrict__ ids_dst, int32_t * __restrict__ expert_bounds,
|
| 30 |
+
const int n_tokens, const int n_expert_used_var, const int nchannels_y, const int si1, const int sis1) {
|
| 31 |
+
constexpr int warp_size = ggml_cuda_get_physical_warp_size();
|
| 32 |
+
const int n_expert_used = n_expert_used_template == 0 ? n_expert_used_var : n_expert_used_template;
|
| 33 |
+
const int expert = blockIdx.x;
|
| 34 |
+
|
| 35 |
+
extern __shared__ char data_mm_ids_helper[];
|
| 36 |
+
mm_ids_helper_store * store = (mm_ids_helper_store *) data_mm_ids_helper;
|
| 37 |
+
|
| 38 |
+
int nex_prev = 0; // Number of columns for experts with a lower index.
|
| 39 |
+
int it_compact = 0; // Running index for the compact slice of this expert.
|
| 40 |
+
|
| 41 |
+
if constexpr (n_expert_used_template == 0) {
|
| 42 |
+
// Generic implementation:
|
| 43 |
+
for (int it = 0; it < n_tokens; ++it) {
|
| 44 |
+
int iex_used = -1; // The index at which the expert is used, if any.
|
| 45 |
+
for (int iex = threadIdx.x; iex < n_expert_used; iex += warp_size) {
|
| 46 |
+
const int expert_used = ids[it*si1 + iex];
|
| 47 |
+
nex_prev += expert_used < expert;
|
| 48 |
+
if (expert_used == expert) {
|
| 49 |
+
iex_used = iex;
|
| 50 |
+
}
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
if (iex_used != -1) {
|
| 54 |
+
store[it_compact] = mm_ids_helper_store(it, iex_used);
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
if (warp_reduce_any<warp_size>(iex_used != -1)) {
|
| 58 |
+
it_compact++;
|
| 59 |
+
}
|
| 60 |
+
}
|
| 61 |
+
} else {
|
| 62 |
+
// Implementation optimized for specific numbers of experts used:
|
| 63 |
+
static_assert(n_expert_used == 6 || warp_size % n_expert_used == 0, "bad n_expert_used");
|
| 64 |
+
const int neu_padded = n_expert_used == 6 ? 8 : n_expert_used; // Padded to next higher power of 2.
|
| 65 |
+
for (int it0 = 0; it0 < n_tokens; it0 += warp_size/neu_padded) {
|
| 66 |
+
const int it = it0 + threadIdx.x / neu_padded;
|
| 67 |
+
|
| 68 |
+
const int iex = threadIdx.x % neu_padded; // The index at which the expert is used, if any.
|
| 69 |
+
const int expert_used = (neu_padded == n_expert_used || iex < n_expert_used) && it < n_tokens ?
|
| 70 |
+
ids[it*si1 + iex] : INT_MAX;
|
| 71 |
+
const int iex_used = expert_used == expert ? iex : -1;
|
| 72 |
+
nex_prev += expert_used < expert;
|
| 73 |
+
|
| 74 |
+
// Whether the threads at this token position have used the expert:
|
| 75 |
+
const int it_compact_add_self = warp_reduce_any<neu_padded>(iex_used != -1);
|
| 76 |
+
|
| 77 |
+
// Do a scan over threads at lower token positions in warp to get the correct index for writing data:
|
| 78 |
+
int it_compact_add_lower = 0;
|
| 79 |
+
#pragma unroll
|
| 80 |
+
for (int offset = neu_padded; offset < warp_size; offset += neu_padded) {
|
| 81 |
+
const int tmp = __shfl_up_sync(0xFFFFFFFF, it_compact_add_self, offset, warp_size);
|
| 82 |
+
if (threadIdx.x >= static_cast<unsigned int>(offset)) {
|
| 83 |
+
it_compact_add_lower += tmp;
|
| 84 |
+
}
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
if (iex_used != -1) {
|
| 88 |
+
store[it_compact + it_compact_add_lower] = mm_ids_helper_store(it, iex_used);
|
| 89 |
+
}
|
| 90 |
+
|
| 91 |
+
// The thread with the highest index in the warp always has the sum over the whole warp, use it to increment all threads:
|
| 92 |
+
it_compact += __shfl_sync(0xFFFFFFFF, it_compact_add_lower + it_compact_add_self, warp_size - 1, warp_size);
|
| 93 |
+
}
|
| 94 |
+
}
|
| 95 |
+
nex_prev = warp_reduce_sum<warp_size>(nex_prev);
|
| 96 |
+
|
| 97 |
+
for (int itc = threadIdx.x; itc < it_compact; itc += warp_size) {
|
| 98 |
+
const mm_ids_helper_store store_it = store[itc];
|
| 99 |
+
const int it = store_it.it();
|
| 100 |
+
const int iex_used = store_it.iex_used();
|
| 101 |
+
ids_src1[nex_prev + itc] = it*sis1 + iex_used % nchannels_y;
|
| 102 |
+
ids_dst [nex_prev + itc] = it*n_expert_used + iex_used;
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
if (threadIdx.x != 0) {
|
| 106 |
+
return;
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
expert_bounds[expert] = nex_prev;
|
| 110 |
+
|
| 111 |
+
if (expert < static_cast<int>(gridDim.x) - 1) {
|
| 112 |
+
return;
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
expert_bounds[gridDim.x] = nex_prev + it_compact;
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
template <int n_expert_used_template>
|
| 119 |
+
static void launch_mm_ids_helper(
|
| 120 |
+
const int32_t * __restrict__ ids, int32_t * __restrict__ ids_src1, int32_t * __restrict__ ids_dst, int32_t * __restrict__ expert_bounds,
|
| 121 |
+
const int n_experts, const int n_tokens, const int n_expert_used_var, const int nchannels_y, const int si1, const int sis1, cudaStream_t stream) {
|
| 122 |
+
GGML_ASSERT(n_tokens < (1 << 22) && "too few bits in mm_ids_helper_store");
|
| 123 |
+
GGML_ASSERT(n_expert_used_var < (1 << 10) && "too few bits in mm_ids_helper_store");
|
| 124 |
+
|
| 125 |
+
const int id = ggml_cuda_get_device();
|
| 126 |
+
const int warp_size = ggml_cuda_info().devices[id].warp_size;
|
| 127 |
+
const size_t smpbo = ggml_cuda_info().devices[id].smpbo;
|
| 128 |
+
CUDA_SET_SHARED_MEMORY_LIMIT(mm_ids_helper<n_expert_used_template>, smpbo);
|
| 129 |
+
|
| 130 |
+
const dim3 num_blocks(n_experts, 1, 1);
|
| 131 |
+
const dim3 block_size(warp_size, 1, 1);
|
| 132 |
+
const size_t nbytes_shared = n_tokens*sizeof(mm_ids_helper_store);
|
| 133 |
+
GGML_ASSERT(nbytes_shared <= smpbo);
|
| 134 |
+
mm_ids_helper<n_expert_used_template><<<num_blocks, block_size, nbytes_shared, stream>>>
|
| 135 |
+
(ids, ids_src1, ids_dst, expert_bounds, n_tokens, n_expert_used_var, nchannels_y, si1, sis1);
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
void ggml_cuda_launch_mm_ids_helper(
|
| 139 |
+
const int32_t * __restrict__ ids, int32_t * __restrict__ ids_src1, int32_t * __restrict__ ids_dst, int32_t * __restrict__ expert_bounds,
|
| 140 |
+
const int n_experts, const int n_tokens, const int n_expert_used, const int nchannels_y, const int si1, const int sis1, cudaStream_t stream) {
|
| 141 |
+
switch (n_expert_used) {
|
| 142 |
+
case 2:
|
| 143 |
+
launch_mm_ids_helper< 2>(ids, ids_src1, ids_dst, expert_bounds, n_experts, n_tokens, n_expert_used, nchannels_y, si1, sis1, stream);
|
| 144 |
+
break;
|
| 145 |
+
case 4:
|
| 146 |
+
launch_mm_ids_helper< 4>(ids, ids_src1, ids_dst, expert_bounds, n_experts, n_tokens, n_expert_used, nchannels_y, si1, sis1, stream);
|
| 147 |
+
break;
|
| 148 |
+
case 6:
|
| 149 |
+
launch_mm_ids_helper< 6>(ids, ids_src1, ids_dst, expert_bounds, n_experts, n_tokens, n_expert_used, nchannels_y, si1, sis1, stream);
|
| 150 |
+
break;
|
| 151 |
+
case 8:
|
| 152 |
+
launch_mm_ids_helper< 8>(ids, ids_src1, ids_dst, expert_bounds, n_experts, n_tokens, n_expert_used, nchannels_y, si1, sis1, stream);
|
| 153 |
+
break;
|
| 154 |
+
case 16:
|
| 155 |
+
launch_mm_ids_helper<16>(ids, ids_src1, ids_dst, expert_bounds, n_experts, n_tokens, n_expert_used, nchannels_y, si1, sis1, stream);
|
| 156 |
+
break;
|
| 157 |
+
case 32:
|
| 158 |
+
launch_mm_ids_helper<32>(ids, ids_src1, ids_dst, expert_bounds, n_experts, n_tokens, n_expert_used, nchannels_y, si1, sis1, stream);
|
| 159 |
+
break;
|
| 160 |
+
default:
|
| 161 |
+
launch_mm_ids_helper< 0>(ids, ids_src1, ids_dst, expert_bounds, n_experts, n_tokens, n_expert_used, nchannels_y, si1, sis1, stream);
|
| 162 |
+
break;
|
| 163 |
+
}
|
| 164 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/mmid.cuh
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
void ggml_cuda_launch_mm_ids_helper(
|
| 4 |
+
const int32_t * ids, int32_t * ids_src1, int32_t * ids_dst, int32_t * expert_bounds,
|
| 5 |
+
int n_experts, int n_tokens, int n_expert_used, int nchannels_y, int si1, int sis1, cudaStream_t stream);
|
backend/llama.cpp/ggml/src/ggml-cuda/mmq.cu
ADDED
|
@@ -0,0 +1,379 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
#include "mmq.cuh"
|
| 3 |
+
#include "quantize.cuh"
|
| 4 |
+
#include "mmid.cuh"
|
| 5 |
+
|
| 6 |
+
static void ggml_cuda_mul_mat_q_switch_type(ggml_backend_cuda_context & ctx, const mmq_args & args, cudaStream_t stream) {
|
| 7 |
+
switch (args.type_x) {
|
| 8 |
+
case GGML_TYPE_Q1_0:
|
| 9 |
+
mul_mat_q_case<GGML_TYPE_Q1_0>(ctx, args, stream);
|
| 10 |
+
break;
|
| 11 |
+
case GGML_TYPE_Q4_0:
|
| 12 |
+
mul_mat_q_case<GGML_TYPE_Q4_0>(ctx, args, stream);
|
| 13 |
+
break;
|
| 14 |
+
case GGML_TYPE_Q4_1:
|
| 15 |
+
mul_mat_q_case<GGML_TYPE_Q4_1>(ctx, args, stream);
|
| 16 |
+
break;
|
| 17 |
+
case GGML_TYPE_Q5_0:
|
| 18 |
+
mul_mat_q_case<GGML_TYPE_Q5_0>(ctx, args, stream);
|
| 19 |
+
break;
|
| 20 |
+
case GGML_TYPE_Q5_1:
|
| 21 |
+
mul_mat_q_case<GGML_TYPE_Q5_1>(ctx, args, stream);
|
| 22 |
+
break;
|
| 23 |
+
case GGML_TYPE_Q8_0:
|
| 24 |
+
mul_mat_q_case<GGML_TYPE_Q8_0>(ctx, args, stream);
|
| 25 |
+
break;
|
| 26 |
+
case GGML_TYPE_MXFP4:
|
| 27 |
+
mul_mat_q_case<GGML_TYPE_MXFP4>(ctx, args, stream);
|
| 28 |
+
break;
|
| 29 |
+
case GGML_TYPE_NVFP4:
|
| 30 |
+
mul_mat_q_case<GGML_TYPE_NVFP4>(ctx, args, stream);
|
| 31 |
+
break;
|
| 32 |
+
case GGML_TYPE_Q2_K:
|
| 33 |
+
mul_mat_q_case<GGML_TYPE_Q2_K>(ctx, args, stream);
|
| 34 |
+
break;
|
| 35 |
+
case GGML_TYPE_Q3_K:
|
| 36 |
+
mul_mat_q_case<GGML_TYPE_Q3_K>(ctx, args, stream);
|
| 37 |
+
break;
|
| 38 |
+
case GGML_TYPE_Q4_K:
|
| 39 |
+
mul_mat_q_case<GGML_TYPE_Q4_K>(ctx, args, stream);
|
| 40 |
+
break;
|
| 41 |
+
case GGML_TYPE_Q5_K:
|
| 42 |
+
mul_mat_q_case<GGML_TYPE_Q5_K>(ctx, args, stream);
|
| 43 |
+
break;
|
| 44 |
+
case GGML_TYPE_Q6_K:
|
| 45 |
+
mul_mat_q_case<GGML_TYPE_Q6_K>(ctx, args, stream);
|
| 46 |
+
break;
|
| 47 |
+
case GGML_TYPE_IQ2_XXS:
|
| 48 |
+
mul_mat_q_case<GGML_TYPE_IQ2_XXS>(ctx, args, stream);
|
| 49 |
+
break;
|
| 50 |
+
case GGML_TYPE_IQ2_XS:
|
| 51 |
+
mul_mat_q_case<GGML_TYPE_IQ2_XS>(ctx, args, stream);
|
| 52 |
+
break;
|
| 53 |
+
case GGML_TYPE_IQ2_S:
|
| 54 |
+
mul_mat_q_case<GGML_TYPE_IQ2_S>(ctx, args, stream);
|
| 55 |
+
break;
|
| 56 |
+
case GGML_TYPE_IQ3_XXS:
|
| 57 |
+
mul_mat_q_case<GGML_TYPE_IQ3_XXS>(ctx, args, stream);
|
| 58 |
+
break;
|
| 59 |
+
case GGML_TYPE_IQ3_S:
|
| 60 |
+
mul_mat_q_case<GGML_TYPE_IQ3_S>(ctx, args, stream);
|
| 61 |
+
break;
|
| 62 |
+
case GGML_TYPE_IQ1_S:
|
| 63 |
+
mul_mat_q_case<GGML_TYPE_IQ1_S>(ctx, args, stream);
|
| 64 |
+
break;
|
| 65 |
+
case GGML_TYPE_IQ4_XS:
|
| 66 |
+
mul_mat_q_case<GGML_TYPE_IQ4_XS>(ctx, args, stream);
|
| 67 |
+
break;
|
| 68 |
+
case GGML_TYPE_IQ4_NL:
|
| 69 |
+
mul_mat_q_case<GGML_TYPE_IQ4_NL>(ctx, args, stream);
|
| 70 |
+
break;
|
| 71 |
+
default:
|
| 72 |
+
GGML_ABORT("fatal error");
|
| 73 |
+
break;
|
| 74 |
+
}
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
void ggml_cuda_mul_mat_q(
|
| 78 |
+
ggml_backend_cuda_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * ids, ggml_tensor * dst) {
|
| 79 |
+
GGML_ASSERT( src1->type == GGML_TYPE_F32);
|
| 80 |
+
GGML_ASSERT( dst->type == GGML_TYPE_F32);
|
| 81 |
+
GGML_ASSERT(!ids || ids->type == GGML_TYPE_I32); // Optional, used for batched GGML_MUL_MAT_ID.
|
| 82 |
+
|
| 83 |
+
GGML_TENSOR_BINARY_OP_LOCALS;
|
| 84 |
+
|
| 85 |
+
cudaStream_t stream = ctx.stream();
|
| 86 |
+
const int cc = ggml_cuda_info().devices[ggml_cuda_get_device()].cc;
|
| 87 |
+
|
| 88 |
+
const size_t ts_src0 = ggml_type_size(src0->type);
|
| 89 |
+
const size_t ts_src1 = ggml_type_size(src1->type);
|
| 90 |
+
const size_t ts_dst = ggml_type_size(dst->type);
|
| 91 |
+
|
| 92 |
+
GGML_ASSERT( nb00 == ts_src0);
|
| 93 |
+
GGML_ASSERT( nb10 == ts_src1);
|
| 94 |
+
GGML_ASSERT( nb0 == ts_dst);
|
| 95 |
+
GGML_ASSERT(!ids || ids->nb[0] == ggml_type_size(ids->type));
|
| 96 |
+
|
| 97 |
+
const char * src0_d = (const char *) src0->data;
|
| 98 |
+
const float * src1_d = (const float *) src1->data;
|
| 99 |
+
float * dst_d = (float *) dst->data;
|
| 100 |
+
|
| 101 |
+
// If src0 is a temporary compute buffer, clear any potential padding.
|
| 102 |
+
if (ggml_backend_buffer_get_usage(src0->buffer) == GGML_BACKEND_BUFFER_USAGE_COMPUTE) {
|
| 103 |
+
const size_t size_data = ggml_nbytes(src0);
|
| 104 |
+
const size_t size_alloc = ggml_backend_buffer_get_alloc_size(src0->buffer, src0);
|
| 105 |
+
if (size_alloc > size_data) {
|
| 106 |
+
GGML_ASSERT(ggml_is_contiguously_allocated(src0));
|
| 107 |
+
GGML_ASSERT(!src0->view_src);
|
| 108 |
+
CUDA_CHECK(cudaMemsetAsync((char *) src0->data + size_data, 0, size_alloc - size_data, stream));
|
| 109 |
+
}
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
const int64_t ne10_padded = GGML_PAD(ne10, MATRIX_ROW_PADDING);
|
| 113 |
+
|
| 114 |
+
const int64_t s01 = src0->nb[1] / ts_src0;
|
| 115 |
+
const int64_t s1 = dst->nb[1] / ts_dst;
|
| 116 |
+
const int64_t s02 = src0->nb[2] / ts_src0;
|
| 117 |
+
const int64_t s2 = dst->nb[2] / ts_dst;
|
| 118 |
+
const int64_t s03 = src0->nb[3] / ts_src0;
|
| 119 |
+
const int64_t s3 = dst->nb[3] / ts_dst;
|
| 120 |
+
|
| 121 |
+
const bool use_stream_k = (GGML_CUDA_CC_IS_NVIDIA(cc) && ggml_cuda_highest_compiled_arch(cc) >= GGML_CUDA_CC_VOLTA)
|
| 122 |
+
|| GGML_CUDA_CC_IS_CDNA(cc);
|
| 123 |
+
|
| 124 |
+
// TODO: tighter pool buffer size vs q8 path
|
| 125 |
+
const bool use_native_fp4 = blackwell_mma_available(cc) && (src0->type == GGML_TYPE_MXFP4 || src0->type == GGML_TYPE_NVFP4);
|
| 126 |
+
|
| 127 |
+
if (!ids) {
|
| 128 |
+
const size_t nbytes_src1_q8_1 = ne13*ne12 * ne11*ne10_padded * sizeof(block_q8_1)/QK8_1 +
|
| 129 |
+
get_mmq_x_max_host(cc)*sizeof(block_q8_1_mmq);
|
| 130 |
+
ggml_cuda_pool_alloc<char> src1_q8_1(ctx.pool(), nbytes_src1_q8_1);
|
| 131 |
+
|
| 132 |
+
{
|
| 133 |
+
const int64_t s11 = src1->nb[1] / ts_src1;
|
| 134 |
+
const int64_t s12 = src1->nb[2] / ts_src1;
|
| 135 |
+
const int64_t s13 = src1->nb[3] / ts_src1;
|
| 136 |
+
if (use_native_fp4) {
|
| 137 |
+
static_assert(sizeof(block_fp4_mmq) == 4 * sizeof(block_q8_1));
|
| 138 |
+
quantize_mmq_fp4_cuda(src1_d, nullptr, src1_q8_1.get(), src0->type, ne10, s11, s12, s13, ne10_padded,
|
| 139 |
+
ne11, ne12, ne13, stream);
|
| 140 |
+
|
| 141 |
+
} else {
|
| 142 |
+
quantize_mmq_q8_1_cuda(src1_d, nullptr, src1_q8_1.get(), src0->type, ne10, s11, s12, s13, ne10_padded,
|
| 143 |
+
ne11, ne12, ne13, stream);
|
| 144 |
+
}
|
| 145 |
+
CUDA_CHECK(cudaGetLastError());
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
// Stride depends on quantization format
|
| 149 |
+
const int64_t s12 = use_native_fp4 ?
|
| 150 |
+
ne11 * ne10_padded * sizeof(block_fp4_mmq) / (QK_K * sizeof(int)) : // block_fp4_mmq holds 256 values
|
| 151 |
+
ne11 * ne10_padded * sizeof(block_q8_1) / (QK8_1 * sizeof(int));
|
| 152 |
+
const int64_t s13 = ne12*s12;
|
| 153 |
+
|
| 154 |
+
const mmq_args args = {
|
| 155 |
+
src0_d, src0->type, (const int *) src1_q8_1.ptr, nullptr, nullptr, dst_d,
|
| 156 |
+
ne00, ne01, ne1, s01, ne11, s1,
|
| 157 |
+
ne02, ne12, s02, s12, s2,
|
| 158 |
+
ne03, ne13, s03, s13, s3,
|
| 159 |
+
use_stream_k, ne1};
|
| 160 |
+
ggml_cuda_mul_mat_q_switch_type(ctx, args, stream);
|
| 161 |
+
return;
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
GGML_ASSERT(ne13 == 1);
|
| 165 |
+
GGML_ASSERT(nb12 % nb11 == 0);
|
| 166 |
+
GGML_ASSERT(nb2 % nb1 == 0);
|
| 167 |
+
|
| 168 |
+
const int64_t n_expert_used = ids->ne[0];
|
| 169 |
+
const int64_t ne_get_rows = ne12 * n_expert_used;
|
| 170 |
+
GGML_ASSERT(ne1 == n_expert_used);
|
| 171 |
+
|
| 172 |
+
ggml_cuda_pool_alloc<int32_t> ids_src1(ctx.pool(), ne_get_rows);
|
| 173 |
+
ggml_cuda_pool_alloc<int32_t> ids_dst(ctx.pool(), ne_get_rows);
|
| 174 |
+
ggml_cuda_pool_alloc<int32_t> expert_bounds(ctx.pool(), ne02 + 1);
|
| 175 |
+
|
| 176 |
+
{
|
| 177 |
+
GGML_ASSERT(ids->nb[0] == ggml_element_size(ids));
|
| 178 |
+
const int si1 = ids->nb[1] / ggml_element_size(ids);
|
| 179 |
+
const int sis1 = nb12 / nb11;
|
| 180 |
+
|
| 181 |
+
ggml_cuda_launch_mm_ids_helper((const int32_t *) ids->data, ids_src1.get(), ids_dst.get(), expert_bounds.get(),
|
| 182 |
+
ne02, ne12, n_expert_used, ne11, si1, sis1, stream);
|
| 183 |
+
CUDA_CHECK(cudaGetLastError());
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
const size_t nbytes_src1_q8_1 = ne12*n_expert_used*ne10_padded * sizeof(block_q8_1)/QK8_1 +
|
| 187 |
+
get_mmq_x_max_host(cc)*sizeof(block_q8_1_mmq);
|
| 188 |
+
ggml_cuda_pool_alloc<char> src1_q8_1(ctx.pool(), nbytes_src1_q8_1);
|
| 189 |
+
|
| 190 |
+
const int64_t ne11_flat = ne12*n_expert_used;
|
| 191 |
+
const int64_t ne12_flat = 1;
|
| 192 |
+
const int64_t ne13_flat = 1;
|
| 193 |
+
|
| 194 |
+
{
|
| 195 |
+
const int64_t s11 = src1->nb[1] / ts_src1;
|
| 196 |
+
const int64_t s12 = src1->nb[2] / ts_src1;
|
| 197 |
+
const int64_t s13 = src1->nb[3] / ts_src1;
|
| 198 |
+
|
| 199 |
+
if (use_native_fp4) {
|
| 200 |
+
quantize_mmq_fp4_cuda(src1_d, ids_src1.get(), src1_q8_1.get(), src0->type, ne10, s11, s12, s13,
|
| 201 |
+
ne10_padded, ne11_flat, ne12_flat, ne13_flat, stream);
|
| 202 |
+
} else {
|
| 203 |
+
quantize_mmq_q8_1_cuda(src1_d, ids_src1.get(), src1_q8_1.get(), src0->type, ne10, s11, s12, s13,
|
| 204 |
+
ne10_padded, ne11_flat, ne12_flat, ne13_flat, stream);
|
| 205 |
+
}
|
| 206 |
+
CUDA_CHECK(cudaGetLastError());
|
| 207 |
+
}
|
| 208 |
+
|
| 209 |
+
static_assert(QK_K == 8 * QK_MXFP4, "QK_K needs to be 8 * QK_MXFP4");
|
| 210 |
+
const int64_t s12 = use_native_fp4 ? ne11 * ne10_padded * sizeof(block_fp4_mmq) / (QK_K * sizeof(int)) :
|
| 211 |
+
ne11 * ne10_padded * sizeof(block_q8_1) / (QK8_1 * sizeof(int));
|
| 212 |
+
const int64_t s13 = ne12*s12;
|
| 213 |
+
|
| 214 |
+
// Note that ne02 is used instead of ne12 because the number of y channels determines the z dimension of the CUDA grid.
|
| 215 |
+
const mmq_args args = {
|
| 216 |
+
src0_d, src0->type, (const int *) src1_q8_1.get(), ids_dst.get(), expert_bounds.get(), dst_d,
|
| 217 |
+
ne00, ne01, ne_get_rows, s01, ne_get_rows, s1,
|
| 218 |
+
ne02, ne02, s02, s12, s2,
|
| 219 |
+
ne03, ne13, s03, s13, s3,
|
| 220 |
+
use_stream_k, ne12};
|
| 221 |
+
|
| 222 |
+
ggml_cuda_mul_mat_q_switch_type(ctx, args, stream);
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
void ggml_cuda_op_mul_mat_q(
|
| 226 |
+
ggml_backend_cuda_context & ctx,
|
| 227 |
+
const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, const char * src0_dd_i, const float * src1_ddf_i,
|
| 228 |
+
const char * src1_ddq_i, float * dst_dd_i, const int64_t row_low, const int64_t row_high, const int64_t src1_ncols,
|
| 229 |
+
const int64_t src1_padded_row_size, cudaStream_t stream) {
|
| 230 |
+
|
| 231 |
+
const int64_t ne00 = src0->ne[0];
|
| 232 |
+
|
| 233 |
+
const int64_t ne10 = src1->ne[0];
|
| 234 |
+
const int64_t ne11 = src1->ne[1];
|
| 235 |
+
GGML_ASSERT(ne10 % QK8_1 == 0);
|
| 236 |
+
|
| 237 |
+
const int64_t ne0 = dst->ne[0];
|
| 238 |
+
|
| 239 |
+
const int64_t row_diff = row_high - row_low;
|
| 240 |
+
const int64_t stride01 = ne00 / ggml_blck_size(src0->type);
|
| 241 |
+
|
| 242 |
+
const int id = ggml_cuda_get_device();
|
| 243 |
+
const int cc = ggml_cuda_info().devices[id].cc;
|
| 244 |
+
|
| 245 |
+
// the main device has a larger memory buffer to hold the results from all GPUs
|
| 246 |
+
// nrows_dst == nrows of the matrix that the kernel writes into
|
| 247 |
+
const int64_t nrows_dst = id == ctx.device ? ne0 : row_diff;
|
| 248 |
+
|
| 249 |
+
// The stream-k decomposition is only faster for recent NVIDIA GPUs.
|
| 250 |
+
// Also its fixup needs to allocate a temporary buffer in the memory pool.
|
| 251 |
+
// There are multiple parallel CUDA streams for src1_ncols != ne11 which would introduce a race condition for this buffer.
|
| 252 |
+
const bool use_stream_k = ((GGML_CUDA_CC_IS_NVIDIA(cc) && ggml_cuda_highest_compiled_arch(cc) >= GGML_CUDA_CC_VOLTA)
|
| 253 |
+
|| GGML_CUDA_CC_IS_CDNA(cc))
|
| 254 |
+
&& src1_ncols == ne11;
|
| 255 |
+
const mmq_args args = {
|
| 256 |
+
src0_dd_i, src0->type, (const int *) src1_ddq_i, nullptr, nullptr, dst_dd_i,
|
| 257 |
+
ne00, row_diff, src1_ncols, stride01, ne11, nrows_dst,
|
| 258 |
+
1, 1, 0, 0, 0,
|
| 259 |
+
1, 1, 0, 0, 0,
|
| 260 |
+
use_stream_k, src1_ncols};
|
| 261 |
+
|
| 262 |
+
ggml_cuda_mul_mat_q_switch_type(ctx, args, stream);
|
| 263 |
+
|
| 264 |
+
GGML_UNUSED_VARS(src1, dst, src1_ddf_i, src1_padded_row_size);
|
| 265 |
+
}
|
| 266 |
+
|
| 267 |
+
bool ggml_cuda_should_use_mmq(enum ggml_type type, int cc, int64_t ne11, int64_t n_experts) {
|
| 268 |
+
#ifdef GGML_CUDA_FORCE_CUBLAS
|
| 269 |
+
return false;
|
| 270 |
+
#endif // GGML_CUDA_FORCE_CUBLAS
|
| 271 |
+
|
| 272 |
+
bool mmq_supported;
|
| 273 |
+
|
| 274 |
+
switch (type) {
|
| 275 |
+
case GGML_TYPE_Q1_0:
|
| 276 |
+
case GGML_TYPE_Q4_0:
|
| 277 |
+
case GGML_TYPE_Q4_1:
|
| 278 |
+
case GGML_TYPE_Q5_0:
|
| 279 |
+
case GGML_TYPE_Q5_1:
|
| 280 |
+
case GGML_TYPE_Q8_0:
|
| 281 |
+
case GGML_TYPE_MXFP4:
|
| 282 |
+
case GGML_TYPE_NVFP4:
|
| 283 |
+
case GGML_TYPE_Q2_K:
|
| 284 |
+
case GGML_TYPE_Q3_K:
|
| 285 |
+
case GGML_TYPE_Q4_K:
|
| 286 |
+
case GGML_TYPE_Q5_K:
|
| 287 |
+
case GGML_TYPE_Q6_K:
|
| 288 |
+
case GGML_TYPE_IQ2_XXS:
|
| 289 |
+
case GGML_TYPE_IQ2_XS:
|
| 290 |
+
case GGML_TYPE_IQ2_S:
|
| 291 |
+
case GGML_TYPE_IQ3_XXS:
|
| 292 |
+
case GGML_TYPE_IQ3_S:
|
| 293 |
+
case GGML_TYPE_IQ1_S:
|
| 294 |
+
case GGML_TYPE_IQ4_XS:
|
| 295 |
+
case GGML_TYPE_IQ4_NL:
|
| 296 |
+
mmq_supported = true;
|
| 297 |
+
break;
|
| 298 |
+
default:
|
| 299 |
+
mmq_supported = false;
|
| 300 |
+
break;
|
| 301 |
+
}
|
| 302 |
+
|
| 303 |
+
if (!mmq_supported) {
|
| 304 |
+
return false;
|
| 305 |
+
}
|
| 306 |
+
|
| 307 |
+
if (turing_mma_available(cc)) {
|
| 308 |
+
return true;
|
| 309 |
+
}
|
| 310 |
+
|
| 311 |
+
if (ggml_cuda_highest_compiled_arch(cc) < GGML_CUDA_CC_DP4A) {
|
| 312 |
+
return false;
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
#ifdef GGML_CUDA_FORCE_MMQ
|
| 316 |
+
return true;
|
| 317 |
+
#endif //GGML_CUDA_FORCE_MMQ
|
| 318 |
+
|
| 319 |
+
if (GGML_CUDA_CC_IS_NVIDIA(cc)) {
|
| 320 |
+
return !fp16_mma_hardware_available(cc) || ne11 < MMQ_DP4A_MAX_BATCH_SIZE;
|
| 321 |
+
}
|
| 322 |
+
|
| 323 |
+
if (amd_mfma_available(cc)) {
|
| 324 |
+
// As of ROCM 7.0 rocblas/tensile performs very poorly on CDNA3 and hipblaslt (via ROCBLAS_USE_HIPBLASLT)
|
| 325 |
+
// performs better but is currently suffering from a crash on this architecture.
|
| 326 |
+
// TODO: Revisit when hipblaslt is fixed on CDNA3
|
| 327 |
+
if (GGML_CUDA_CC_IS_CDNA3(cc)) {
|
| 328 |
+
return true;
|
| 329 |
+
}
|
| 330 |
+
if (n_experts > 64 || ne11 <= 128) {
|
| 331 |
+
return true;
|
| 332 |
+
}
|
| 333 |
+
if (type == GGML_TYPE_Q4_0 || type == GGML_TYPE_Q4_1 || type == GGML_TYPE_Q5_0 || type == GGML_TYPE_Q5_1) {
|
| 334 |
+
return true;
|
| 335 |
+
}
|
| 336 |
+
if (ne11 <= 256 && (type == GGML_TYPE_Q4_K || type == GGML_TYPE_Q5_K)) {
|
| 337 |
+
return true;
|
| 338 |
+
}
|
| 339 |
+
return false;
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
if (amd_wmma_available(cc)) {
|
| 343 |
+
if (GGML_CUDA_CC_IS_RDNA3(cc)) {
|
| 344 |
+
// High expert counts are almost always better on MMQ due to
|
| 345 |
+
// the synchronization overhead in the cuBLAS/hipBLAS path:
|
| 346 |
+
// https://github.com/ggml-org/llama.cpp/pull/18202
|
| 347 |
+
if (n_experts >= 64) {
|
| 348 |
+
return true;
|
| 349 |
+
}
|
| 350 |
+
|
| 351 |
+
// For some quantization types MMQ can have lower peak TOPS than hipBLAS
|
| 352 |
+
// so it's only faster for sufficiently small batch sizes:
|
| 353 |
+
switch (type) {
|
| 354 |
+
case GGML_TYPE_Q2_K:
|
| 355 |
+
return ne11 <= 128;
|
| 356 |
+
case GGML_TYPE_Q6_K:
|
| 357 |
+
return ne11 <= (GGML_CUDA_CC_IS_RDNA3_0(cc) ? 128 : 256);
|
| 358 |
+
case GGML_TYPE_IQ2_XS:
|
| 359 |
+
case GGML_TYPE_IQ2_S:
|
| 360 |
+
return GGML_CUDA_CC_IS_RDNA3_5(cc) || ne11 <= 128;
|
| 361 |
+
default:
|
| 362 |
+
return true;
|
| 363 |
+
}
|
| 364 |
+
}
|
| 365 |
+
|
| 366 |
+
// For RDNA4 MMQ is consistently faster than dequantization + hipBLAS:
|
| 367 |
+
// https://github.com/ggml-org/llama.cpp/pull/18537#issuecomment-3706422301
|
| 368 |
+
return true;
|
| 369 |
+
}
|
| 370 |
+
|
| 371 |
+
// gfx900 (Vega 10) lacks native dp4a, loses to dequant + hipBLAS
|
| 372 |
+
// for dense matrices; keep MMQ only for MoE, where the
|
| 373 |
+
// hipBLAS path is much slower.
|
| 374 |
+
if (cc == GGML_CUDA_CC_VEGA) {
|
| 375 |
+
return n_experts > 0;
|
| 376 |
+
}
|
| 377 |
+
|
| 378 |
+
return (!GGML_CUDA_CC_IS_CDNA(cc)) || ne11 < MMQ_DP4A_MAX_BATCH_SIZE;
|
| 379 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/mmq.cuh
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
backend/llama.cpp/ggml/src/ggml-cuda/mmvf.cu
ADDED
|
@@ -0,0 +1,869 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "ggml.h"
|
| 2 |
+
#include "common.cuh"
|
| 3 |
+
#include "unary.cuh"
|
| 4 |
+
#include "mmvf.cuh"
|
| 5 |
+
#include "convert.cuh"
|
| 6 |
+
|
| 7 |
+
template <typename T, typename type_acc, int ncols_dst, int block_size, bool has_fusion = false, bool is_multi_token_id = false>
|
| 8 |
+
static __global__ void mul_mat_vec_f(
|
| 9 |
+
const T * x_ptr, const float * y_ptr, const int32_t * ids_ptr, const ggml_cuda_mm_fusion_args_device fusion, float * dst_ptr,
|
| 10 |
+
const int ncols2, const uint3 nchannels_y, const int stride_row, const int stride_col_y2, const int stride_col_dst,
|
| 11 |
+
const uint3 channel_ratio, const int stride_channel_x, const int stride_channel_y, const int stride_channel_dst,
|
| 12 |
+
const uint3 sample_ratio, const int stride_sample_x, const int stride_sample_y, const int stride_sample_dst,
|
| 13 |
+
const int ids_stride) {
|
| 14 |
+
const T * GGML_CUDA_RESTRICT x = x_ptr;
|
| 15 |
+
const float * GGML_CUDA_RESTRICT y = y_ptr;
|
| 16 |
+
const int32_t * GGML_CUDA_RESTRICT ids = ids_ptr;
|
| 17 |
+
float * GGML_CUDA_RESTRICT dst = dst_ptr;
|
| 18 |
+
const int row = blockIdx.x;
|
| 19 |
+
// for MUL_MAT_ID - blockIdx.y = n_expert_used, blockIdx.z = ncols_dst (tokens)
|
| 20 |
+
const int channel_dst = blockIdx.y;
|
| 21 |
+
const int tid = threadIdx.x;
|
| 22 |
+
|
| 23 |
+
int token_idx;
|
| 24 |
+
int channel_x;
|
| 25 |
+
int channel_y;
|
| 26 |
+
int sample_dst;
|
| 27 |
+
|
| 28 |
+
ggml_cuda_pdl_sync();
|
| 29 |
+
if constexpr (is_multi_token_id) {
|
| 30 |
+
// Multi-token MUL_MAT_ID path, adding these in the normal path causes a perf regression for n_tokens=1 case
|
| 31 |
+
token_idx = blockIdx.z;
|
| 32 |
+
channel_x = ids[channel_dst + token_idx * ids_stride];
|
| 33 |
+
channel_y = fastmodulo(channel_dst, nchannels_y);
|
| 34 |
+
sample_dst = 0;
|
| 35 |
+
} else {
|
| 36 |
+
token_idx = ids ? blockIdx.z : 0;
|
| 37 |
+
channel_x = ids ? ids[blockIdx.y + token_idx * ids_stride] : fastdiv((uint32_t) channel_dst, channel_ratio);
|
| 38 |
+
channel_y = ids ? fastmodulo(blockIdx.y, nchannels_y) : channel_dst;
|
| 39 |
+
sample_dst = ids ? 0 : blockIdx.z;
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
const int sample_x = fastdiv((uint32_t) sample_dst, sample_ratio);
|
| 43 |
+
const int sample_y = sample_dst;
|
| 44 |
+
|
| 45 |
+
constexpr int warp_size = ggml_cuda_get_physical_warp_size();
|
| 46 |
+
|
| 47 |
+
x += int64_t(sample_x) *stride_sample_x + channel_x *stride_channel_x + row*stride_row;
|
| 48 |
+
y += int64_t(sample_y) *stride_sample_y + channel_y *stride_channel_y;
|
| 49 |
+
dst += int64_t(sample_dst)*stride_sample_dst + channel_dst*stride_channel_dst;
|
| 50 |
+
if constexpr (is_multi_token_id) {
|
| 51 |
+
y += token_idx*stride_col_y2*2;
|
| 52 |
+
dst += token_idx*stride_col_dst;
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
bool use_gate = false;
|
| 56 |
+
bool use_bias = false;
|
| 57 |
+
bool use_gate_bias = false;
|
| 58 |
+
ggml_glu_op glu_op = ggml_glu_op::GGML_GLU_OP_SWIGLU;
|
| 59 |
+
const T * gate_x = nullptr;
|
| 60 |
+
const float * x_bias = nullptr;
|
| 61 |
+
const float * gate_bias = nullptr;
|
| 62 |
+
|
| 63 |
+
if constexpr (has_fusion) {
|
| 64 |
+
use_gate = fusion.gate != nullptr;
|
| 65 |
+
use_bias = fusion.x_bias != nullptr;
|
| 66 |
+
use_gate_bias = fusion.gate_bias != nullptr;
|
| 67 |
+
glu_op = fusion.glu_op;
|
| 68 |
+
|
| 69 |
+
if (use_gate) {
|
| 70 |
+
gate_x = static_cast<const T *>(fusion.gate);
|
| 71 |
+
}
|
| 72 |
+
if (use_bias) {
|
| 73 |
+
x_bias = static_cast<const float *>(fusion.x_bias);
|
| 74 |
+
}
|
| 75 |
+
if (use_gate_bias) {
|
| 76 |
+
gate_bias = static_cast<const float *>(fusion.gate_bias);
|
| 77 |
+
use_gate_bias = use_gate;
|
| 78 |
+
} else {
|
| 79 |
+
use_gate_bias = false;
|
| 80 |
+
}
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
if (use_gate) {
|
| 84 |
+
gate_x += int64_t(sample_x) *stride_sample_x + channel_x *stride_channel_x + row*stride_row;
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
if constexpr (has_fusion) {
|
| 88 |
+
const int channel_bias = ids ? channel_x : channel_dst;
|
| 89 |
+
if (use_bias) {
|
| 90 |
+
x_bias += int64_t(sample_dst)*stride_sample_dst + channel_bias*stride_channel_dst;
|
| 91 |
+
}
|
| 92 |
+
if (use_gate_bias) {
|
| 93 |
+
gate_bias += int64_t(sample_dst)*stride_sample_dst + channel_bias*stride_channel_dst;
|
| 94 |
+
}
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
const float2 * y2 = (const float2 *) y;
|
| 98 |
+
|
| 99 |
+
extern __shared__ char data_mmv[];
|
| 100 |
+
float * buf_iw = (float *) data_mmv;
|
| 101 |
+
[[maybe_unused]] float * buf_iw_gate = nullptr;
|
| 102 |
+
if constexpr (has_fusion) {
|
| 103 |
+
buf_iw_gate = (float *) (data_mmv + warp_size*sizeof(float));
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
if (block_size > warp_size) {
|
| 107 |
+
if (tid < warp_size) {
|
| 108 |
+
buf_iw[tid] = 0.0f;
|
| 109 |
+
if constexpr (has_fusion) {
|
| 110 |
+
if (use_gate) {
|
| 111 |
+
buf_iw_gate[tid] = 0.0f;
|
| 112 |
+
}
|
| 113 |
+
}
|
| 114 |
+
}
|
| 115 |
+
__syncthreads();
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
float sumf[ncols_dst] = {0.0f};
|
| 119 |
+
float sumf_gate[ncols_dst];
|
| 120 |
+
if constexpr (has_fusion) {
|
| 121 |
+
#pragma unroll
|
| 122 |
+
for (int j = 0; j < ncols_dst; ++j) {
|
| 123 |
+
sumf_gate[j] = 0.0f;
|
| 124 |
+
}
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
if constexpr (std::is_same_v<T, float>) {
|
| 128 |
+
const float2 * x2 = (const float2 *) x;
|
| 129 |
+
[[maybe_unused]] const float2 * gate_x2 = nullptr;
|
| 130 |
+
if constexpr (has_fusion) {
|
| 131 |
+
if (use_gate) {
|
| 132 |
+
gate_x2 = (const float2 *) gate_x;
|
| 133 |
+
}
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
for (int col2 = tid; col2 < ncols2; col2 += block_size) {
|
| 137 |
+
const float2 tmpx = x2[col2];
|
| 138 |
+
float2 tmpx_gate = make_float2(0.0f, 0.0f);
|
| 139 |
+
if constexpr (has_fusion) {
|
| 140 |
+
if (use_gate) {
|
| 141 |
+
tmpx_gate = gate_x2[col2];
|
| 142 |
+
}
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
#pragma unroll
|
| 146 |
+
for (int j = 0; j < ncols_dst; ++j) {
|
| 147 |
+
const float2 tmpy = y2[j*stride_col_y2 + col2];
|
| 148 |
+
ggml_cuda_mad(sumf[j], tmpx.x, tmpy.x);
|
| 149 |
+
ggml_cuda_mad(sumf[j], tmpx.y, tmpy.y);
|
| 150 |
+
|
| 151 |
+
if constexpr (has_fusion) {
|
| 152 |
+
if (use_gate) {
|
| 153 |
+
ggml_cuda_mad(sumf_gate[j], tmpx_gate.x, tmpy.x);
|
| 154 |
+
ggml_cuda_mad(sumf_gate[j], tmpx_gate.y, tmpy.y);
|
| 155 |
+
}
|
| 156 |
+
}
|
| 157 |
+
}
|
| 158 |
+
}
|
| 159 |
+
} else if constexpr (std::is_same_v<T, half>) {
|
| 160 |
+
const half2 * x2 = (const half2 *) x;
|
| 161 |
+
[[maybe_unused]] const half2 * gate_x2 = nullptr;
|
| 162 |
+
if constexpr (has_fusion) {
|
| 163 |
+
if (use_gate) {
|
| 164 |
+
gate_x2 = (const half2 *) gate_x;
|
| 165 |
+
}
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
if (std::is_same_v<type_acc, float>) {
|
| 169 |
+
for (int col2 = tid; col2 < ncols2; col2 += block_size) {
|
| 170 |
+
const float2 tmpx = __half22float2(x2[col2]);
|
| 171 |
+
float2 tmpx_gate = make_float2(0.0f, 0.0f);
|
| 172 |
+
if constexpr (has_fusion) {
|
| 173 |
+
if (use_gate) {
|
| 174 |
+
tmpx_gate = __half22float2(gate_x2[col2]);
|
| 175 |
+
}
|
| 176 |
+
}
|
| 177 |
+
#pragma unroll
|
| 178 |
+
for (int j = 0; j < ncols_dst; ++j) {
|
| 179 |
+
const float2 tmpy = y2[j*stride_col_y2 + col2];
|
| 180 |
+
ggml_cuda_mad(sumf[j], tmpx.x, tmpy.x);
|
| 181 |
+
ggml_cuda_mad(sumf[j], tmpx.y, tmpy.y);
|
| 182 |
+
|
| 183 |
+
if constexpr (has_fusion) {
|
| 184 |
+
if (use_gate) {
|
| 185 |
+
ggml_cuda_mad(sumf_gate[j], tmpx_gate.x, tmpy.x);
|
| 186 |
+
ggml_cuda_mad(sumf_gate[j], tmpx_gate.y, tmpy.y);
|
| 187 |
+
}
|
| 188 |
+
}
|
| 189 |
+
}
|
| 190 |
+
}
|
| 191 |
+
} else {
|
| 192 |
+
#ifdef FP16_AVAILABLE
|
| 193 |
+
half2 sumh2[ncols_dst] = {{0.0f, 0.0f}};
|
| 194 |
+
half2 sumh2_gate[ncols_dst] = {{0.0f, 0.0f}};
|
| 195 |
+
|
| 196 |
+
for (int col2 = tid; col2 < ncols2; col2 += block_size) {
|
| 197 |
+
const half2 tmpx = x2[col2];
|
| 198 |
+
half2 tmpx_gate = make_half2(0.0f, 0.0f);
|
| 199 |
+
if constexpr (has_fusion) {
|
| 200 |
+
if (use_gate) {
|
| 201 |
+
tmpx_gate = gate_x2[col2];
|
| 202 |
+
}
|
| 203 |
+
}
|
| 204 |
+
#pragma unroll
|
| 205 |
+
for (int j = 0; j < ncols_dst; ++j) {
|
| 206 |
+
const float2 tmpy = y2[j*stride_col_y2 + col2];
|
| 207 |
+
sumh2[j] += tmpx * make_half2(tmpy.x, tmpy.y);
|
| 208 |
+
|
| 209 |
+
if constexpr (has_fusion) {
|
| 210 |
+
if (use_gate) {
|
| 211 |
+
sumh2_gate[j] += tmpx_gate * make_half2(tmpy.x, tmpy.y);
|
| 212 |
+
}
|
| 213 |
+
}
|
| 214 |
+
}
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
#pragma unroll
|
| 218 |
+
for (int j = 0; j < ncols_dst; ++j) {
|
| 219 |
+
sumf[j] = __low2float(sumh2[j]) + __high2float(sumh2[j]);
|
| 220 |
+
}
|
| 221 |
+
|
| 222 |
+
if constexpr (has_fusion) {
|
| 223 |
+
if (use_gate) {
|
| 224 |
+
#pragma unroll
|
| 225 |
+
for (int j = 0; j < ncols_dst; ++j) {
|
| 226 |
+
sumf_gate[j] = __low2float(sumh2_gate[j]) + __high2float(sumh2_gate[j]);
|
| 227 |
+
}
|
| 228 |
+
}
|
| 229 |
+
}
|
| 230 |
+
#else
|
| 231 |
+
NO_DEVICE_CODE;
|
| 232 |
+
#endif // FP16_AVAILABLE
|
| 233 |
+
}
|
| 234 |
+
} else if constexpr (std::is_same_v<T, nv_bfloat16>) {
|
| 235 |
+
//TODO: add support for ggml_cuda_mad for hip_bfloat162
|
| 236 |
+
#if defined(GGML_USE_HIP)
|
| 237 |
+
const int * x2 = (const int *) x;
|
| 238 |
+
const int * gate_x2 = nullptr;
|
| 239 |
+
if constexpr (has_fusion) {
|
| 240 |
+
if (use_gate) {
|
| 241 |
+
gate_x2 = (const int *) gate_x;
|
| 242 |
+
}
|
| 243 |
+
}
|
| 244 |
+
for (int col2 = tid; col2 < ncols2; col2 += block_size) {
|
| 245 |
+
const int tmpx = x2[col2];
|
| 246 |
+
int tmpx_gate = 0;
|
| 247 |
+
if constexpr (has_fusion) {
|
| 248 |
+
if (use_gate) {
|
| 249 |
+
tmpx_gate = gate_x2[col2];
|
| 250 |
+
}
|
| 251 |
+
}
|
| 252 |
+
#pragma unroll
|
| 253 |
+
for (int j = 0; j < ncols_dst; ++j) {
|
| 254 |
+
const float2 tmpy = y2[j*stride_col_y2 + col2];
|
| 255 |
+
const float tmpx0 = ggml_cuda_cast<float>(reinterpret_cast<const nv_bfloat16 *>(&tmpx)[0]);
|
| 256 |
+
const float tmpx1 = ggml_cuda_cast<float>(reinterpret_cast<const nv_bfloat16 *>(&tmpx)[1]);
|
| 257 |
+
ggml_cuda_mad(sumf[j], tmpx0, tmpy.x);
|
| 258 |
+
ggml_cuda_mad(sumf[j], tmpx1, tmpy.y);
|
| 259 |
+
|
| 260 |
+
if constexpr (has_fusion) {
|
| 261 |
+
if (use_gate) {
|
| 262 |
+
const float tmpx0_gate = ggml_cuda_cast<float>(reinterpret_cast<const nv_bfloat16 *>(&tmpx_gate)[0]);
|
| 263 |
+
const float tmpx1_gate = ggml_cuda_cast<float>(reinterpret_cast<const nv_bfloat16 *>(&tmpx_gate)[1]);
|
| 264 |
+
ggml_cuda_mad(sumf_gate[j], tmpx0_gate, tmpy.x);
|
| 265 |
+
ggml_cuda_mad(sumf_gate[j], tmpx1_gate, tmpy.y);
|
| 266 |
+
}
|
| 267 |
+
}
|
| 268 |
+
}
|
| 269 |
+
}
|
| 270 |
+
#else
|
| 271 |
+
const nv_bfloat162 * x2 = (const nv_bfloat162 *) x;
|
| 272 |
+
[[maybe_unused]] const nv_bfloat162 * gate_x2 = nullptr;
|
| 273 |
+
if constexpr (has_fusion) {
|
| 274 |
+
if (use_gate) {
|
| 275 |
+
gate_x2 = (const nv_bfloat162 *) gate_x;
|
| 276 |
+
}
|
| 277 |
+
}
|
| 278 |
+
for (int col2 = tid; col2 < ncols2; col2 += block_size) {
|
| 279 |
+
const nv_bfloat162 tmpx = x2[col2];
|
| 280 |
+
[[maybe_unused]] nv_bfloat162 tmpx_gate;
|
| 281 |
+
if constexpr (has_fusion) {
|
| 282 |
+
if (use_gate) {
|
| 283 |
+
tmpx_gate = gate_x2[col2];
|
| 284 |
+
}
|
| 285 |
+
}
|
| 286 |
+
#pragma unroll
|
| 287 |
+
for (int j = 0; j < ncols_dst; ++j) {
|
| 288 |
+
const float2 tmpy = y2[j*stride_col_y2 + col2];
|
| 289 |
+
ggml_cuda_mad(sumf[j], tmpx.x, tmpy.x);
|
| 290 |
+
ggml_cuda_mad(sumf[j], tmpx.y, tmpy.y);
|
| 291 |
+
|
| 292 |
+
if constexpr (has_fusion) {
|
| 293 |
+
if (use_gate) {
|
| 294 |
+
ggml_cuda_mad(sumf_gate[j], tmpx_gate.x, tmpy.x);
|
| 295 |
+
ggml_cuda_mad(sumf_gate[j], tmpx_gate.y, tmpy.y);
|
| 296 |
+
}
|
| 297 |
+
}
|
| 298 |
+
}
|
| 299 |
+
}
|
| 300 |
+
#endif
|
| 301 |
+
} else {
|
| 302 |
+
static_assert(std::is_same_v<T, void>, "unsupported type");
|
| 303 |
+
}
|
| 304 |
+
|
| 305 |
+
ggml_cuda_pdl_lc();
|
| 306 |
+
#pragma unroll
|
| 307 |
+
for (int j = 0; j < ncols_dst; ++j) {
|
| 308 |
+
sumf[j] = warp_reduce_sum<warp_size>(sumf[j]);
|
| 309 |
+
|
| 310 |
+
if constexpr (has_fusion) {
|
| 311 |
+
if (use_gate) {
|
| 312 |
+
sumf_gate[j] = warp_reduce_sum<warp_size>(sumf_gate[j]);
|
| 313 |
+
}
|
| 314 |
+
}
|
| 315 |
+
|
| 316 |
+
if (block_size > warp_size) {
|
| 317 |
+
buf_iw[tid/warp_size] = sumf[j];
|
| 318 |
+
if constexpr (has_fusion) {
|
| 319 |
+
if (use_gate) {
|
| 320 |
+
buf_iw_gate[tid/warp_size] = sumf_gate[j];
|
| 321 |
+
}
|
| 322 |
+
}
|
| 323 |
+
__syncthreads();
|
| 324 |
+
if (tid < warp_size) {
|
| 325 |
+
sumf[j] = buf_iw[tid];
|
| 326 |
+
sumf[j] = warp_reduce_sum<warp_size>(sumf[j]);
|
| 327 |
+
if constexpr (has_fusion) {
|
| 328 |
+
if (use_gate) {
|
| 329 |
+
sumf_gate[j] = buf_iw_gate[tid];
|
| 330 |
+
sumf_gate[j] = warp_reduce_sum<warp_size>(sumf_gate[j]);
|
| 331 |
+
}
|
| 332 |
+
}
|
| 333 |
+
}
|
| 334 |
+
|
| 335 |
+
if (j < ncols_dst) {
|
| 336 |
+
__syncthreads();
|
| 337 |
+
}
|
| 338 |
+
}
|
| 339 |
+
}
|
| 340 |
+
|
| 341 |
+
if (tid >= ncols_dst) {
|
| 342 |
+
return;
|
| 343 |
+
}
|
| 344 |
+
|
| 345 |
+
float value = sumf[tid];
|
| 346 |
+
|
| 347 |
+
if constexpr (has_fusion) {
|
| 348 |
+
if (use_bias) {
|
| 349 |
+
value += x_bias[tid*stride_col_dst + row];
|
| 350 |
+
}
|
| 351 |
+
|
| 352 |
+
if (use_gate) {
|
| 353 |
+
float gate_value = sumf_gate[tid];
|
| 354 |
+
if (use_gate_bias) {
|
| 355 |
+
gate_value += gate_bias[tid*stride_col_dst + row];
|
| 356 |
+
}
|
| 357 |
+
switch (glu_op) {
|
| 358 |
+
case GGML_GLU_OP_SWIGLU:
|
| 359 |
+
value *= ggml_cuda_op_silu_single(gate_value);
|
| 360 |
+
break;
|
| 361 |
+
case GGML_GLU_OP_GEGLU:
|
| 362 |
+
value *= ggml_cuda_op_gelu_single(gate_value);
|
| 363 |
+
break;
|
| 364 |
+
case GGML_GLU_OP_SWIGLU_OAI: {
|
| 365 |
+
value = ggml_cuda_op_swiglu_oai_single(gate_value, value);
|
| 366 |
+
break;
|
| 367 |
+
}
|
| 368 |
+
default:
|
| 369 |
+
break;
|
| 370 |
+
}
|
| 371 |
+
}
|
| 372 |
+
}
|
| 373 |
+
|
| 374 |
+
dst[tid*stride_col_dst + row] = value;
|
| 375 |
+
|
| 376 |
+
if constexpr (!has_fusion) {
|
| 377 |
+
GGML_UNUSED_VARS(use_gate, use_bias, use_gate_bias, glu_op, gate_x, x_bias, gate_bias, sumf_gate);
|
| 378 |
+
}
|
| 379 |
+
}
|
| 380 |
+
|
| 381 |
+
template<typename T, typename type_acc, int ncols_dst, int block_size, bool is_multi_token_id = false>
|
| 382 |
+
static void mul_mat_vec_f_switch_fusion(
|
| 383 |
+
const T * x, const float * y, const int32_t * ids, const ggml_cuda_mm_fusion_args_device fusion, float * dst,
|
| 384 |
+
const int64_t ncols, const uint3 nchannels_y,
|
| 385 |
+
const int64_t stride_row, const int64_t stride_col_y, const int64_t stride_col_dst,
|
| 386 |
+
const uint3 channel_ratio, const int stride_channel_x, const int stride_channel_y, const int stride_channel_dst,
|
| 387 |
+
const uint3 sample_ratio, const int stride_sample_x, const int stride_sample_y, const int stride_sample_dst,
|
| 388 |
+
const dim3 & block_dims, const dim3 & block_nums, const int nbytes_shared, const int ids_stride, const cudaStream_t stream) {
|
| 389 |
+
|
| 390 |
+
const ggml_cuda_kernel_launch_params launch_params = {block_nums, block_dims, nbytes_shared, stream};
|
| 391 |
+
|
| 392 |
+
const bool has_fusion = fusion.gate != nullptr || fusion.x_bias != nullptr || fusion.gate_bias != nullptr;
|
| 393 |
+
if constexpr (ncols_dst == 1) {
|
| 394 |
+
if (has_fusion) {
|
| 395 |
+
ggml_cuda_kernel_launch(mul_mat_vec_f<T, type_acc, ncols_dst, block_size, true, is_multi_token_id>, launch_params,
|
| 396 |
+
x, y, ids, fusion, dst, ncols, nchannels_y, stride_row, stride_col_y, stride_col_dst,
|
| 397 |
+
channel_ratio, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 398 |
+
sample_ratio, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride);
|
| 399 |
+
return;
|
| 400 |
+
}
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
GGML_ASSERT(!has_fusion && "fusion only supported for ncols_dst=1");
|
| 404 |
+
|
| 405 |
+
ggml_cuda_kernel_launch(mul_mat_vec_f<T, type_acc, ncols_dst, block_size, false, is_multi_token_id>, launch_params,
|
| 406 |
+
x, y, ids, fusion, dst, ncols, nchannels_y, stride_row, stride_col_y, stride_col_dst,
|
| 407 |
+
channel_ratio, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 408 |
+
sample_ratio, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride);
|
| 409 |
+
|
| 410 |
+
}
|
| 411 |
+
|
| 412 |
+
template <typename T, typename type_acc, int ncols_dst, bool is_multi_token_id = false>
|
| 413 |
+
void launch_mul_mat_vec_f_cuda(
|
| 414 |
+
const T * x, const float * y, const int32_t * ids, const ggml_cuda_mm_fusion_args_device fusion, float * dst,
|
| 415 |
+
const int64_t ncols, const int64_t nrows,
|
| 416 |
+
const int64_t stride_row, const int64_t stride_col_y, const int64_t stride_col_dst,
|
| 417 |
+
const int64_t nchannels_x, const int64_t nchannels_y, const int64_t nchannels_dst,
|
| 418 |
+
const int64_t stride_channel_x, const int64_t stride_channel_y, const int64_t stride_channel_dst, const int64_t nsamples_x,
|
| 419 |
+
const int64_t nsamples_dst, const int64_t stride_sample_x, const int64_t stride_sample_y, const int64_t stride_sample_dst,
|
| 420 |
+
const int64_t nsamples_or_ntokens, const int64_t ids_stride, cudaStream_t stream) {
|
| 421 |
+
GGML_ASSERT(ncols % 2 == 0);
|
| 422 |
+
GGML_ASSERT(stride_row % 2 == 0);
|
| 423 |
+
GGML_ASSERT(stride_col_y % 2 == 0);
|
| 424 |
+
GGML_ASSERT(ids || nchannels_dst % nchannels_x == 0);
|
| 425 |
+
GGML_ASSERT( nsamples_dst % nsamples_x == 0);
|
| 426 |
+
const uint3 nchannels_y_fd = ids ? init_fastdiv_values(nchannels_y) : make_uint3(0, 0, 0);
|
| 427 |
+
const uint3 channel_ratio_fd = ids ? make_uint3(0, 0, 0) : init_fastdiv_values(nchannels_dst / nchannels_x);
|
| 428 |
+
const uint3 sample_ratio_fd = init_fastdiv_values(nsamples_dst / nsamples_x);
|
| 429 |
+
|
| 430 |
+
const int device = ggml_cuda_get_device();
|
| 431 |
+
const int warp_size = ggml_cuda_info().devices[device].warp_size;
|
| 432 |
+
|
| 433 |
+
int64_t block_size_best = warp_size;
|
| 434 |
+
int64_t niter_best = (ncols + 2*warp_size - 1) / (2*warp_size);
|
| 435 |
+
int64_t max_block_size = 256;
|
| 436 |
+
if(ggml_cuda_info().devices[device].cc > GGML_CUDA_CC_OFFSET_AMD && ggml_cuda_info().devices[device].cc < GGML_CUDA_CC_RDNA1) {
|
| 437 |
+
max_block_size = 128;
|
| 438 |
+
}
|
| 439 |
+
for (int64_t block_size = 2*warp_size; block_size <= max_block_size; block_size += warp_size) {
|
| 440 |
+
const int64_t niter = (ncols + 2*block_size - 1) / (2*block_size);
|
| 441 |
+
if (niter < niter_best) {
|
| 442 |
+
niter_best = niter;
|
| 443 |
+
block_size_best = block_size;
|
| 444 |
+
}
|
| 445 |
+
}
|
| 446 |
+
|
| 447 |
+
const bool has_fusion = fusion.gate != nullptr || fusion.x_bias != nullptr || fusion.gate_bias != nullptr;
|
| 448 |
+
|
| 449 |
+
const int nbytes_shared = warp_size*sizeof(float) + (has_fusion ? warp_size*sizeof(float) : 0);
|
| 450 |
+
const dim3 block_nums(nrows, nchannels_dst, nsamples_or_ntokens);
|
| 451 |
+
const dim3 block_dims(block_size_best, 1, 1);
|
| 452 |
+
switch (block_size_best) {
|
| 453 |
+
case 32: {
|
| 454 |
+
mul_mat_vec_f_switch_fusion<T, type_acc, ncols_dst, 32, is_multi_token_id>
|
| 455 |
+
(x, y, ids, fusion, dst, ncols/2, nchannels_y_fd, stride_row, stride_col_y/2, stride_col_dst,
|
| 456 |
+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 457 |
+
sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst, block_dims, block_nums, nbytes_shared, ids_stride, stream);
|
| 458 |
+
} break;
|
| 459 |
+
case 64: {
|
| 460 |
+
mul_mat_vec_f_switch_fusion<T, type_acc, ncols_dst, 64, is_multi_token_id>
|
| 461 |
+
(x, y, ids, fusion, dst, ncols/2, nchannels_y_fd, stride_row, stride_col_y/2, stride_col_dst,
|
| 462 |
+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 463 |
+
sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst, block_dims, block_nums, nbytes_shared, ids_stride, stream);
|
| 464 |
+
} break;
|
| 465 |
+
case 96: {
|
| 466 |
+
mul_mat_vec_f_switch_fusion<T, type_acc, ncols_dst, 96, is_multi_token_id>
|
| 467 |
+
(x, y, ids, fusion, dst, ncols/2, nchannels_y_fd, stride_row, stride_col_y/2, stride_col_dst,
|
| 468 |
+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 469 |
+
sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst, block_dims, block_nums, nbytes_shared, ids_stride, stream);
|
| 470 |
+
} break;
|
| 471 |
+
case 128: {
|
| 472 |
+
mul_mat_vec_f_switch_fusion<T, type_acc, ncols_dst, 128, is_multi_token_id>
|
| 473 |
+
(x, y, ids, fusion, dst, ncols/2, nchannels_y_fd, stride_row, stride_col_y/2, stride_col_dst,
|
| 474 |
+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 475 |
+
sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst, block_dims, block_nums, nbytes_shared, ids_stride, stream);
|
| 476 |
+
} break;
|
| 477 |
+
case 160: {
|
| 478 |
+
mul_mat_vec_f_switch_fusion<T, type_acc, ncols_dst, 160, is_multi_token_id>
|
| 479 |
+
(x, y, ids, fusion, dst, ncols/2, nchannels_y_fd, stride_row, stride_col_y/2, stride_col_dst,
|
| 480 |
+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 481 |
+
sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst, block_dims, block_nums, nbytes_shared, ids_stride, stream);
|
| 482 |
+
} break;
|
| 483 |
+
case 192: {
|
| 484 |
+
mul_mat_vec_f_switch_fusion<T, type_acc, ncols_dst, 192, is_multi_token_id>
|
| 485 |
+
(x, y, ids, fusion, dst, ncols/2, nchannels_y_fd, stride_row, stride_col_y/2, stride_col_dst,
|
| 486 |
+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 487 |
+
sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst, block_dims, block_nums, nbytes_shared, ids_stride, stream);
|
| 488 |
+
} break;
|
| 489 |
+
case 224: {
|
| 490 |
+
mul_mat_vec_f_switch_fusion<T, type_acc, ncols_dst, 224, is_multi_token_id>
|
| 491 |
+
(x, y, ids, fusion, dst, ncols/2, nchannels_y_fd, stride_row, stride_col_y/2, stride_col_dst,
|
| 492 |
+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 493 |
+
sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst, block_dims, block_nums, nbytes_shared, ids_stride, stream);
|
| 494 |
+
} break;
|
| 495 |
+
case 256: {
|
| 496 |
+
mul_mat_vec_f_switch_fusion<T, type_acc, ncols_dst, 256, is_multi_token_id>
|
| 497 |
+
(x, y, ids, fusion, dst, ncols/2, nchannels_y_fd, stride_row, stride_col_y/2, stride_col_dst,
|
| 498 |
+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 499 |
+
sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst, block_dims, block_nums, nbytes_shared, ids_stride, stream);
|
| 500 |
+
} break;
|
| 501 |
+
default: {
|
| 502 |
+
GGML_ABORT("fatal error");
|
| 503 |
+
} break;
|
| 504 |
+
}
|
| 505 |
+
}
|
| 506 |
+
|
| 507 |
+
template <typename T, typename type_acc>
|
| 508 |
+
static void mul_mat_vec_f_cuda_switch_ncols_dst(
|
| 509 |
+
const T * x, const float * y, const int32_t * ids, const ggml_cuda_mm_fusion_args_device fusion, float * dst,
|
| 510 |
+
const int64_t ncols, const int64_t nrows, const int64_t ncols_dst,
|
| 511 |
+
const int64_t stride_row, const int64_t stride_col_y, const int64_t stride_col_dst,
|
| 512 |
+
const int64_t nchannels_x, const int64_t nchannels_y, const int64_t nchannels_dst,
|
| 513 |
+
const int64_t stride_channel_x, const int64_t stride_channel_y, const int64_t stride_channel_dst, const int64_t nsamples_x,
|
| 514 |
+
const int64_t nsamples_dst, const int64_t stride_sample_x, const int64_t stride_sample_y, const int64_t stride_sample_dst,
|
| 515 |
+
const int64_t ids_stride, cudaStream_t stream) {
|
| 516 |
+
|
| 517 |
+
const bool has_ids = ids != nullptr;
|
| 518 |
+
|
| 519 |
+
if (has_ids && ncols_dst > 1) {
|
| 520 |
+
// Multi-token MUL_MAT_ID path only - single-token goes through regular path below
|
| 521 |
+
constexpr int c_ncols_dst = 1;
|
| 522 |
+
launch_mul_mat_vec_f_cuda<T, type_acc, c_ncols_dst, true>
|
| 523 |
+
(x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst,
|
| 524 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y,
|
| 525 |
+
stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst,
|
| 526 |
+
ncols_dst, ids_stride, stream);
|
| 527 |
+
return;
|
| 528 |
+
}
|
| 529 |
+
|
| 530 |
+
if (has_ids) {
|
| 531 |
+
// Single-token MUL_MAT_ID path
|
| 532 |
+
constexpr int c_ncols_dst = 1;
|
| 533 |
+
launch_mul_mat_vec_f_cuda<T, type_acc, c_ncols_dst>
|
| 534 |
+
(x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst,
|
| 535 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y,
|
| 536 |
+
stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst,
|
| 537 |
+
ncols_dst, ids_stride, stream);
|
| 538 |
+
return;
|
| 539 |
+
}
|
| 540 |
+
|
| 541 |
+
switch (ncols_dst) {
|
| 542 |
+
case 1:
|
| 543 |
+
launch_mul_mat_vec_f_cuda<T, type_acc, 1>
|
| 544 |
+
(x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst,
|
| 545 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y,
|
| 546 |
+
stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst,
|
| 547 |
+
nsamples_dst, ids_stride, stream);
|
| 548 |
+
break;
|
| 549 |
+
case 2:
|
| 550 |
+
launch_mul_mat_vec_f_cuda<T, type_acc, 2>
|
| 551 |
+
(x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst,
|
| 552 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y,
|
| 553 |
+
stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst,
|
| 554 |
+
nsamples_dst, ids_stride, stream);
|
| 555 |
+
break;
|
| 556 |
+
case 3:
|
| 557 |
+
launch_mul_mat_vec_f_cuda<T, type_acc, 3>
|
| 558 |
+
(x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst,
|
| 559 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y,
|
| 560 |
+
stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst,
|
| 561 |
+
nsamples_dst, ids_stride, stream);
|
| 562 |
+
break;
|
| 563 |
+
case 4:
|
| 564 |
+
launch_mul_mat_vec_f_cuda<T, type_acc, 4>
|
| 565 |
+
(x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst,
|
| 566 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y,
|
| 567 |
+
stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst,
|
| 568 |
+
nsamples_dst, ids_stride, stream);
|
| 569 |
+
break;
|
| 570 |
+
case 5:
|
| 571 |
+
launch_mul_mat_vec_f_cuda<T, type_acc, 5>
|
| 572 |
+
(x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst,
|
| 573 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y,
|
| 574 |
+
stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst,
|
| 575 |
+
nsamples_dst, ids_stride, stream);
|
| 576 |
+
break;
|
| 577 |
+
case 6:
|
| 578 |
+
launch_mul_mat_vec_f_cuda<T, type_acc, 6>
|
| 579 |
+
(x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst,
|
| 580 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y,
|
| 581 |
+
stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst,
|
| 582 |
+
nsamples_dst, ids_stride, stream);
|
| 583 |
+
break;
|
| 584 |
+
case 7:
|
| 585 |
+
launch_mul_mat_vec_f_cuda<T, type_acc, 7>
|
| 586 |
+
(x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst,
|
| 587 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y,
|
| 588 |
+
stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst,
|
| 589 |
+
nsamples_dst, ids_stride, stream);
|
| 590 |
+
break;
|
| 591 |
+
case 8:
|
| 592 |
+
launch_mul_mat_vec_f_cuda<T, type_acc, 8>
|
| 593 |
+
(x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst,
|
| 594 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y,
|
| 595 |
+
stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst,
|
| 596 |
+
nsamples_dst, ids_stride, stream);
|
| 597 |
+
break;
|
| 598 |
+
default:
|
| 599 |
+
GGML_ABORT("fatal error");
|
| 600 |
+
break;
|
| 601 |
+
}
|
| 602 |
+
}
|
| 603 |
+
|
| 604 |
+
template<typename T>
|
| 605 |
+
static void mul_mat_vec_f_cuda(
|
| 606 |
+
const T * x, const float * y, const int32_t * ids, const ggml_cuda_mm_fusion_args_device fusion, float * dst,
|
| 607 |
+
const int64_t ncols, const int64_t nrows, const int64_t ncols_dst,
|
| 608 |
+
const int64_t stride_row, const int64_t stride_col_y, const int stride_col_dst,
|
| 609 |
+
const int64_t nchannels_x, const int64_t nchannels_y, const int64_t nchannels_dst,
|
| 610 |
+
const int64_t stride_channel_x, const int64_t stride_channel_y, const int64_t stride_channel_dst, const int64_t nsamples_x,
|
| 611 |
+
const int64_t nsamples_dst, const int64_t stride_sample_x, const int64_t stride_sample_y, const int64_t stride_sample_dst,
|
| 612 |
+
const int64_t ids_stride, enum ggml_prec prec, cudaStream_t stream) {
|
| 613 |
+
|
| 614 |
+
if constexpr(std::is_same_v<T, half>) {
|
| 615 |
+
if (prec == GGML_PREC_DEFAULT) {
|
| 616 |
+
mul_mat_vec_f_cuda_switch_ncols_dst<T, half>
|
| 617 |
+
(x, y, ids, fusion, dst, ncols, nrows, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 618 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y,
|
| 619 |
+
stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 620 |
+
return;
|
| 621 |
+
}
|
| 622 |
+
}
|
| 623 |
+
mul_mat_vec_f_cuda_switch_ncols_dst<T, float>
|
| 624 |
+
(x, y, ids, fusion, dst, ncols, nrows, ncols_dst, stride_row, stride_col_y, stride_col_dst,
|
| 625 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y,
|
| 626 |
+
stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 627 |
+
}
|
| 628 |
+
|
| 629 |
+
void ggml_cuda_mul_mat_vec_f(ggml_backend_cuda_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * ids, ggml_tensor * dst,
|
| 630 |
+
const ggml_cuda_mm_fusion_args_host * fusion) {
|
| 631 |
+
GGML_ASSERT( src1->type == GGML_TYPE_F32);
|
| 632 |
+
GGML_ASSERT(!ids || ids->type == GGML_TYPE_I32);
|
| 633 |
+
GGML_ASSERT( dst->type == GGML_TYPE_F32);
|
| 634 |
+
|
| 635 |
+
GGML_TENSOR_BINARY_OP_LOCALS;
|
| 636 |
+
|
| 637 |
+
const size_t ts_src0 = ggml_type_size(src0->type);
|
| 638 |
+
const size_t ts_src1 = ggml_type_size(src1->type);
|
| 639 |
+
const size_t ts_dst = ggml_type_size(dst->type);
|
| 640 |
+
|
| 641 |
+
GGML_ASSERT(!ids || ne12 <= MMVF_MAX_BATCH_SIZE);
|
| 642 |
+
GGML_ASSERT(ne13 == ne3);
|
| 643 |
+
|
| 644 |
+
GGML_ASSERT( nb00 == ts_src0);
|
| 645 |
+
GGML_ASSERT( nb10 == ts_src1);
|
| 646 |
+
GGML_ASSERT(!ids || ids->nb[0] == ggml_type_size(ids->type));
|
| 647 |
+
GGML_ASSERT( nb0 == ts_dst);
|
| 648 |
+
|
| 649 |
+
const int cc = ggml_cuda_info().devices[ggml_cuda_get_device()].cc;
|
| 650 |
+
const enum ggml_prec prec = fast_fp16_available(cc) ? ggml_prec(dst->op_params[0]) : GGML_PREC_F32;
|
| 651 |
+
|
| 652 |
+
const float * src1_d = (const float *) src1->data;
|
| 653 |
+
const int32_t * ids_d = ids ? (const int32_t *) ids->data : nullptr;
|
| 654 |
+
float * dst_d = (float *) dst->data;
|
| 655 |
+
|
| 656 |
+
ggml_cuda_mm_fusion_args_device fusion_local{};
|
| 657 |
+
|
| 658 |
+
if (fusion) {
|
| 659 |
+
GGML_ASSERT( !ids || dst->ne[2] == 1);
|
| 660 |
+
GGML_ASSERT( ids || dst->ne[1] == 1);
|
| 661 |
+
if (fusion->x_bias) {
|
| 662 |
+
GGML_ASSERT(fusion->x_bias->type == GGML_TYPE_F32);
|
| 663 |
+
GGML_ASSERT(fusion->x_bias->ne[0] == dst->ne[0]);
|
| 664 |
+
GGML_ASSERT(!ids || fusion->x_bias->ne[1] == src0->ne[2]);
|
| 665 |
+
fusion_local.x_bias = fusion->x_bias->data;
|
| 666 |
+
}
|
| 667 |
+
if (fusion->gate) {
|
| 668 |
+
GGML_ASSERT(fusion->gate->type == src0->type && ggml_are_same_stride(fusion->gate, src0));
|
| 669 |
+
fusion_local.gate = fusion->gate->data;
|
| 670 |
+
}
|
| 671 |
+
if (fusion->gate_bias) {
|
| 672 |
+
GGML_ASSERT(fusion->gate_bias->type == GGML_TYPE_F32);
|
| 673 |
+
GGML_ASSERT(fusion->gate_bias->ne[0] == dst->ne[0]);
|
| 674 |
+
GGML_ASSERT(!ids || fusion->gate_bias->ne[1] == src0->ne[2]);
|
| 675 |
+
fusion_local.gate_bias = fusion->gate_bias->data;
|
| 676 |
+
}
|
| 677 |
+
fusion_local.glu_op = fusion->glu_op;
|
| 678 |
+
}
|
| 679 |
+
|
| 680 |
+
const int64_t s01 = src0->nb[1] / ts_src0;
|
| 681 |
+
const int64_t s11 = src1->nb[1] / ts_src1;
|
| 682 |
+
const int64_t s1 = dst->nb[1] / ts_dst;
|
| 683 |
+
const int64_t s02 = src0->nb[2] / ts_src0;
|
| 684 |
+
const int64_t s12 = src1->nb[2] / ts_src1;
|
| 685 |
+
const int64_t s2 = dst->nb[2] / ts_dst;
|
| 686 |
+
const int64_t s03 = src0->nb[3] / ts_src0;
|
| 687 |
+
const int64_t s13 = src1->nb[3] / ts_src1;
|
| 688 |
+
const int64_t s3 = dst->nb[3] / ts_dst;
|
| 689 |
+
|
| 690 |
+
// For MUL_MAT_ID the memory layout is different than for MUL_MAT:
|
| 691 |
+
const int64_t ncols_dst = ids ? ne2 : ne1;
|
| 692 |
+
const int64_t nchannels_y = ids ? ne11 : ne12;
|
| 693 |
+
const int64_t nchannels_dst = ids ? ne1 : ne2;
|
| 694 |
+
const int64_t stride_col_dst = ids ? s2 : s1;
|
| 695 |
+
const int64_t stride_col_y = ids ? s12 : s11;
|
| 696 |
+
const int64_t stride_channel_dst = ids ? s1 : s2;
|
| 697 |
+
const int64_t stride_channel_y = ids ? s11 : s12;
|
| 698 |
+
|
| 699 |
+
const int64_t ids_stride = ids ? ids->nb[1] / ggml_type_size(ids->type) : 0;
|
| 700 |
+
|
| 701 |
+
switch (src0->type) {
|
| 702 |
+
case GGML_TYPE_F32: {
|
| 703 |
+
const float * src0_d = (const float *) src0->data;
|
| 704 |
+
mul_mat_vec_f_cuda(src0_d, src1_d, ids_d, fusion_local, dst_d, ne00, ne01, ncols_dst, s01, stride_col_y, stride_col_dst,
|
| 705 |
+
ne02, nchannels_y, nchannels_dst, s02, stride_channel_y, stride_channel_dst,
|
| 706 |
+
ne03, ne3, s03, s13, s3, ids_stride, prec, ctx.stream());
|
| 707 |
+
} break;
|
| 708 |
+
case GGML_TYPE_F16: {
|
| 709 |
+
const half * src0_d = (const half *) src0->data;
|
| 710 |
+
mul_mat_vec_f_cuda(src0_d, src1_d, ids_d, fusion_local, dst_d, ne00, ne01, ncols_dst, s01, stride_col_y, stride_col_dst,
|
| 711 |
+
ne02, nchannels_y, nchannels_dst, s02, stride_channel_y, stride_channel_dst,
|
| 712 |
+
ne03, ne3, s03, s13, s3, ids_stride, prec, ctx.stream());
|
| 713 |
+
} break;
|
| 714 |
+
case GGML_TYPE_BF16: {
|
| 715 |
+
const nv_bfloat16 * src0_d = (const nv_bfloat16 *) src0->data;
|
| 716 |
+
mul_mat_vec_f_cuda(src0_d, src1_d, ids_d, fusion_local, dst_d, ne00, ne01, ncols_dst, s01, stride_col_y, stride_col_dst,
|
| 717 |
+
ne02, nchannels_y, nchannels_dst, s02, stride_channel_y, stride_channel_dst,
|
| 718 |
+
ne03, ne3, s03, s13, s3, ids_stride, prec, ctx.stream());
|
| 719 |
+
} break;
|
| 720 |
+
default:
|
| 721 |
+
GGML_ABORT("unsupported type: %s", ggml_type_name(src0->type));
|
| 722 |
+
}
|
| 723 |
+
}
|
| 724 |
+
|
| 725 |
+
void ggml_cuda_op_mul_mat_vec_f(
|
| 726 |
+
ggml_backend_cuda_context & ctx,
|
| 727 |
+
const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, const char * src0_dd_i, const float * src1_ddf_i,
|
| 728 |
+
const char * src1_ddq_i, float * dst_dd_i, const int64_t row_low, const int64_t row_high, const int64_t src1_ncols,
|
| 729 |
+
const int64_t src1_padded_row_size, cudaStream_t stream) {
|
| 730 |
+
|
| 731 |
+
GGML_ASSERT(src1->type == GGML_TYPE_F32);
|
| 732 |
+
GGML_ASSERT(dst->type == GGML_TYPE_F32);
|
| 733 |
+
|
| 734 |
+
const int64_t ne00 = src0->ne[0];
|
| 735 |
+
const int64_t ne10 = src1->ne[0];
|
| 736 |
+
const int64_t ne0 = dst->ne[0];
|
| 737 |
+
const int64_t row_diff = row_high - row_low;
|
| 738 |
+
|
| 739 |
+
const int id = ggml_cuda_get_device();
|
| 740 |
+
const int cc = ggml_cuda_info().devices[id].cc;
|
| 741 |
+
const enum ggml_prec prec = fast_fp16_available(cc) ? ggml_prec(dst->op_params[0]) : GGML_PREC_F32;
|
| 742 |
+
|
| 743 |
+
// ggml_cuda_op provides single, contiguous matrices
|
| 744 |
+
const int64_t stride_row = ne00;
|
| 745 |
+
const int64_t stride_col_y = ne10;
|
| 746 |
+
const int64_t stride_col_dst = id == ctx.device ? ne0 : row_diff; // main device has larger memory buffer
|
| 747 |
+
const int64_t nchannels_x = 1;
|
| 748 |
+
const int64_t nchannels_y = 1;
|
| 749 |
+
const int64_t nchannels_dst = 1;
|
| 750 |
+
const int64_t stride_channel_x = 0;
|
| 751 |
+
const int64_t stride_channel_y = 0;
|
| 752 |
+
const int64_t stride_channel_dst = 0;
|
| 753 |
+
const int64_t nsamples_x = 1;
|
| 754 |
+
const int64_t nsamples_dst = 1;
|
| 755 |
+
const int64_t stride_sample_x = 0;
|
| 756 |
+
const int64_t stride_sample_y = 0;
|
| 757 |
+
const int64_t stride_sample_dst = 0;
|
| 758 |
+
|
| 759 |
+
ggml_cuda_mm_fusion_args_device empty{};
|
| 760 |
+
switch (src0->type) {
|
| 761 |
+
case GGML_TYPE_F32: {
|
| 762 |
+
const float * src0_d = (const float *) src0_dd_i;
|
| 763 |
+
mul_mat_vec_f_cuda(src0_d, src1_ddf_i, nullptr, empty, dst_dd_i, ne00, row_diff, src1_ncols, stride_row, stride_col_y, stride_col_dst,
|
| 764 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 765 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, 0, prec, stream);
|
| 766 |
+
} break;
|
| 767 |
+
case GGML_TYPE_F16: {
|
| 768 |
+
const half * src0_d = (const half *) src0_dd_i;
|
| 769 |
+
mul_mat_vec_f_cuda(src0_d, src1_ddf_i, nullptr, empty, dst_dd_i, ne00, row_diff, src1_ncols, stride_row, stride_col_y, stride_col_dst,
|
| 770 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 771 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, 0, prec, stream);
|
| 772 |
+
} break;
|
| 773 |
+
case GGML_TYPE_BF16: {
|
| 774 |
+
const nv_bfloat16 * src0_d = (const nv_bfloat16 *) src0_dd_i;
|
| 775 |
+
mul_mat_vec_f_cuda(src0_d, src1_ddf_i, nullptr, empty, dst_dd_i, ne00, row_diff, src1_ncols, stride_row, stride_col_y, stride_col_dst,
|
| 776 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 777 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, 0, prec, stream);
|
| 778 |
+
} break;
|
| 779 |
+
default:
|
| 780 |
+
GGML_ABORT("unsupported type: %s", ggml_type_name(src0->type));
|
| 781 |
+
}
|
| 782 |
+
|
| 783 |
+
GGML_UNUSED_VARS(ctx, src1, dst, src1_ddq_i, src1_ncols, src1_padded_row_size);
|
| 784 |
+
}
|
| 785 |
+
|
| 786 |
+
bool ggml_cuda_should_use_mmvf(enum ggml_type type, int cc, const int64_t * src0_ne, const size_t * src0_nb, int64_t ne11) {
|
| 787 |
+
if (src0_ne[0] % 2 != 0) {
|
| 788 |
+
return false;
|
| 789 |
+
}
|
| 790 |
+
|
| 791 |
+
const size_t ts = ggml_type_size(type);
|
| 792 |
+
if (src0_nb[0] != ts) {
|
| 793 |
+
return false;
|
| 794 |
+
}
|
| 795 |
+
|
| 796 |
+
// Pointers not aligned to the size of half2/nv_bfloat162/float2 would result in a crash:
|
| 797 |
+
for (size_t i = 1; i < GGML_MAX_DIMS; ++i) {
|
| 798 |
+
if (src0_nb[i] % (2*ts) != 0) {
|
| 799 |
+
return false;
|
| 800 |
+
}
|
| 801 |
+
}
|
| 802 |
+
|
| 803 |
+
switch (type) {
|
| 804 |
+
case GGML_TYPE_F32:
|
| 805 |
+
if (GGML_CUDA_CC_IS_NVIDIA(cc)) {
|
| 806 |
+
if (ampere_mma_available(cc)) {
|
| 807 |
+
return ne11 <= 3;
|
| 808 |
+
}
|
| 809 |
+
if (cc >= GGML_CUDA_CC_TURING) {
|
| 810 |
+
return ne11 <= 4;
|
| 811 |
+
}
|
| 812 |
+
return ne11 <= 3;
|
| 813 |
+
} else if (GGML_CUDA_CC_IS_AMD(cc)) {
|
| 814 |
+
if (fp32_mma_hardware_available(cc)) {
|
| 815 |
+
return ne11 <= 3;
|
| 816 |
+
}
|
| 817 |
+
return ne11 <= 8;
|
| 818 |
+
}
|
| 819 |
+
return ne11 <= 8;
|
| 820 |
+
case GGML_TYPE_F16:
|
| 821 |
+
if (GGML_CUDA_CC_IS_NVIDIA(cc)) {
|
| 822 |
+
const bool src0_small = (src0_ne[1] <= 512 || src0_ne[2]*src0_ne[3] == 1);
|
| 823 |
+
if (ampere_mma_available(cc)) {
|
| 824 |
+
return src0_small && ne11 == 1;
|
| 825 |
+
}
|
| 826 |
+
if (cc >= GGML_CUDA_CC_ADA_LOVELACE) {
|
| 827 |
+
return src0_small && ne11 <= 4;
|
| 828 |
+
}
|
| 829 |
+
if (fp16_mma_hardware_available(cc)) {
|
| 830 |
+
return src0_small && ne11 <= 3;
|
| 831 |
+
}
|
| 832 |
+
return ne11 <= 8;
|
| 833 |
+
} else if (GGML_CUDA_CC_IS_AMD(cc)) {
|
| 834 |
+
if (fp16_mma_hardware_available(cc)) {
|
| 835 |
+
if (GGML_CUDA_CC_IS_RDNA3(cc)) {
|
| 836 |
+
return ne11 <= 3;
|
| 837 |
+
}
|
| 838 |
+
if (GGML_CUDA_CC_IS_RDNA4(cc)) {
|
| 839 |
+
return ne11 <= 5;
|
| 840 |
+
}
|
| 841 |
+
return ne11 <= 2;
|
| 842 |
+
}
|
| 843 |
+
return ne11 <= 8;
|
| 844 |
+
}
|
| 845 |
+
return ne11 <= 8;
|
| 846 |
+
case GGML_TYPE_BF16:
|
| 847 |
+
if (GGML_CUDA_CC_IS_NVIDIA(cc)) {
|
| 848 |
+
const bool src0_small = (src0_ne[1] <= 512 || src0_ne[2]*src0_ne[3] == 1);
|
| 849 |
+
if (ampere_mma_available(cc)) {
|
| 850 |
+
return src0_small && ne11 == 1;
|
| 851 |
+
}
|
| 852 |
+
if (cc >= GGML_CUDA_CC_ADA_LOVELACE) {
|
| 853 |
+
return src0_small && ne11 <= 4;
|
| 854 |
+
}
|
| 855 |
+
if (bf16_mma_hardware_available(cc)) {
|
| 856 |
+
return src0_small && ne11 <= 3;
|
| 857 |
+
}
|
| 858 |
+
return ne11 <= 8;
|
| 859 |
+
} else if (GGML_CUDA_CC_IS_AMD(cc)) {
|
| 860 |
+
if (bf16_mma_hardware_available(cc)) {
|
| 861 |
+
return ne11 <= 3;
|
| 862 |
+
}
|
| 863 |
+
return ne11 <= 8;
|
| 864 |
+
}
|
| 865 |
+
return ne11 <= 8;
|
| 866 |
+
default:
|
| 867 |
+
return false;
|
| 868 |
+
}
|
| 869 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/mmvf.cuh
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
|
| 3 |
+
#define MMVF_MAX_BATCH_SIZE 8 // Max. batch size for which to use MMVF kernels.
|
| 4 |
+
|
| 5 |
+
void ggml_cuda_mul_mat_vec_f(ggml_backend_cuda_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * ids, ggml_tensor * dst,
|
| 6 |
+
const ggml_cuda_mm_fusion_args_host * fusion = nullptr);
|
| 7 |
+
|
| 8 |
+
void ggml_cuda_op_mul_mat_vec_f(
|
| 9 |
+
ggml_backend_cuda_context & ctx,
|
| 10 |
+
const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, const char * src0_dd_i, const float * src1_ddf_i,
|
| 11 |
+
const char * src1_ddq_i, float * dst_dd_i, const int64_t row_low, const int64_t row_high, const int64_t src1_ncols,
|
| 12 |
+
const int64_t src1_padded_row_size, cudaStream_t stream);
|
| 13 |
+
|
| 14 |
+
bool ggml_cuda_should_use_mmvf(enum ggml_type type, int cc, const int64_t * src0_ne, const size_t * src0_nb, int64_t ne11);
|
backend/llama.cpp/ggml/src/ggml-cuda/mmvq.cu
ADDED
|
@@ -0,0 +1,1289 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "mmvq.cuh"
|
| 2 |
+
#include "quantize.cuh"
|
| 3 |
+
#include "unary.cuh"
|
| 4 |
+
#include "vecdotq.cuh"
|
| 5 |
+
|
| 6 |
+
#include <cstdint>
|
| 7 |
+
|
| 8 |
+
typedef float (*vec_dot_q_cuda_t)(const void * __restrict__ vbq, const block_q8_1 * __restrict__ bq8_1, const int & kbx, const int & iqs);
|
| 9 |
+
|
| 10 |
+
static constexpr __device__ vec_dot_q_cuda_t get_vec_dot_q_cuda(ggml_type type) {
|
| 11 |
+
switch (type) {
|
| 12 |
+
case GGML_TYPE_Q1_0: return vec_dot_q1_0_q8_1;
|
| 13 |
+
case GGML_TYPE_Q4_0: return vec_dot_q4_0_q8_1;
|
| 14 |
+
case GGML_TYPE_Q4_1: return vec_dot_q4_1_q8_1;
|
| 15 |
+
case GGML_TYPE_Q5_0: return vec_dot_q5_0_q8_1;
|
| 16 |
+
case GGML_TYPE_Q5_1: return vec_dot_q5_1_q8_1;
|
| 17 |
+
case GGML_TYPE_Q8_0: return vec_dot_q8_0_q8_1;
|
| 18 |
+
case GGML_TYPE_MXFP4: return vec_dot_mxfp4_q8_1;
|
| 19 |
+
case GGML_TYPE_NVFP4: return vec_dot_nvfp4_q8_1;
|
| 20 |
+
case GGML_TYPE_Q2_K: return vec_dot_q2_K_q8_1;
|
| 21 |
+
case GGML_TYPE_Q3_K: return vec_dot_q3_K_q8_1;
|
| 22 |
+
case GGML_TYPE_Q4_K: return vec_dot_q4_K_q8_1;
|
| 23 |
+
case GGML_TYPE_Q5_K: return vec_dot_q5_K_q8_1;
|
| 24 |
+
case GGML_TYPE_Q6_K: return vec_dot_q6_K_q8_1;
|
| 25 |
+
case GGML_TYPE_IQ2_XXS: return vec_dot_iq2_xxs_q8_1;
|
| 26 |
+
case GGML_TYPE_IQ2_XS: return vec_dot_iq2_xs_q8_1;
|
| 27 |
+
case GGML_TYPE_IQ2_S: return vec_dot_iq2_s_q8_1;
|
| 28 |
+
case GGML_TYPE_IQ3_XXS: return vec_dot_iq3_xxs_q8_1;
|
| 29 |
+
case GGML_TYPE_IQ1_S: return vec_dot_iq1_s_q8_1;
|
| 30 |
+
case GGML_TYPE_IQ1_M: return vec_dot_iq1_m_q8_1;
|
| 31 |
+
case GGML_TYPE_IQ4_NL: return vec_dot_iq4_nl_q8_1;
|
| 32 |
+
case GGML_TYPE_IQ4_XS: return vec_dot_iq4_xs_q8_1;
|
| 33 |
+
case GGML_TYPE_IQ3_S: return vec_dot_iq3_s_q8_1;
|
| 34 |
+
default: return nullptr;
|
| 35 |
+
}
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
static constexpr __host__ __device__ int get_vdr_mmvq(ggml_type type) {
|
| 39 |
+
switch (type) {
|
| 40 |
+
case GGML_TYPE_Q1_0: return VDR_Q1_0_Q8_1_MMVQ;
|
| 41 |
+
case GGML_TYPE_Q4_0: return VDR_Q4_0_Q8_1_MMVQ;
|
| 42 |
+
case GGML_TYPE_Q4_1: return VDR_Q4_1_Q8_1_MMVQ;
|
| 43 |
+
case GGML_TYPE_Q5_0: return VDR_Q5_0_Q8_1_MMVQ;
|
| 44 |
+
case GGML_TYPE_Q5_1: return VDR_Q5_1_Q8_1_MMVQ;
|
| 45 |
+
case GGML_TYPE_Q8_0: return VDR_Q8_0_Q8_1_MMVQ;
|
| 46 |
+
case GGML_TYPE_MXFP4: return VDR_MXFP4_Q8_1_MMVQ;
|
| 47 |
+
case GGML_TYPE_NVFP4: return VDR_NVFP4_Q8_1_MMVQ;
|
| 48 |
+
case GGML_TYPE_Q2_K: return VDR_Q2_K_Q8_1_MMVQ;
|
| 49 |
+
case GGML_TYPE_Q3_K: return VDR_Q3_K_Q8_1_MMVQ;
|
| 50 |
+
case GGML_TYPE_Q4_K: return VDR_Q4_K_Q8_1_MMVQ;
|
| 51 |
+
case GGML_TYPE_Q5_K: return VDR_Q5_K_Q8_1_MMVQ;
|
| 52 |
+
case GGML_TYPE_Q6_K: return VDR_Q6_K_Q8_1_MMVQ;
|
| 53 |
+
case GGML_TYPE_IQ2_XXS: return VDR_IQ2_XXS_Q8_1_MMVQ;
|
| 54 |
+
case GGML_TYPE_IQ2_XS: return VDR_IQ2_XS_Q8_1_MMVQ;
|
| 55 |
+
case GGML_TYPE_IQ2_S: return VDR_IQ2_S_Q8_1_MMVQ;
|
| 56 |
+
case GGML_TYPE_IQ3_XXS: return VDR_IQ3_XXS_Q8_1_MMVQ;
|
| 57 |
+
case GGML_TYPE_IQ3_S: return VDR_IQ3_S_Q8_1_MMVQ;
|
| 58 |
+
case GGML_TYPE_IQ4_NL: return VDR_IQ4_NL_Q8_1_MMVQ;
|
| 59 |
+
case GGML_TYPE_IQ4_XS: return VDR_IQ4_XS_Q8_1_MMVQ;
|
| 60 |
+
default: return 1;
|
| 61 |
+
}
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
enum mmvq_parameter_table_id {
|
| 65 |
+
MMVQ_PARAMETERS_GENERIC = 0,
|
| 66 |
+
MMVQ_PARAMETERS_TURING,
|
| 67 |
+
MMVQ_PARAMETERS_GCN,
|
| 68 |
+
MMVQ_PARAMETERS_RDNA2,
|
| 69 |
+
MMVQ_PARAMETERS_RDNA3_0,
|
| 70 |
+
MMVQ_PARAMETERS_RDNA4
|
| 71 |
+
};
|
| 72 |
+
|
| 73 |
+
static constexpr __device__ mmvq_parameter_table_id get_device_table_id() {
|
| 74 |
+
#if defined(RDNA4)
|
| 75 |
+
return MMVQ_PARAMETERS_RDNA4;
|
| 76 |
+
#elif defined(RDNA3_0)
|
| 77 |
+
return MMVQ_PARAMETERS_RDNA3_0;
|
| 78 |
+
#elif defined(RDNA2) || defined(RDNA3_5)
|
| 79 |
+
return MMVQ_PARAMETERS_RDNA2;
|
| 80 |
+
#elif defined(GCN) || defined(CDNA)
|
| 81 |
+
return MMVQ_PARAMETERS_GCN;
|
| 82 |
+
#elif defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= GGML_CUDA_CC_TURING && __CUDA_ARCH__ < GGML_CUDA_CC_AMPERE
|
| 83 |
+
return MMVQ_PARAMETERS_TURING;
|
| 84 |
+
#else
|
| 85 |
+
return MMVQ_PARAMETERS_GENERIC;
|
| 86 |
+
#endif
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
static __host__ mmvq_parameter_table_id get_device_table_id(int cc) {
|
| 90 |
+
if (GGML_CUDA_CC_IS_RDNA4(cc)) {
|
| 91 |
+
return MMVQ_PARAMETERS_RDNA4;
|
| 92 |
+
}
|
| 93 |
+
if (GGML_CUDA_CC_IS_RDNA3_0(cc)) {
|
| 94 |
+
return MMVQ_PARAMETERS_RDNA3_0;
|
| 95 |
+
}
|
| 96 |
+
if (GGML_CUDA_CC_IS_RDNA2(cc) || GGML_CUDA_CC_IS_RDNA3_5(cc)) {
|
| 97 |
+
return MMVQ_PARAMETERS_RDNA2;
|
| 98 |
+
}
|
| 99 |
+
if (GGML_CUDA_CC_IS_GCN(cc) || GGML_CUDA_CC_IS_CDNA(cc)) {
|
| 100 |
+
return MMVQ_PARAMETERS_GCN;
|
| 101 |
+
}
|
| 102 |
+
if (GGML_CUDA_CC_IS_NVIDIA(cc) && ggml_cuda_highest_compiled_arch(cc) >= GGML_CUDA_CC_TURING && ggml_cuda_highest_compiled_arch(cc) < GGML_CUDA_CC_AMPERE) {
|
| 103 |
+
return MMVQ_PARAMETERS_TURING;
|
| 104 |
+
}
|
| 105 |
+
return MMVQ_PARAMETERS_GENERIC;
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
// Per-architecture maximum batch size for which MMVQ should be used for MUL_MAT_ID.
|
| 109 |
+
// Returns a value <= MMVQ_MAX_BATCH_SIZE. Default is MMVQ_MAX_BATCH_SIZE.
|
| 110 |
+
// Check https://github.com/ggml-org/llama.cpp/pull/20905#issuecomment-4145835627 for details
|
| 111 |
+
|
| 112 |
+
static constexpr __host__ __device__ int get_mmvq_mmid_max_batch_pascal_older(ggml_type type) {
|
| 113 |
+
switch (type) {
|
| 114 |
+
case GGML_TYPE_IQ1_S: return 6;
|
| 115 |
+
case GGML_TYPE_IQ1_M: return 6;
|
| 116 |
+
case GGML_TYPE_IQ2_S: return 4;
|
| 117 |
+
case GGML_TYPE_IQ2_XS: return 5;
|
| 118 |
+
case GGML_TYPE_IQ2_XXS: return 5;
|
| 119 |
+
case GGML_TYPE_IQ3_S: return 4;
|
| 120 |
+
case GGML_TYPE_IQ3_XXS: return 4;
|
| 121 |
+
case GGML_TYPE_IQ4_NL: return 6;
|
| 122 |
+
case GGML_TYPE_IQ4_XS: return 5;
|
| 123 |
+
case GGML_TYPE_MXFP4: return 4;
|
| 124 |
+
case GGML_TYPE_NVFP4: return 4;
|
| 125 |
+
case GGML_TYPE_Q2_K: return 4;
|
| 126 |
+
case GGML_TYPE_Q3_K: return 4;
|
| 127 |
+
case GGML_TYPE_Q4_0: return 6;
|
| 128 |
+
case GGML_TYPE_Q4_1: return 6;
|
| 129 |
+
case GGML_TYPE_Q4_K: return 5;
|
| 130 |
+
case GGML_TYPE_Q5_0: return 6;
|
| 131 |
+
case GGML_TYPE_Q5_1: return 6;
|
| 132 |
+
case GGML_TYPE_Q5_K: return 5;
|
| 133 |
+
case GGML_TYPE_Q6_K: return 4;
|
| 134 |
+
case GGML_TYPE_Q8_0: return 4;
|
| 135 |
+
default: return MMVQ_MAX_BATCH_SIZE;
|
| 136 |
+
}
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
static constexpr __host__ __device__ int get_mmvq_mmid_max_batch_turing_plus(ggml_type type) {
|
| 140 |
+
switch (type) {
|
| 141 |
+
case GGML_TYPE_IQ2_S: return 7;
|
| 142 |
+
case GGML_TYPE_IQ3_S: return 6;
|
| 143 |
+
case GGML_TYPE_IQ3_XXS: return 7;
|
| 144 |
+
case GGML_TYPE_MXFP4: return 7;
|
| 145 |
+
case GGML_TYPE_NVFP4: return 8;
|
| 146 |
+
case GGML_TYPE_Q2_K: return 7;
|
| 147 |
+
case GGML_TYPE_Q3_K: return 5;
|
| 148 |
+
default: return MMVQ_MAX_BATCH_SIZE;
|
| 149 |
+
}
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
static constexpr __host__ __device__ int get_mmvq_mmid_max_batch_gcn(ggml_type type) {
|
| 153 |
+
switch (type) {
|
| 154 |
+
case GGML_TYPE_IQ1_S: return 5;
|
| 155 |
+
case GGML_TYPE_IQ1_M: return 5;
|
| 156 |
+
case GGML_TYPE_IQ2_S: return 4;
|
| 157 |
+
case GGML_TYPE_IQ2_XS: return 4;
|
| 158 |
+
case GGML_TYPE_IQ2_XXS: return 4;
|
| 159 |
+
case GGML_TYPE_IQ3_S: return 4;
|
| 160 |
+
case GGML_TYPE_IQ3_XXS: return 4;
|
| 161 |
+
case GGML_TYPE_IQ4_NL: return 6;
|
| 162 |
+
case GGML_TYPE_IQ4_XS: return 4;
|
| 163 |
+
case GGML_TYPE_Q2_K: return 4;
|
| 164 |
+
case GGML_TYPE_Q3_K: return 4;
|
| 165 |
+
case GGML_TYPE_Q4_0: return 5;
|
| 166 |
+
case GGML_TYPE_Q4_1: return 5;
|
| 167 |
+
case GGML_TYPE_Q4_K: return 4;
|
| 168 |
+
case GGML_TYPE_Q5_K: return 4;
|
| 169 |
+
case GGML_TYPE_Q6_K: return 4;
|
| 170 |
+
case GGML_TYPE_Q8_0: return 4;
|
| 171 |
+
default: return MMVQ_MAX_BATCH_SIZE;
|
| 172 |
+
}
|
| 173 |
+
}
|
| 174 |
+
|
| 175 |
+
static constexpr __host__ __device__ int get_mmvq_mmid_max_batch_cdna(ggml_type type) {
|
| 176 |
+
switch (type) {
|
| 177 |
+
case GGML_TYPE_IQ2_S: return 5;
|
| 178 |
+
case GGML_TYPE_IQ2_XS: return 5;
|
| 179 |
+
case GGML_TYPE_IQ2_XXS: return 5;
|
| 180 |
+
case GGML_TYPE_IQ3_S: return 4;
|
| 181 |
+
case GGML_TYPE_IQ3_XXS: return 5;
|
| 182 |
+
default: return MMVQ_MAX_BATCH_SIZE;
|
| 183 |
+
}
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
static constexpr __host__ __device__ int get_mmvq_mmid_max_batch_rdna1_rdna2(ggml_type type) {
|
| 187 |
+
switch (type) {
|
| 188 |
+
case GGML_TYPE_IQ2_S: return 4;
|
| 189 |
+
case GGML_TYPE_IQ2_XS: return 4;
|
| 190 |
+
case GGML_TYPE_IQ2_XXS: return 4;
|
| 191 |
+
case GGML_TYPE_IQ3_S: return 4;
|
| 192 |
+
case GGML_TYPE_IQ3_XXS: return 4;
|
| 193 |
+
case GGML_TYPE_Q2_K: return 7;
|
| 194 |
+
case GGML_TYPE_Q3_K: return 4;
|
| 195 |
+
case GGML_TYPE_Q4_K: return 5;
|
| 196 |
+
case GGML_TYPE_Q5_K: return 6;
|
| 197 |
+
case GGML_TYPE_Q6_K: return 5;
|
| 198 |
+
default: return MMVQ_MAX_BATCH_SIZE;
|
| 199 |
+
}
|
| 200 |
+
}
|
| 201 |
+
|
| 202 |
+
static constexpr __host__ __device__ int get_mmvq_mmid_max_batch_rdna3(ggml_type type) {
|
| 203 |
+
switch (type) {
|
| 204 |
+
case GGML_TYPE_IQ1_S: return 6;
|
| 205 |
+
case GGML_TYPE_IQ1_M: return 6;
|
| 206 |
+
case GGML_TYPE_IQ2_S: return 4;
|
| 207 |
+
case GGML_TYPE_IQ2_XS: return 4;
|
| 208 |
+
case GGML_TYPE_IQ2_XXS: return 4;
|
| 209 |
+
case GGML_TYPE_IQ3_S: return 4;
|
| 210 |
+
case GGML_TYPE_IQ3_XXS: return 4;
|
| 211 |
+
case GGML_TYPE_IQ4_NL: return 6;
|
| 212 |
+
case GGML_TYPE_IQ4_XS: return 6;
|
| 213 |
+
case GGML_TYPE_Q4_K: return 4;
|
| 214 |
+
case GGML_TYPE_Q5_K: return 4;
|
| 215 |
+
case GGML_TYPE_Q6_K: return 4;
|
| 216 |
+
default: return MMVQ_MAX_BATCH_SIZE;
|
| 217 |
+
}
|
| 218 |
+
}
|
| 219 |
+
|
| 220 |
+
static constexpr __host__ __device__ int get_mmvq_mmid_max_batch_rdna4(ggml_type type) {
|
| 221 |
+
switch (type) {
|
| 222 |
+
case GGML_TYPE_IQ1_S: return 7;
|
| 223 |
+
case GGML_TYPE_IQ1_M: return 7;
|
| 224 |
+
case GGML_TYPE_IQ2_S: return 4;
|
| 225 |
+
case GGML_TYPE_IQ2_XS: return 4;
|
| 226 |
+
case GGML_TYPE_IQ2_XXS: return 4;
|
| 227 |
+
case GGML_TYPE_IQ3_S: return 4;
|
| 228 |
+
case GGML_TYPE_IQ3_XXS: return 4;
|
| 229 |
+
case GGML_TYPE_IQ4_NL: return 7;
|
| 230 |
+
case GGML_TYPE_IQ4_XS: return 5;
|
| 231 |
+
case GGML_TYPE_MXFP4: return 5;
|
| 232 |
+
case GGML_TYPE_NVFP4: return 5;
|
| 233 |
+
case GGML_TYPE_Q3_K: return 4;
|
| 234 |
+
case GGML_TYPE_Q4_0: return 7;
|
| 235 |
+
case GGML_TYPE_Q4_1: return 7;
|
| 236 |
+
case GGML_TYPE_Q4_K: return 4;
|
| 237 |
+
case GGML_TYPE_Q5_0: return 7;
|
| 238 |
+
case GGML_TYPE_Q5_1: return 7;
|
| 239 |
+
case GGML_TYPE_Q5_K: return 5;
|
| 240 |
+
case GGML_TYPE_Q6_K: return 5;
|
| 241 |
+
case GGML_TYPE_Q8_0: return 7;
|
| 242 |
+
default: return MMVQ_MAX_BATCH_SIZE;
|
| 243 |
+
}
|
| 244 |
+
}
|
| 245 |
+
|
| 246 |
+
// Host function: returns the max batch size for the current arch+type at runtime.
|
| 247 |
+
int get_mmvq_mmid_max_batch(ggml_type type, int cc) {
|
| 248 |
+
// NVIDIA: Volta, Ada Lovelace, and Blackwell always use MMVQ for MUL_MAT_ID.
|
| 249 |
+
if (GGML_CUDA_CC_IS_NVIDIA(cc)) {
|
| 250 |
+
if (cc == GGML_CUDA_CC_VOLTA || cc >= GGML_CUDA_CC_ADA_LOVELACE) {
|
| 251 |
+
return MMVQ_MAX_BATCH_SIZE;
|
| 252 |
+
}
|
| 253 |
+
if (cc >= GGML_CUDA_CC_TURING) {
|
| 254 |
+
return get_mmvq_mmid_max_batch_turing_plus(type);
|
| 255 |
+
}
|
| 256 |
+
return get_mmvq_mmid_max_batch_pascal_older(type);
|
| 257 |
+
}
|
| 258 |
+
|
| 259 |
+
// AMD
|
| 260 |
+
if (GGML_CUDA_CC_IS_AMD(cc)) {
|
| 261 |
+
if (GGML_CUDA_CC_IS_RDNA4(cc)) {
|
| 262 |
+
return get_mmvq_mmid_max_batch_rdna4(type);
|
| 263 |
+
}
|
| 264 |
+
if (GGML_CUDA_CC_IS_RDNA3(cc)) {
|
| 265 |
+
return get_mmvq_mmid_max_batch_rdna3(type);
|
| 266 |
+
}
|
| 267 |
+
if (GGML_CUDA_CC_IS_RDNA1(cc) || GGML_CUDA_CC_IS_RDNA2(cc)) {
|
| 268 |
+
return get_mmvq_mmid_max_batch_rdna1_rdna2(type);
|
| 269 |
+
}
|
| 270 |
+
if (GGML_CUDA_CC_IS_CDNA(cc)) {
|
| 271 |
+
return get_mmvq_mmid_max_batch_cdna(type);
|
| 272 |
+
}
|
| 273 |
+
if (GGML_CUDA_CC_IS_GCN(cc)) {
|
| 274 |
+
return get_mmvq_mmid_max_batch_gcn(type);
|
| 275 |
+
}
|
| 276 |
+
}
|
| 277 |
+
return MMVQ_MAX_BATCH_SIZE;
|
| 278 |
+
}
|
| 279 |
+
|
| 280 |
+
bool ggml_cuda_should_use_mmvq(enum ggml_type type, int cc, int64_t ne11) {
|
| 281 |
+
if (!ggml_is_quantized(type)) {
|
| 282 |
+
return false;
|
| 283 |
+
}
|
| 284 |
+
if (GGML_CUDA_CC_IS_CDNA(cc)) {
|
| 285 |
+
if (GGML_CUDA_CC_IS_CDNA1(cc)) {
|
| 286 |
+
switch (type) {
|
| 287 |
+
case GGML_TYPE_Q4_0:
|
| 288 |
+
case GGML_TYPE_Q4_1:
|
| 289 |
+
return ne11 <= 7;
|
| 290 |
+
case GGML_TYPE_Q5_1:
|
| 291 |
+
return ne11 <= 7;
|
| 292 |
+
case GGML_TYPE_Q8_0:
|
| 293 |
+
return ne11 <= 6;
|
| 294 |
+
case GGML_TYPE_Q2_K:
|
| 295 |
+
return ne11 <= 4;
|
| 296 |
+
case GGML_TYPE_Q3_K:
|
| 297 |
+
return ne11 <= 3;
|
| 298 |
+
case GGML_TYPE_Q4_K:
|
| 299 |
+
return ne11 <= 2;
|
| 300 |
+
case GGML_TYPE_Q5_K:
|
| 301 |
+
return ne11 <= 3;
|
| 302 |
+
case GGML_TYPE_Q6_K:
|
| 303 |
+
return ne11 <= 4;
|
| 304 |
+
case GGML_TYPE_IQ1_S:
|
| 305 |
+
return ne11 <= 5;
|
| 306 |
+
case GGML_TYPE_IQ2_XXS:
|
| 307 |
+
case GGML_TYPE_IQ3_S:
|
| 308 |
+
case GGML_TYPE_IQ4_XS:
|
| 309 |
+
return ne11 <= 6;
|
| 310 |
+
default:
|
| 311 |
+
return ne11 <= MMVQ_MAX_BATCH_SIZE;
|
| 312 |
+
}
|
| 313 |
+
}
|
| 314 |
+
switch (type) { // tuned for CDNA2
|
| 315 |
+
case GGML_TYPE_Q2_K:
|
| 316 |
+
return ne11 <= 5;
|
| 317 |
+
case GGML_TYPE_Q3_K:
|
| 318 |
+
case GGML_TYPE_Q4_K:
|
| 319 |
+
case GGML_TYPE_Q5_K:
|
| 320 |
+
return ne11 <= 3;
|
| 321 |
+
case GGML_TYPE_Q6_K:
|
| 322 |
+
return ne11 <= 5;
|
| 323 |
+
default:
|
| 324 |
+
return ne11 <= MMVQ_MAX_BATCH_SIZE;
|
| 325 |
+
}
|
| 326 |
+
}
|
| 327 |
+
return ne11 <= MMVQ_MAX_BATCH_SIZE;
|
| 328 |
+
}
|
| 329 |
+
|
| 330 |
+
// Device constexpr: returns the max batch size for the current arch+type at compile time.
|
| 331 |
+
template <ggml_type type>
|
| 332 |
+
static constexpr __device__ int get_mmvq_mmid_max_batch_for_device() {
|
| 333 |
+
#if defined(RDNA4)
|
| 334 |
+
return get_mmvq_mmid_max_batch_rdna4(type);
|
| 335 |
+
#elif defined(RDNA3)
|
| 336 |
+
return get_mmvq_mmid_max_batch_rdna3(type);
|
| 337 |
+
#elif defined(RDNA2) || defined(RDNA1)
|
| 338 |
+
return get_mmvq_mmid_max_batch_rdna1_rdna2(type);
|
| 339 |
+
#elif defined(CDNA)
|
| 340 |
+
return get_mmvq_mmid_max_batch_cdna(type);
|
| 341 |
+
#elif defined(GCN)
|
| 342 |
+
return get_mmvq_mmid_max_batch_gcn(type);
|
| 343 |
+
#elif defined(__CUDA_ARCH__) && (__CUDA_ARCH__ == GGML_CUDA_CC_VOLTA || __CUDA_ARCH__ >= GGML_CUDA_CC_ADA_LOVELACE)
|
| 344 |
+
return MMVQ_MAX_BATCH_SIZE;
|
| 345 |
+
#elif defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= GGML_CUDA_CC_TURING
|
| 346 |
+
return get_mmvq_mmid_max_batch_turing_plus(type);
|
| 347 |
+
#else
|
| 348 |
+
return get_mmvq_mmid_max_batch_pascal_older(type);
|
| 349 |
+
#endif
|
| 350 |
+
}
|
| 351 |
+
|
| 352 |
+
static constexpr __host__ __device__ int calc_nwarps(ggml_type type, int ncols_dst, mmvq_parameter_table_id table_id) {
|
| 353 |
+
if (table_id == MMVQ_PARAMETERS_GENERIC) {
|
| 354 |
+
switch (ncols_dst) {
|
| 355 |
+
case 1:
|
| 356 |
+
case 2:
|
| 357 |
+
case 3:
|
| 358 |
+
case 4:
|
| 359 |
+
return 4;
|
| 360 |
+
case 5:
|
| 361 |
+
case 6:
|
| 362 |
+
case 7:
|
| 363 |
+
case 8:
|
| 364 |
+
return 2;
|
| 365 |
+
default:
|
| 366 |
+
return 1;
|
| 367 |
+
}
|
| 368 |
+
} else if (table_id == MMVQ_PARAMETERS_GCN) {
|
| 369 |
+
switch (ncols_dst) {
|
| 370 |
+
case 1:
|
| 371 |
+
case 2:
|
| 372 |
+
case 3:
|
| 373 |
+
case 4:
|
| 374 |
+
return 2;
|
| 375 |
+
case 5:
|
| 376 |
+
case 6:
|
| 377 |
+
case 7:
|
| 378 |
+
case 8:
|
| 379 |
+
default:
|
| 380 |
+
return 1;
|
| 381 |
+
}
|
| 382 |
+
}
|
| 383 |
+
if (table_id == MMVQ_PARAMETERS_RDNA4) {
|
| 384 |
+
// nwarps=8 benefits types with simple vec_dot on RDNA4 (ncols_dst=1).
|
| 385 |
+
// Types with complex vec_dot (Q3_K, IQ2_*, IQ3_*) regress due to register
|
| 386 |
+
// pressure and lookup table contention at higher thread counts.
|
| 387 |
+
if (ncols_dst == 1) {
|
| 388 |
+
switch (type) {
|
| 389 |
+
case GGML_TYPE_Q4_0:
|
| 390 |
+
case GGML_TYPE_Q4_1:
|
| 391 |
+
case GGML_TYPE_Q5_0:
|
| 392 |
+
case GGML_TYPE_Q5_1:
|
| 393 |
+
case GGML_TYPE_Q8_0:
|
| 394 |
+
case GGML_TYPE_Q2_K:
|
| 395 |
+
case GGML_TYPE_Q4_K:
|
| 396 |
+
case GGML_TYPE_Q5_K:
|
| 397 |
+
case GGML_TYPE_Q6_K:
|
| 398 |
+
case GGML_TYPE_IQ4_NL:
|
| 399 |
+
case GGML_TYPE_IQ4_XS:
|
| 400 |
+
return 8;
|
| 401 |
+
default:
|
| 402 |
+
return 1;
|
| 403 |
+
}
|
| 404 |
+
}
|
| 405 |
+
return 1;
|
| 406 |
+
}
|
| 407 |
+
if (table_id == MMVQ_PARAMETERS_RDNA3_0) {
|
| 408 |
+
// RDNA3 (W7900): stricter whitelist than RDNA4.
|
| 409 |
+
// Q2_K / Q5_K / IQ4_XS regress in full quant sweeps.
|
| 410 |
+
if (ncols_dst == 1) {
|
| 411 |
+
switch (type) {
|
| 412 |
+
case GGML_TYPE_Q4_0:
|
| 413 |
+
case GGML_TYPE_Q4_1:
|
| 414 |
+
case GGML_TYPE_Q5_0:
|
| 415 |
+
case GGML_TYPE_Q5_1:
|
| 416 |
+
case GGML_TYPE_Q8_0:
|
| 417 |
+
return 8;
|
| 418 |
+
case GGML_TYPE_Q6_K:
|
| 419 |
+
return 2;
|
| 420 |
+
case GGML_TYPE_IQ4_NL:
|
| 421 |
+
return 8;
|
| 422 |
+
default:
|
| 423 |
+
return 1;
|
| 424 |
+
}
|
| 425 |
+
}
|
| 426 |
+
return 1;
|
| 427 |
+
}
|
| 428 |
+
if (table_id == MMVQ_PARAMETERS_TURING) {
|
| 429 |
+
if (ncols_dst == 1) {
|
| 430 |
+
switch (type) {
|
| 431 |
+
case GGML_TYPE_Q2_K:
|
| 432 |
+
case GGML_TYPE_Q3_K:
|
| 433 |
+
case GGML_TYPE_Q4_K:
|
| 434 |
+
case GGML_TYPE_Q5_K:
|
| 435 |
+
case GGML_TYPE_Q6_K:
|
| 436 |
+
return 2;
|
| 437 |
+
default:
|
| 438 |
+
return 4;
|
| 439 |
+
}
|
| 440 |
+
}
|
| 441 |
+
switch (ncols_dst) {
|
| 442 |
+
case 2:
|
| 443 |
+
case 3:
|
| 444 |
+
case 4:
|
| 445 |
+
return 4;
|
| 446 |
+
case 5:
|
| 447 |
+
case 6:
|
| 448 |
+
case 7:
|
| 449 |
+
case 8:
|
| 450 |
+
return 2;
|
| 451 |
+
default:
|
| 452 |
+
return 1;
|
| 453 |
+
}
|
| 454 |
+
}
|
| 455 |
+
return 1;
|
| 456 |
+
}
|
| 457 |
+
|
| 458 |
+
static constexpr __host__ __device__ int calc_rows_per_block(int ncols_dst, int table_id, bool small_k = false, int nwarps = 1) {
|
| 459 |
+
if (table_id == MMVQ_PARAMETERS_GENERIC || table_id == MMVQ_PARAMETERS_GCN || table_id == MMVQ_PARAMETERS_TURING) {
|
| 460 |
+
switch (ncols_dst) {
|
| 461 |
+
case 1:
|
| 462 |
+
return small_k ? nwarps : 1;
|
| 463 |
+
case 2:
|
| 464 |
+
case 3:
|
| 465 |
+
case 4:
|
| 466 |
+
case 5:
|
| 467 |
+
case 6:
|
| 468 |
+
case 7:
|
| 469 |
+
case 8:
|
| 470 |
+
return 2;
|
| 471 |
+
default:
|
| 472 |
+
return 1;
|
| 473 |
+
}
|
| 474 |
+
}
|
| 475 |
+
return 1;
|
| 476 |
+
}
|
| 477 |
+
|
| 478 |
+
template <ggml_type type, int ncols_dst, bool has_fusion, bool small_k = false>
|
| 479 |
+
__launch_bounds__(calc_nwarps(type, ncols_dst, get_device_table_id())*ggml_cuda_get_physical_warp_size(), 1)
|
| 480 |
+
static __global__ void mul_mat_vec_q(
|
| 481 |
+
const void * vx_ptr, const void * vy_ptr, const int32_t * ids_ptr, const ggml_cuda_mm_fusion_args_device fusion, float * dst_ptr,
|
| 482 |
+
const uint32_t ncols_x, const uint3 nchannels_y, const uint32_t stride_row_x, const uint32_t stride_col_y,
|
| 483 |
+
const uint32_t stride_col_dst, const uint3 channel_ratio, const uint32_t stride_channel_x,
|
| 484 |
+
const uint32_t stride_channel_y, const uint32_t stride_channel_dst, const uint3 sample_ratio,
|
| 485 |
+
const uint32_t stride_sample_x, const uint32_t stride_sample_y, const uint32_t stride_sample_dst,
|
| 486 |
+
const uint32_t ids_stride) {
|
| 487 |
+
const void * GGML_CUDA_RESTRICT vx = vx_ptr;
|
| 488 |
+
const void * GGML_CUDA_RESTRICT vy = vy_ptr;
|
| 489 |
+
const int32_t * GGML_CUDA_RESTRICT ids = ids_ptr;
|
| 490 |
+
float * GGML_CUDA_RESTRICT dst = dst_ptr;
|
| 491 |
+
|
| 492 |
+
constexpr int qk = ggml_cuda_type_traits<type>::qk;
|
| 493 |
+
constexpr int qi = ggml_cuda_type_traits<type>::qi;
|
| 494 |
+
constexpr int vdr = get_vdr_mmvq(type);
|
| 495 |
+
constexpr mmvq_parameter_table_id table_id = get_device_table_id();
|
| 496 |
+
constexpr int nwarps = calc_nwarps(type, ncols_dst, table_id);
|
| 497 |
+
constexpr int rows_per_cuda_block = calc_rows_per_block(ncols_dst, table_id, small_k, nwarps);
|
| 498 |
+
constexpr int warp_size = ggml_cuda_get_physical_warp_size();
|
| 499 |
+
|
| 500 |
+
constexpr vec_dot_q_cuda_t vec_dot_q_cuda = get_vec_dot_q_cuda(type);
|
| 501 |
+
|
| 502 |
+
const int tid = warp_size*threadIdx.y + threadIdx.x;
|
| 503 |
+
const int row0 = rows_per_cuda_block*blockIdx.x;
|
| 504 |
+
const int blocks_per_row_x = ncols_x / qk;
|
| 505 |
+
constexpr int blocks_per_iter = vdr * nwarps*warp_size / qi;
|
| 506 |
+
|
| 507 |
+
const uint32_t channel_dst = blockIdx.y;
|
| 508 |
+
|
| 509 |
+
uint32_t channel_x;
|
| 510 |
+
uint32_t channel_y;
|
| 511 |
+
uint32_t sample_dst;
|
| 512 |
+
|
| 513 |
+
ggml_cuda_pdl_sync();
|
| 514 |
+
channel_x = ncols_dst == 1 && ids ? ids[channel_dst] : fastdiv(channel_dst, channel_ratio);
|
| 515 |
+
channel_y = ncols_dst == 1 && ids ? fastmodulo(channel_dst, nchannels_y) : channel_dst;
|
| 516 |
+
sample_dst = blockIdx.z;
|
| 517 |
+
|
| 518 |
+
const uint32_t sample_x = fastdiv(sample_dst, sample_ratio);
|
| 519 |
+
const uint32_t sample_y = sample_dst;
|
| 520 |
+
|
| 521 |
+
bool use_gate = false;
|
| 522 |
+
bool use_bias = false;
|
| 523 |
+
bool use_gate_bias = false;
|
| 524 |
+
bool use_scale = false;
|
| 525 |
+
bool use_gate_scale = false;
|
| 526 |
+
[[maybe_unused]] const void * vgate = nullptr;
|
| 527 |
+
const float * x_bias = nullptr;
|
| 528 |
+
const float * gate_bias = nullptr;
|
| 529 |
+
const float * x_scale = nullptr;
|
| 530 |
+
const float * gate_scale = nullptr;
|
| 531 |
+
ggml_glu_op active_glu;
|
| 532 |
+
|
| 533 |
+
if constexpr (has_fusion) {
|
| 534 |
+
use_gate = fusion.gate != nullptr;
|
| 535 |
+
use_bias = fusion.x_bias != nullptr;
|
| 536 |
+
use_gate_bias = fusion.gate_bias != nullptr && use_gate;
|
| 537 |
+
vgate = fusion.gate;
|
| 538 |
+
x_bias = (const float *) fusion.x_bias;
|
| 539 |
+
gate_bias = (const float *) fusion.gate_bias;
|
| 540 |
+
active_glu = fusion.glu_op;
|
| 541 |
+
if constexpr (type == GGML_TYPE_NVFP4) {
|
| 542 |
+
use_scale = fusion.x_scale != nullptr;
|
| 543 |
+
use_gate_scale = fusion.gate_scale != nullptr && use_gate;
|
| 544 |
+
x_scale = (const float *) fusion.x_scale;
|
| 545 |
+
gate_scale = (const float *) fusion.gate_scale;
|
| 546 |
+
}
|
| 547 |
+
}
|
| 548 |
+
|
| 549 |
+
|
| 550 |
+
[[maybe_unused]] float x_biases[ncols_dst] = { 0.0f };
|
| 551 |
+
[[maybe_unused]] float gate_biases[ncols_dst] = { 0.0f };
|
| 552 |
+
[[maybe_unused]] float x_scales = 1.0f;
|
| 553 |
+
[[maybe_unused]] float gate_scales = 1.0f;
|
| 554 |
+
if constexpr (has_fusion) {
|
| 555 |
+
// 1. Hide latency by prefetching bias, gates and scales here
|
| 556 |
+
// 2. load only on threads that won't die after partial sum calculation
|
| 557 |
+
const uint32_t channel_bias = ids ? channel_x : channel_dst;
|
| 558 |
+
if (threadIdx.x < rows_per_cuda_block && threadIdx.y == 0 &&
|
| 559 |
+
(rows_per_cuda_block == 1 || uint32_t(row0 + threadIdx.x) < stride_col_dst)) {
|
| 560 |
+
if (use_bias) {
|
| 561 |
+
x_bias = x_bias + sample_dst * stride_sample_dst + channel_bias * stride_channel_dst + row0;
|
| 562 |
+
#pragma unroll
|
| 563 |
+
for (int j = 0; j < ncols_dst; ++j) {
|
| 564 |
+
x_biases[j] = x_bias[j * stride_col_dst + threadIdx.x];
|
| 565 |
+
}
|
| 566 |
+
}
|
| 567 |
+
if (use_gate_bias) {
|
| 568 |
+
gate_bias = gate_bias + sample_dst * stride_sample_dst + channel_bias * stride_channel_dst + row0;
|
| 569 |
+
#pragma unroll
|
| 570 |
+
for (int j = 0; j < ncols_dst; ++j) {
|
| 571 |
+
gate_biases[j] = gate_bias[j * stride_col_dst + threadIdx.x];
|
| 572 |
+
}
|
| 573 |
+
}
|
| 574 |
+
if constexpr (type == GGML_TYPE_NVFP4) {
|
| 575 |
+
if (use_scale) {
|
| 576 |
+
x_scales = x_scale[ids ? channel_x : 0];
|
| 577 |
+
}
|
| 578 |
+
if (use_gate_scale) {
|
| 579 |
+
gate_scales = gate_scale[ids ? channel_x : 0];
|
| 580 |
+
}
|
| 581 |
+
}
|
| 582 |
+
}
|
| 583 |
+
}
|
| 584 |
+
|
| 585 |
+
// partial sum for each thread
|
| 586 |
+
float tmp[ncols_dst][rows_per_cuda_block] = {{0.0f}};
|
| 587 |
+
float tmp_gate[ncols_dst][rows_per_cuda_block] = {{0.0f}};
|
| 588 |
+
|
| 589 |
+
const block_q8_1 * y = ((const block_q8_1 *) vy) + sample_y*stride_sample_y + channel_y*stride_channel_y;
|
| 590 |
+
const int kbx_offset = sample_x*stride_sample_x + channel_x*stride_channel_x + row0*stride_row_x;
|
| 591 |
+
|
| 592 |
+
for (int kbx = tid / (qi/vdr); kbx < blocks_per_row_x; kbx += blocks_per_iter) {
|
| 593 |
+
const int kby = kbx * (qk/QK8_1); // y block index that aligns with kbx
|
| 594 |
+
|
| 595 |
+
// x block quant index when casting the quants to int
|
| 596 |
+
const int kqs = vdr * (tid % (qi/vdr));
|
| 597 |
+
|
| 598 |
+
#pragma unroll
|
| 599 |
+
for (int j = 0; j < ncols_dst; ++j) {
|
| 600 |
+
#pragma unroll
|
| 601 |
+
for (int i = 0; i < rows_per_cuda_block; ++i) {
|
| 602 |
+
tmp[j][i] += vec_dot_q_cuda(
|
| 603 |
+
vx, &y[j*stride_col_y + kby], kbx_offset + i*stride_row_x + kbx, kqs);
|
| 604 |
+
if constexpr (has_fusion) {
|
| 605 |
+
if (use_gate) {
|
| 606 |
+
tmp_gate[j][i] += vec_dot_q_cuda(
|
| 607 |
+
vgate, &y[j*stride_col_y + kby], kbx_offset + i*stride_row_x + kbx, kqs);
|
| 608 |
+
}
|
| 609 |
+
}
|
| 610 |
+
}
|
| 611 |
+
}
|
| 612 |
+
}
|
| 613 |
+
|
| 614 |
+
__shared__ float tmp_shared[nwarps-1 > 0 ? nwarps-1 : 1][ncols_dst][rows_per_cuda_block][warp_size];
|
| 615 |
+
[[maybe_unused]] __shared__ float tmp_shared_gate[(has_fusion && (nwarps-1 > 0)) ? nwarps-1 : 1][ncols_dst][rows_per_cuda_block][warp_size];
|
| 616 |
+
|
| 617 |
+
if (threadIdx.y > 0) {
|
| 618 |
+
#pragma unroll
|
| 619 |
+
for (int j = 0; j < ncols_dst; ++j) {
|
| 620 |
+
#pragma unroll
|
| 621 |
+
for (int i = 0; i < rows_per_cuda_block; ++i) {
|
| 622 |
+
tmp_shared[threadIdx.y-1][j][i][threadIdx.x] = tmp[j][i];
|
| 623 |
+
if constexpr (has_fusion) {
|
| 624 |
+
if (use_gate) {
|
| 625 |
+
tmp_shared_gate[threadIdx.y-1][j][i][threadIdx.x] = tmp_gate[j][i];
|
| 626 |
+
}
|
| 627 |
+
}
|
| 628 |
+
}
|
| 629 |
+
}
|
| 630 |
+
}
|
| 631 |
+
__syncthreads();
|
| 632 |
+
if (threadIdx.y > 0) {
|
| 633 |
+
return;
|
| 634 |
+
}
|
| 635 |
+
|
| 636 |
+
dst += sample_dst*stride_sample_dst + channel_dst*stride_channel_dst + row0;
|
| 637 |
+
|
| 638 |
+
// sum up partial sums and write back result
|
| 639 |
+
#pragma unroll
|
| 640 |
+
for (int j = 0; j < ncols_dst; ++j) {
|
| 641 |
+
#pragma unroll
|
| 642 |
+
for (int i = 0; i < rows_per_cuda_block; ++i) {
|
| 643 |
+
#pragma unroll
|
| 644 |
+
for (int l = 0; l < nwarps-1; ++l) {
|
| 645 |
+
tmp[j][i] += tmp_shared[l][j][i][threadIdx.x];
|
| 646 |
+
if constexpr (has_fusion) {
|
| 647 |
+
if (use_gate) {
|
| 648 |
+
tmp_gate[j][i] += tmp_shared_gate[l][j][i][threadIdx.x];
|
| 649 |
+
}
|
| 650 |
+
}
|
| 651 |
+
}
|
| 652 |
+
tmp[j][i] = warp_reduce_sum<warp_size>(tmp[j][i]);
|
| 653 |
+
if constexpr (has_fusion) {
|
| 654 |
+
if (use_gate) {
|
| 655 |
+
tmp_gate[j][i] = warp_reduce_sum<warp_size>(tmp_gate[j][i]);
|
| 656 |
+
}
|
| 657 |
+
}
|
| 658 |
+
|
| 659 |
+
if (threadIdx.x == i && (rows_per_cuda_block == 1 || uint32_t(row0 + i) < stride_col_dst)) {
|
| 660 |
+
float result = tmp[j][i];
|
| 661 |
+
if constexpr (has_fusion) {
|
| 662 |
+
if constexpr (type == GGML_TYPE_NVFP4) {
|
| 663 |
+
result *= x_scales;
|
| 664 |
+
}
|
| 665 |
+
result += x_biases[j];
|
| 666 |
+
if (use_gate) {
|
| 667 |
+
float gate_value = tmp_gate[j][i];
|
| 668 |
+
if constexpr (type == GGML_TYPE_NVFP4) {
|
| 669 |
+
gate_value *= gate_scales;
|
| 670 |
+
}
|
| 671 |
+
gate_value += gate_biases[j];
|
| 672 |
+
switch (active_glu) {
|
| 673 |
+
case GGML_GLU_OP_SWIGLU:
|
| 674 |
+
result *= ggml_cuda_op_silu_single(gate_value);
|
| 675 |
+
break;
|
| 676 |
+
case GGML_GLU_OP_GEGLU:
|
| 677 |
+
result *= ggml_cuda_op_gelu_single(gate_value);
|
| 678 |
+
break;
|
| 679 |
+
case GGML_GLU_OP_SWIGLU_OAI:
|
| 680 |
+
result = ggml_cuda_op_swiglu_oai_single(gate_value, result);
|
| 681 |
+
break;
|
| 682 |
+
default:
|
| 683 |
+
result = result * gate_value;
|
| 684 |
+
break;
|
| 685 |
+
}
|
| 686 |
+
}
|
| 687 |
+
}
|
| 688 |
+
dst[j*stride_col_dst + i] = result;
|
| 689 |
+
}
|
| 690 |
+
}
|
| 691 |
+
}
|
| 692 |
+
|
| 693 |
+
if constexpr (!has_fusion) {
|
| 694 |
+
GGML_UNUSED_VARS(use_gate, use_bias, use_gate_bias, use_scale, use_gate_scale, active_glu, gate_bias, x_bias, x_scale, gate_scale, tmp_gate);
|
| 695 |
+
}
|
| 696 |
+
if constexpr (type != GGML_TYPE_NVFP4) {
|
| 697 |
+
GGML_UNUSED_VARS(use_scale, use_gate_scale, x_scale, gate_scale, x_scales, gate_scales);
|
| 698 |
+
}
|
| 699 |
+
}
|
| 700 |
+
|
| 701 |
+
// Dedicated MoE multi-token kernel.
|
| 702 |
+
// Grid: (ceil(nrows_x / c_rows_per_block), nchannels_dst)
|
| 703 |
+
// Block: (warp_size, ncols_dst) - each warp handles one token independently.
|
| 704 |
+
// No shared memory reduction needed since each warp works alone.
|
| 705 |
+
template <ggml_type type, int c_rows_per_block>
|
| 706 |
+
__launch_bounds__(get_mmvq_mmid_max_batch_for_device<type>()*ggml_cuda_get_physical_warp_size(), 1)
|
| 707 |
+
static __global__ void mul_mat_vec_q_moe(
|
| 708 |
+
const void * vx_ptr, const void * vy_ptr, const int32_t * ids_ptr,
|
| 709 |
+
float * dst_ptr,
|
| 710 |
+
const uint32_t ncols_x, const uint3 nchannels_y, const uint32_t nrows_x,
|
| 711 |
+
const uint32_t stride_row_x, const uint32_t stride_col_y, const uint32_t stride_col_dst,
|
| 712 |
+
const uint32_t stride_channel_x, const uint32_t stride_channel_y, const uint32_t stride_channel_dst,
|
| 713 |
+
const uint32_t ncols_dst, const uint32_t ids_stride) {
|
| 714 |
+
const void * GGML_CUDA_RESTRICT vx = vx_ptr;
|
| 715 |
+
const void * GGML_CUDA_RESTRICT vy = vy_ptr;
|
| 716 |
+
const int32_t * GGML_CUDA_RESTRICT ids = ids_ptr;
|
| 717 |
+
float * GGML_CUDA_RESTRICT dst = dst_ptr;
|
| 718 |
+
|
| 719 |
+
constexpr int qk = ggml_cuda_type_traits<type>::qk;
|
| 720 |
+
constexpr int qi = ggml_cuda_type_traits<type>::qi;
|
| 721 |
+
constexpr int vdr = get_vdr_mmvq(type);
|
| 722 |
+
constexpr int warp_size = ggml_cuda_get_physical_warp_size();
|
| 723 |
+
|
| 724 |
+
constexpr vec_dot_q_cuda_t vec_dot_q_cuda = get_vec_dot_q_cuda(type);
|
| 725 |
+
|
| 726 |
+
const uint32_t token_idx = threadIdx.y;
|
| 727 |
+
const int row0 = c_rows_per_block*blockIdx.x;
|
| 728 |
+
const int blocks_per_row_x = ncols_x / qk;
|
| 729 |
+
constexpr int blocks_per_iter = vdr * warp_size / qi;
|
| 730 |
+
|
| 731 |
+
const uint32_t channel_dst = blockIdx.y;
|
| 732 |
+
|
| 733 |
+
if (token_idx >= ncols_dst) {
|
| 734 |
+
return;
|
| 735 |
+
}
|
| 736 |
+
|
| 737 |
+
ggml_cuda_pdl_sync();
|
| 738 |
+
const uint32_t channel_x = ids[channel_dst + token_idx * ids_stride];
|
| 739 |
+
const uint32_t channel_y = fastmodulo(channel_dst, nchannels_y);
|
| 740 |
+
|
| 741 |
+
const block_q8_1 * y = ((const block_q8_1 *) vy) + channel_y*stride_channel_y + token_idx*stride_col_y;
|
| 742 |
+
const int kbx_offset = channel_x*stride_channel_x + row0*stride_row_x;
|
| 743 |
+
|
| 744 |
+
// partial sum for each thread
|
| 745 |
+
float tmp[c_rows_per_block] = {0.0f};
|
| 746 |
+
|
| 747 |
+
for (int kbx = threadIdx.x / (qi/vdr); kbx < blocks_per_row_x; kbx += blocks_per_iter) {
|
| 748 |
+
const int kby = kbx * (qk/QK8_1);
|
| 749 |
+
const int kqs = vdr * (threadIdx.x % (qi/vdr));
|
| 750 |
+
|
| 751 |
+
#pragma unroll
|
| 752 |
+
for (int i = 0; i < c_rows_per_block; ++i) {
|
| 753 |
+
tmp[i] += vec_dot_q_cuda(vx, &y[kby], kbx_offset + i*stride_row_x + kbx, kqs);
|
| 754 |
+
}
|
| 755 |
+
}
|
| 756 |
+
|
| 757 |
+
ggml_cuda_pdl_lc();
|
| 758 |
+
|
| 759 |
+
// Warp-level reduction only - no shared memory needed
|
| 760 |
+
#pragma unroll
|
| 761 |
+
for (int i = 0; i < c_rows_per_block; ++i) {
|
| 762 |
+
tmp[i] = warp_reduce_sum<warp_size>(tmp[i]);
|
| 763 |
+
}
|
| 764 |
+
|
| 765 |
+
// Write results
|
| 766 |
+
if (threadIdx.x < c_rows_per_block && (c_rows_per_block == 1 || uint32_t(row0 + threadIdx.x) < nrows_x)) {
|
| 767 |
+
dst[channel_dst*stride_channel_dst + token_idx*stride_col_dst + row0 + threadIdx.x] = tmp[threadIdx.x];
|
| 768 |
+
}
|
| 769 |
+
}
|
| 770 |
+
|
| 771 |
+
template<ggml_type type>
|
| 772 |
+
static std::pair<dim3, dim3> calc_launch_params(
|
| 773 |
+
const int ncols_dst, const int nrows_x, const int nchannels_dst, const int nsamples_or_ntokens,
|
| 774 |
+
const int warp_size, const mmvq_parameter_table_id table_id, const bool small_k = false) {
|
| 775 |
+
const int nwarps = calc_nwarps(type, ncols_dst, table_id);
|
| 776 |
+
const int rpb = calc_rows_per_block(ncols_dst, table_id, small_k, nwarps);
|
| 777 |
+
const int64_t nblocks = (nrows_x + rpb - 1) / rpb;
|
| 778 |
+
const dim3 block_nums(nblocks, nchannels_dst, nsamples_or_ntokens);
|
| 779 |
+
const dim3 block_dims(warp_size, nwarps, 1);
|
| 780 |
+
return {block_nums, block_dims};
|
| 781 |
+
}
|
| 782 |
+
|
| 783 |
+
template<ggml_type type, int c_ncols_dst, bool small_k = false>
|
| 784 |
+
static void mul_mat_vec_q_switch_fusion(
|
| 785 |
+
const void * vx, const void * vy, const int32_t * ids, const ggml_cuda_mm_fusion_args_device fusion, float * dst,
|
| 786 |
+
const uint32_t ncols_x, const uint3 nchannels_y, const uint32_t stride_row_x, const uint32_t stride_col_y,
|
| 787 |
+
const uint32_t stride_col_dst, const uint3 channel_ratio, const uint32_t stride_channel_x,
|
| 788 |
+
const uint32_t stride_channel_y, const uint32_t stride_channel_dst, const uint3 sample_ratio,
|
| 789 |
+
const uint32_t stride_sample_x, const uint32_t stride_sample_y, const uint32_t stride_sample_dst,
|
| 790 |
+
const dim3 & block_nums, const dim3 & block_dims, const int nbytes_shared,
|
| 791 |
+
const uint32_t ids_stride, cudaStream_t stream) {
|
| 792 |
+
|
| 793 |
+
const bool has_fusion = fusion.gate != nullptr || fusion.x_bias != nullptr || fusion.gate_bias != nullptr ||
|
| 794 |
+
fusion.x_scale != nullptr || fusion.gate_scale != nullptr;
|
| 795 |
+
if constexpr (c_ncols_dst == 1) {
|
| 796 |
+
if (has_fusion) {
|
| 797 |
+
const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params(block_nums, block_dims, nbytes_shared, stream);
|
| 798 |
+
ggml_cuda_kernel_launch(mul_mat_vec_q<type, c_ncols_dst, true, small_k>, launch_params,
|
| 799 |
+
vx, vy, ids, fusion, dst, ncols_x, nchannels_y, stride_row_x, stride_col_y, stride_col_dst,
|
| 800 |
+
channel_ratio, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 801 |
+
sample_ratio, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride);
|
| 802 |
+
return;
|
| 803 |
+
}
|
| 804 |
+
}
|
| 805 |
+
|
| 806 |
+
GGML_ASSERT(!has_fusion && "fusion only supported for ncols_dst=1");
|
| 807 |
+
|
| 808 |
+
const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params(block_nums, block_dims, nbytes_shared, stream);
|
| 809 |
+
ggml_cuda_kernel_launch(mul_mat_vec_q<type, c_ncols_dst, false, small_k>, launch_params,
|
| 810 |
+
vx, vy, ids, fusion, dst, ncols_x, nchannels_y, stride_row_x, stride_col_y, stride_col_dst,
|
| 811 |
+
channel_ratio, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 812 |
+
sample_ratio, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride);
|
| 813 |
+
}
|
| 814 |
+
|
| 815 |
+
template <ggml_type type>
|
| 816 |
+
static void mul_mat_vec_q_moe_launch(
|
| 817 |
+
const void * vx, const void * vy, const int32_t * ids, float * dst,
|
| 818 |
+
const uint32_t ncols_x, const uint3 nchannels_y, const uint32_t nrows_x,
|
| 819 |
+
const uint32_t stride_row_x, const uint32_t stride_col_y, const uint32_t stride_col_dst,
|
| 820 |
+
const uint32_t stride_channel_x, const uint32_t stride_channel_y, const uint32_t stride_channel_dst,
|
| 821 |
+
const uint32_t ncols_dst, const uint32_t ids_stride,
|
| 822 |
+
const int warp_size, const int nchannels_dst, cudaStream_t stream) {
|
| 823 |
+
|
| 824 |
+
constexpr int rows_per_block = 2; // 2 gives best perf based on tuning
|
| 825 |
+
const int64_t nblocks_rows = (nrows_x + rows_per_block - 1) / rows_per_block;
|
| 826 |
+
const dim3 block_nums(nblocks_rows, nchannels_dst);
|
| 827 |
+
const dim3 block_dims(warp_size, ncols_dst);
|
| 828 |
+
const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params(block_nums, block_dims, 0, stream);
|
| 829 |
+
|
| 830 |
+
ggml_cuda_kernel_launch(mul_mat_vec_q_moe<type, rows_per_block>, launch_params,
|
| 831 |
+
vx, vy, ids, dst, ncols_x, nchannels_y, nrows_x,
|
| 832 |
+
stride_row_x, stride_col_y, stride_col_dst,
|
| 833 |
+
stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 834 |
+
ncols_dst, ids_stride);
|
| 835 |
+
}
|
| 836 |
+
|
| 837 |
+
template <ggml_type type>
|
| 838 |
+
static void mul_mat_vec_q_switch_ncols_dst(
|
| 839 |
+
const void * vx, const void * vy, const int32_t * ids, const ggml_cuda_mm_fusion_args_device fusion, float * dst,
|
| 840 |
+
const int ncols_x, const int nrows_x, const int ncols_dst,
|
| 841 |
+
const int stride_row_x, const int stride_col_y, const int stride_col_dst,
|
| 842 |
+
const int nchannels_x, const int nchannels_y, const int nchannels_dst,
|
| 843 |
+
const int stride_channel_x, const int stride_channel_y, const int stride_channel_dst,
|
| 844 |
+
const int nsamples_x, const int nsamples_dst, const int stride_sample_x, const int stride_sample_y, const int stride_sample_dst,
|
| 845 |
+
const int ids_stride, cudaStream_t stream) {
|
| 846 |
+
|
| 847 |
+
GGML_ASSERT(ncols_x % ggml_blck_size(type) == 0);
|
| 848 |
+
GGML_ASSERT(ncols_dst <= MMVQ_MAX_BATCH_SIZE);
|
| 849 |
+
|
| 850 |
+
const uint3 nchannels_y_fd = ids ? init_fastdiv_values(nchannels_y) : make_uint3(0, 0, 0);
|
| 851 |
+
const uint3 channel_ratio_fd = ids ? make_uint3(0, 0, 0) : init_fastdiv_values(nchannels_dst / nchannels_x);
|
| 852 |
+
const uint3 sample_ratio_fd = init_fastdiv_values(nsamples_dst / nsamples_x);
|
| 853 |
+
|
| 854 |
+
const int device = ggml_cuda_get_device();
|
| 855 |
+
const int cc = ggml_cuda_info().devices[device].cc;
|
| 856 |
+
const int warp_size = ggml_cuda_info().devices[device].warp_size;
|
| 857 |
+
const mmvq_parameter_table_id table_id = get_device_table_id(cc);
|
| 858 |
+
|
| 859 |
+
const bool has_ids = ids != nullptr;
|
| 860 |
+
|
| 861 |
+
const auto should_use_small_k = [&](int c_ncols_dst) {
|
| 862 |
+
// When K is small, increase rows_per_block to match nwarps so each warp has more work to do
|
| 863 |
+
// Trigger when the full thread block covers all K blocks in a single loop iteration and few threads remain idle.
|
| 864 |
+
constexpr int qk = ggml_cuda_type_traits<type>::qk;
|
| 865 |
+
constexpr int qi = ggml_cuda_type_traits<type>::qi;
|
| 866 |
+
constexpr int vdr = get_vdr_mmvq(type);
|
| 867 |
+
const int blocks_per_row_x = ncols_x / qk;
|
| 868 |
+
const int blocks_per_iter_1warp = vdr * warp_size / qi;
|
| 869 |
+
const int nwarps = calc_nwarps(type, c_ncols_dst, table_id);
|
| 870 |
+
bool use = nwarps > 1 && blocks_per_row_x < nwarps * blocks_per_iter_1warp;
|
| 871 |
+
|
| 872 |
+
constexpr std::array<ggml_type, 2> iq_slow_turing = {
|
| 873 |
+
GGML_TYPE_IQ3_XXS,
|
| 874 |
+
GGML_TYPE_IQ3_S,
|
| 875 |
+
};
|
| 876 |
+
constexpr std::array<ggml_type, 8> iq_slow_other = {
|
| 877 |
+
GGML_TYPE_IQ1_S, GGML_TYPE_IQ1_M, GGML_TYPE_IQ2_XXS, GGML_TYPE_IQ2_XS,
|
| 878 |
+
GGML_TYPE_IQ2_S, GGML_TYPE_IQ3_XXS, GGML_TYPE_IQ3_S, GGML_TYPE_IQ4_XS,
|
| 879 |
+
};
|
| 880 |
+
constexpr std::array<ggml_type, 3> slow_pascal = {
|
| 881 |
+
GGML_TYPE_IQ3_S,
|
| 882 |
+
GGML_TYPE_Q2_K,
|
| 883 |
+
GGML_TYPE_Q3_K,
|
| 884 |
+
};
|
| 885 |
+
|
| 886 |
+
const bool is_nvidia_turing_plus = GGML_CUDA_CC_IS_NVIDIA(cc) && cc >= GGML_CUDA_CC_TURING;
|
| 887 |
+
const bool is_nvidia_pascal_older = GGML_CUDA_CC_IS_NVIDIA(cc) && cc < GGML_CUDA_CC_VOLTA;
|
| 888 |
+
|
| 889 |
+
if (is_nvidia_turing_plus) {
|
| 890 |
+
if (ncols_dst == 1 &&
|
| 891 |
+
std::find(iq_slow_turing.begin(), iq_slow_turing.end(), type) != iq_slow_turing.end()) {
|
| 892 |
+
use = false;
|
| 893 |
+
}
|
| 894 |
+
} else if ((ncols_dst == 1 && std::find(iq_slow_other.begin(), iq_slow_other.end(), type) != iq_slow_other.end()) ||
|
| 895 |
+
(is_nvidia_pascal_older && std::find(slow_pascal.begin(), slow_pascal.end(), type) != slow_pascal.end()) ||
|
| 896 |
+
GGML_CUDA_CC_IS_RDNA(cc)) {
|
| 897 |
+
use = false;
|
| 898 |
+
}
|
| 899 |
+
|
| 900 |
+
return use;
|
| 901 |
+
};
|
| 902 |
+
|
| 903 |
+
if (has_ids && ncols_dst > 1) {
|
| 904 |
+
// Multi-token MUL_MAT_ID path - dedicated MoE kernel
|
| 905 |
+
mul_mat_vec_q_moe_launch<type>(
|
| 906 |
+
vx, vy, ids, dst, ncols_x, nchannels_y_fd, nrows_x,
|
| 907 |
+
stride_row_x, stride_col_y, stride_col_dst,
|
| 908 |
+
stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 909 |
+
ncols_dst, ids_stride, warp_size, nchannels_dst, stream);
|
| 910 |
+
return;
|
| 911 |
+
}
|
| 912 |
+
|
| 913 |
+
switch (ncols_dst) {
|
| 914 |
+
case 1: {
|
| 915 |
+
constexpr int c_ncols_dst = 1;
|
| 916 |
+
|
| 917 |
+
bool use_small_k = should_use_small_k(c_ncols_dst);
|
| 918 |
+
|
| 919 |
+
if (use_small_k) {
|
| 920 |
+
std::pair<dim3, dim3> dims = calc_launch_params<type>(c_ncols_dst, nrows_x, nchannels_dst,
|
| 921 |
+
nsamples_dst, warp_size, table_id, true);
|
| 922 |
+
mul_mat_vec_q_switch_fusion<type, c_ncols_dst, true>(
|
| 923 |
+
vx, vy, ids, fusion, dst, ncols_x, nchannels_y_fd, stride_row_x, stride_col_y, stride_col_dst,
|
| 924 |
+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst, sample_ratio_fd,
|
| 925 |
+
stride_sample_x, stride_sample_y, stride_sample_dst, dims.first, dims.second, 0, ids_stride,
|
| 926 |
+
stream);
|
| 927 |
+
} else {
|
| 928 |
+
std::pair<dim3, dim3> dims = calc_launch_params<type>(c_ncols_dst, nrows_x, nchannels_dst,
|
| 929 |
+
nsamples_dst, warp_size, table_id);
|
| 930 |
+
mul_mat_vec_q_switch_fusion<type, c_ncols_dst>(
|
| 931 |
+
vx, vy, ids, fusion, dst, ncols_x, nchannels_y_fd, stride_row_x, stride_col_y, stride_col_dst,
|
| 932 |
+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst, sample_ratio_fd,
|
| 933 |
+
stride_sample_x, stride_sample_y, stride_sample_dst, dims.first, dims.second, 0, ids_stride,
|
| 934 |
+
stream);
|
| 935 |
+
}
|
| 936 |
+
} break;
|
| 937 |
+
case 2: {
|
| 938 |
+
constexpr int c_ncols_dst = 2;
|
| 939 |
+
std::pair<dim3, dim3> dims = calc_launch_params<type>(c_ncols_dst, nrows_x, nchannels_dst, nsamples_dst, warp_size, table_id);
|
| 940 |
+
mul_mat_vec_q_switch_fusion<type, c_ncols_dst>(vx, vy, ids, fusion, dst, ncols_x, nchannels_y_fd, stride_row_x, stride_col_y, stride_col_dst,
|
| 941 |
+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 942 |
+
sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst,
|
| 943 |
+
dims.first, dims.second, 0, ids_stride, stream);
|
| 944 |
+
} break;
|
| 945 |
+
case 3: {
|
| 946 |
+
constexpr int c_ncols_dst = 3;
|
| 947 |
+
std::pair<dim3, dim3> dims = calc_launch_params<type>(c_ncols_dst, nrows_x, nchannels_dst, nsamples_dst, warp_size, table_id);
|
| 948 |
+
mul_mat_vec_q_switch_fusion<type, c_ncols_dst>(vx, vy, ids, fusion, dst, ncols_x, nchannels_y_fd, stride_row_x, stride_col_y, stride_col_dst,
|
| 949 |
+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 950 |
+
sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst,
|
| 951 |
+
dims.first, dims.second, 0, ids_stride, stream);
|
| 952 |
+
} break;
|
| 953 |
+
case 4: {
|
| 954 |
+
constexpr int c_ncols_dst = 4;
|
| 955 |
+
std::pair<dim3, dim3> dims = calc_launch_params<type>(c_ncols_dst, nrows_x, nchannels_dst, nsamples_dst, warp_size, table_id);
|
| 956 |
+
mul_mat_vec_q_switch_fusion<type, c_ncols_dst>(vx, vy, ids, fusion, dst, ncols_x, nchannels_y_fd, stride_row_x, stride_col_y, stride_col_dst,
|
| 957 |
+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 958 |
+
sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst,
|
| 959 |
+
dims.first, dims.second, 0, ids_stride, stream);
|
| 960 |
+
} break;
|
| 961 |
+
case 5: {
|
| 962 |
+
constexpr int c_ncols_dst = 5;
|
| 963 |
+
std::pair<dim3, dim3> dims = calc_launch_params<type>(c_ncols_dst, nrows_x, nchannels_dst, nsamples_dst, warp_size, table_id);
|
| 964 |
+
mul_mat_vec_q_switch_fusion<type, c_ncols_dst>(vx, vy, ids, fusion, dst, ncols_x, nchannels_y_fd, stride_row_x, stride_col_y, stride_col_dst,
|
| 965 |
+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 966 |
+
sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst,
|
| 967 |
+
dims.first, dims.second, 0, ids_stride, stream);
|
| 968 |
+
} break;
|
| 969 |
+
case 6: {
|
| 970 |
+
constexpr int c_ncols_dst = 6;
|
| 971 |
+
std::pair<dim3, dim3> dims = calc_launch_params<type>(c_ncols_dst, nrows_x, nchannels_dst, nsamples_dst, warp_size, table_id);
|
| 972 |
+
mul_mat_vec_q_switch_fusion<type, c_ncols_dst>(vx, vy, ids, fusion, dst, ncols_x, nchannels_y_fd, stride_row_x, stride_col_y, stride_col_dst,
|
| 973 |
+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 974 |
+
sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst,
|
| 975 |
+
dims.first, dims.second, 0, ids_stride, stream);
|
| 976 |
+
} break;
|
| 977 |
+
case 7: {
|
| 978 |
+
constexpr int c_ncols_dst = 7;
|
| 979 |
+
std::pair<dim3, dim3> dims = calc_launch_params<type>(c_ncols_dst, nrows_x, nchannels_dst, nsamples_dst, warp_size, table_id);
|
| 980 |
+
mul_mat_vec_q_switch_fusion<type, c_ncols_dst>(vx, vy, ids, fusion, dst, ncols_x, nchannels_y_fd, stride_row_x, stride_col_y, stride_col_dst,
|
| 981 |
+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 982 |
+
sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst,
|
| 983 |
+
dims.first, dims.second, 0, ids_stride, stream);
|
| 984 |
+
} break;
|
| 985 |
+
case 8: {
|
| 986 |
+
constexpr int c_ncols_dst = 8;
|
| 987 |
+
std::pair<dim3, dim3> dims = calc_launch_params<type>(c_ncols_dst, nrows_x, nchannels_dst, nsamples_dst, warp_size, table_id);
|
| 988 |
+
mul_mat_vec_q_switch_fusion<type, c_ncols_dst>(vx, vy, ids, fusion, dst, ncols_x, nchannels_y_fd, stride_row_x, stride_col_y, stride_col_dst,
|
| 989 |
+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 990 |
+
sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst,
|
| 991 |
+
dims.first, dims.second, 0, ids_stride, stream);
|
| 992 |
+
} break;
|
| 993 |
+
default:
|
| 994 |
+
GGML_ABORT("fatal error");
|
| 995 |
+
break;
|
| 996 |
+
}
|
| 997 |
+
}
|
| 998 |
+
static void mul_mat_vec_q_switch_type(
|
| 999 |
+
const void * vx, const ggml_type type_x, const void * vy, const int32_t * ids, const ggml_cuda_mm_fusion_args_device fusion, float * dst,
|
| 1000 |
+
const int ncols_x, const int nrows_x, const int ncols_dst,
|
| 1001 |
+
const int stride_row_x, const int stride_col_y, const int stride_col_dst,
|
| 1002 |
+
const int nchannels_x, const int nchannels_y, const int nchannels_dst,
|
| 1003 |
+
const int stride_channel_x, const int stride_channel_y, const int stride_channel_dst,
|
| 1004 |
+
const int nsamples_x, const int nsamples_dst, const int stride_sample_x, const int stride_sample_y, const int stride_sample_dst,
|
| 1005 |
+
const int ids_stride, cudaStream_t stream) {
|
| 1006 |
+
switch (type_x) {
|
| 1007 |
+
case GGML_TYPE_Q1_0:
|
| 1008 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_Q1_0>
|
| 1009 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1010 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1011 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1012 |
+
break;
|
| 1013 |
+
case GGML_TYPE_Q4_0:
|
| 1014 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_Q4_0>
|
| 1015 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1016 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1017 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1018 |
+
break;
|
| 1019 |
+
case GGML_TYPE_Q4_1:
|
| 1020 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_Q4_1>
|
| 1021 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1022 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1023 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1024 |
+
break;
|
| 1025 |
+
case GGML_TYPE_Q5_0:
|
| 1026 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_Q5_0>
|
| 1027 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1028 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1029 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1030 |
+
break;
|
| 1031 |
+
case GGML_TYPE_Q5_1:
|
| 1032 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_Q5_1>
|
| 1033 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1034 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1035 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1036 |
+
break;
|
| 1037 |
+
case GGML_TYPE_Q8_0:
|
| 1038 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_Q8_0>
|
| 1039 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1040 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1041 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1042 |
+
break;
|
| 1043 |
+
case GGML_TYPE_MXFP4:
|
| 1044 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_MXFP4>
|
| 1045 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1046 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1047 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1048 |
+
break;
|
| 1049 |
+
case GGML_TYPE_NVFP4:
|
| 1050 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_NVFP4>
|
| 1051 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1052 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1053 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1054 |
+
break;
|
| 1055 |
+
case GGML_TYPE_Q2_K:
|
| 1056 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_Q2_K>
|
| 1057 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1058 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1059 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1060 |
+
break;
|
| 1061 |
+
case GGML_TYPE_Q3_K:
|
| 1062 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_Q3_K>
|
| 1063 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1064 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1065 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1066 |
+
break;
|
| 1067 |
+
case GGML_TYPE_Q4_K:
|
| 1068 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_Q4_K>
|
| 1069 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1070 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1071 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1072 |
+
break;
|
| 1073 |
+
case GGML_TYPE_Q5_K:
|
| 1074 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_Q5_K>
|
| 1075 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1076 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1077 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1078 |
+
break;
|
| 1079 |
+
case GGML_TYPE_Q6_K:
|
| 1080 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_Q6_K>
|
| 1081 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1082 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1083 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1084 |
+
break;
|
| 1085 |
+
case GGML_TYPE_IQ2_XXS:
|
| 1086 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_IQ2_XXS>
|
| 1087 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1088 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1089 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1090 |
+
break;
|
| 1091 |
+
case GGML_TYPE_IQ2_XS:
|
| 1092 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_IQ2_XS>
|
| 1093 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1094 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1095 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1096 |
+
break;
|
| 1097 |
+
case GGML_TYPE_IQ2_S:
|
| 1098 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_IQ2_S>
|
| 1099 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1100 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1101 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1102 |
+
break;
|
| 1103 |
+
case GGML_TYPE_IQ3_XXS:
|
| 1104 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_IQ3_XXS>
|
| 1105 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1106 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1107 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1108 |
+
break;
|
| 1109 |
+
case GGML_TYPE_IQ1_S:
|
| 1110 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_IQ1_S>
|
| 1111 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1112 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1113 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1114 |
+
break;
|
| 1115 |
+
case GGML_TYPE_IQ1_M:
|
| 1116 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_IQ1_M>
|
| 1117 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1118 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1119 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1120 |
+
break;
|
| 1121 |
+
case GGML_TYPE_IQ4_NL:
|
| 1122 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_IQ4_NL>
|
| 1123 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1124 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1125 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1126 |
+
break;
|
| 1127 |
+
case GGML_TYPE_IQ4_XS:
|
| 1128 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_IQ4_XS>
|
| 1129 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1130 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1131 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1132 |
+
break;
|
| 1133 |
+
case GGML_TYPE_IQ3_S:
|
| 1134 |
+
mul_mat_vec_q_switch_ncols_dst<GGML_TYPE_IQ3_S>
|
| 1135 |
+
(vx, vy, ids, fusion, dst, ncols_x, nrows_x, ncols_dst, stride_row_x, stride_col_y, stride_col_dst,
|
| 1136 |
+
nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst,
|
| 1137 |
+
nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream);
|
| 1138 |
+
break;
|
| 1139 |
+
default:
|
| 1140 |
+
GGML_ABORT("fatal error");
|
| 1141 |
+
break;
|
| 1142 |
+
}
|
| 1143 |
+
}
|
| 1144 |
+
|
| 1145 |
+
void ggml_cuda_mul_mat_vec_q(
|
| 1146 |
+
ggml_backend_cuda_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * ids, ggml_tensor * dst,
|
| 1147 |
+
const ggml_cuda_mm_fusion_args_host * fusion) {
|
| 1148 |
+
GGML_ASSERT( src1->type == GGML_TYPE_F32);
|
| 1149 |
+
GGML_ASSERT( dst->type == GGML_TYPE_F32);
|
| 1150 |
+
GGML_ASSERT(!ids || ids->type == GGML_TYPE_I32); // Optional, used for batched GGML_MUL_MAT_ID.
|
| 1151 |
+
|
| 1152 |
+
GGML_TENSOR_BINARY_OP_LOCALS;
|
| 1153 |
+
|
| 1154 |
+
cudaStream_t stream = ctx.stream();
|
| 1155 |
+
|
| 1156 |
+
const size_t ts_src0 = ggml_type_size(src0->type);
|
| 1157 |
+
const size_t ts_src1 = ggml_type_size(src1->type);
|
| 1158 |
+
const size_t ts_dst = ggml_type_size(dst->type);
|
| 1159 |
+
|
| 1160 |
+
GGML_ASSERT( nb00 == ts_src0);
|
| 1161 |
+
GGML_ASSERT( nb10 == ts_src1);
|
| 1162 |
+
GGML_ASSERT( nb0 == ts_dst);
|
| 1163 |
+
GGML_ASSERT(!ids || ids->nb[0] == ggml_type_size(ids->type));
|
| 1164 |
+
|
| 1165 |
+
GGML_ASSERT(!ids || ne12 <= MMVQ_MAX_BATCH_SIZE);
|
| 1166 |
+
|
| 1167 |
+
const float * src1_d = (const float *) src1->data;
|
| 1168 |
+
const int32_t * ids_d = ids ? (const int32_t *) ids->data : nullptr;
|
| 1169 |
+
float * dst_d = (float *) dst->data;
|
| 1170 |
+
|
| 1171 |
+
ggml_cuda_mm_fusion_args_device fusion_local{};
|
| 1172 |
+
|
| 1173 |
+
if (fusion) {
|
| 1174 |
+
GGML_ASSERT( !ids || dst->ne[2] == 1);
|
| 1175 |
+
GGML_ASSERT( ids || dst->ne[1] == 1);
|
| 1176 |
+
// Scale fusion is only allowed for NVFP4 currently as the cost of checking this at run-time in the prologue is
|
| 1177 |
+
// non-negligible for some models such as gpt-oss-20b
|
| 1178 |
+
GGML_ASSERT((fusion->x_scale == nullptr && fusion->gate_scale == nullptr) || src0->type == GGML_TYPE_NVFP4);
|
| 1179 |
+
|
| 1180 |
+
if (fusion->x_bias) {
|
| 1181 |
+
GGML_ASSERT(fusion->x_bias->type == GGML_TYPE_F32);
|
| 1182 |
+
GGML_ASSERT(fusion->x_bias->ne[0] == dst->ne[0]);
|
| 1183 |
+
GGML_ASSERT(!ids || fusion->x_bias->ne[1] == src0->ne[2]);
|
| 1184 |
+
fusion_local.x_bias = fusion->x_bias->data;
|
| 1185 |
+
}
|
| 1186 |
+
if (fusion->gate) {
|
| 1187 |
+
GGML_ASSERT(fusion->gate->type == src0->type && ggml_are_same_stride(fusion->gate, src0));
|
| 1188 |
+
fusion_local.gate = fusion->gate->data;
|
| 1189 |
+
}
|
| 1190 |
+
if (fusion->gate_bias) {
|
| 1191 |
+
GGML_ASSERT(fusion->gate_bias->type == GGML_TYPE_F32);
|
| 1192 |
+
GGML_ASSERT(fusion->gate_bias->ne[0] == dst->ne[0]);
|
| 1193 |
+
GGML_ASSERT(!ids || fusion->gate_bias->ne[1] == src0->ne[2]);
|
| 1194 |
+
fusion_local.gate_bias = fusion->gate_bias->data;
|
| 1195 |
+
}
|
| 1196 |
+
if (fusion->x_scale) {
|
| 1197 |
+
GGML_ASSERT(fusion->x_scale->type == GGML_TYPE_F32);
|
| 1198 |
+
GGML_ASSERT(ggml_is_contiguous(fusion->x_scale));
|
| 1199 |
+
GGML_ASSERT(ggml_nelements(fusion->x_scale) == (ids ? src0->ne[2] : 1));
|
| 1200 |
+
fusion_local.x_scale = fusion->x_scale->data;
|
| 1201 |
+
}
|
| 1202 |
+
if (fusion->gate_scale) {
|
| 1203 |
+
GGML_ASSERT(fusion->gate_scale->type == GGML_TYPE_F32);
|
| 1204 |
+
GGML_ASSERT(ggml_is_contiguous(fusion->gate_scale));
|
| 1205 |
+
GGML_ASSERT(ggml_nelements(fusion->gate_scale) == (ids ? src0->ne[2] : 1));
|
| 1206 |
+
fusion_local.gate_scale = fusion->gate_scale->data;
|
| 1207 |
+
}
|
| 1208 |
+
fusion_local.glu_op = fusion->glu_op;
|
| 1209 |
+
}
|
| 1210 |
+
|
| 1211 |
+
// If src0 is a temporary compute buffer, clear any potential padding.
|
| 1212 |
+
if (ggml_backend_buffer_get_usage(src0->buffer) == GGML_BACKEND_BUFFER_USAGE_COMPUTE) {
|
| 1213 |
+
const size_t size_data = ggml_nbytes(src0);
|
| 1214 |
+
const size_t size_alloc = ggml_backend_buffer_get_alloc_size(src0->buffer, src0);
|
| 1215 |
+
if (size_alloc > size_data) {
|
| 1216 |
+
GGML_ASSERT(ggml_is_contiguously_allocated(src0));
|
| 1217 |
+
GGML_ASSERT(!src0->view_src);
|
| 1218 |
+
CUDA_CHECK(cudaMemsetAsync((char *) src0->data + size_data, 0, size_alloc - size_data, stream));
|
| 1219 |
+
}
|
| 1220 |
+
}
|
| 1221 |
+
|
| 1222 |
+
const int64_t ne10_padded = GGML_PAD(ne10, MATRIX_ROW_PADDING);
|
| 1223 |
+
ggml_cuda_pool_alloc<char> src1_q8_1(ctx.pool(), ne13*ne12 * ne11*ne10_padded * sizeof(block_q8_1)/QK8_1);
|
| 1224 |
+
{
|
| 1225 |
+
const int64_t s11 = src1->nb[1] / ts_src1;
|
| 1226 |
+
const int64_t s12 = src1->nb[2] / ts_src1;
|
| 1227 |
+
const int64_t s13 = src1->nb[3] / ts_src1;
|
| 1228 |
+
quantize_row_q8_1_cuda(src1_d, nullptr, src1_q8_1.get(), src0->type, ne10, s11, s12, s13, ne10_padded, ne11, ne12, ne13, stream);
|
| 1229 |
+
}
|
| 1230 |
+
|
| 1231 |
+
const int64_t s01 = src0->nb[1] / ts_src0;
|
| 1232 |
+
const int64_t s11 = ne10_padded / QK8_1;
|
| 1233 |
+
const int64_t s1 = dst->nb[1] / ts_dst;
|
| 1234 |
+
const int64_t s02 = src0->nb[2] / ts_src0;
|
| 1235 |
+
const int64_t s2 = dst->nb[2] / ts_dst;
|
| 1236 |
+
const int64_t s03 = src0->nb[3] / ts_src0;
|
| 1237 |
+
const int64_t s3 = dst->nb[3] / ts_dst;
|
| 1238 |
+
|
| 1239 |
+
const int64_t s12 = ne11*s11;
|
| 1240 |
+
const int64_t s13 = ne12*s12;
|
| 1241 |
+
|
| 1242 |
+
// For MUL_MAT_ID the memory layout is different than for MUL_MAT:
|
| 1243 |
+
const int64_t ncols_dst = ids ? ne2 : ne1;
|
| 1244 |
+
const int64_t nchannels_y = ids ? ne11 : ne12;
|
| 1245 |
+
const int64_t nchannels_dst = ids ? ne1 : ne2;
|
| 1246 |
+
const int64_t stride_col_dst = ids ? s2 : s1;
|
| 1247 |
+
const int64_t stride_col_y = ids ? s12 : s11;
|
| 1248 |
+
const int64_t stride_channel_dst = ids ? s1 : s2;
|
| 1249 |
+
const int64_t stride_channel_y = ids ? s11 : s12;
|
| 1250 |
+
|
| 1251 |
+
const int64_t ids_stride = ids ? ids->nb[1] / ggml_type_size(ids->type) : 0;
|
| 1252 |
+
|
| 1253 |
+
mul_mat_vec_q_switch_type(
|
| 1254 |
+
src0->data, src0->type, src1_q8_1.get(), ids_d, fusion_local, dst_d, ne00,
|
| 1255 |
+
ne01, ncols_dst, s01, stride_col_y, stride_col_dst,
|
| 1256 |
+
ne02, nchannels_y, nchannels_dst, s02, stride_channel_y, stride_channel_dst,
|
| 1257 |
+
ne03, ne3, s03, s13, s3, ids_stride, stream);
|
| 1258 |
+
}
|
| 1259 |
+
|
| 1260 |
+
void ggml_cuda_op_mul_mat_vec_q(
|
| 1261 |
+
ggml_backend_cuda_context & ctx,
|
| 1262 |
+
const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, const char * src0_dd_i, const float * src1_ddf_i,
|
| 1263 |
+
const char * src1_ddq_i, float * dst_dd_i, const int64_t row_low, const int64_t row_high, const int64_t src1_ncols,
|
| 1264 |
+
const int64_t src1_padded_row_size, cudaStream_t stream) {
|
| 1265 |
+
|
| 1266 |
+
const int64_t ne00 = src0->ne[0];
|
| 1267 |
+
const int64_t row_diff = row_high - row_low;
|
| 1268 |
+
|
| 1269 |
+
const int64_t ne10 = src1->ne[0];
|
| 1270 |
+
GGML_ASSERT(ne10 % QK8_1 == 0);
|
| 1271 |
+
|
| 1272 |
+
const int64_t ne0 = dst->ne[0];
|
| 1273 |
+
|
| 1274 |
+
int id = ggml_cuda_get_device();
|
| 1275 |
+
|
| 1276 |
+
// the main device has a larger memory buffer to hold the results from all GPUs
|
| 1277 |
+
// nrows_dst == nrows of the matrix that the kernel writes into
|
| 1278 |
+
const int64_t nrows_dst = id == ctx.device ? ne0 : row_diff;
|
| 1279 |
+
|
| 1280 |
+
const int stride_row_x = ne00 / ggml_blck_size(src0->type);
|
| 1281 |
+
const int stride_col_y = src1_padded_row_size / QK8_1;
|
| 1282 |
+
|
| 1283 |
+
ggml_cuda_mm_fusion_args_device fusion_local{};
|
| 1284 |
+
mul_mat_vec_q_switch_type(
|
| 1285 |
+
src0_dd_i, src0->type, src1_ddq_i, nullptr, fusion_local, dst_dd_i, ne00, row_diff, src1_ncols, stride_row_x, stride_col_y, nrows_dst,
|
| 1286 |
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, stream);
|
| 1287 |
+
|
| 1288 |
+
GGML_UNUSED_VARS(src1, dst, src1_ddf_i, src1_ncols, src1_padded_row_size);
|
| 1289 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/mmvq.cuh
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
|
| 3 |
+
#define MMVQ_MAX_BATCH_SIZE 8 // Max. batch size for which to use MMVQ kernels.
|
| 4 |
+
|
| 5 |
+
bool ggml_cuda_should_use_mmvq(enum ggml_type type, int cc, int64_t ne11);
|
| 6 |
+
|
| 7 |
+
// Returns the maximum batch size for which MMVQ should be used for MUL_MAT_ID,
|
| 8 |
+
// based on the quantization type and GPU architecture (compute capability).
|
| 9 |
+
int get_mmvq_mmid_max_batch(ggml_type type, int cc);
|
| 10 |
+
|
| 11 |
+
void ggml_cuda_mul_mat_vec_q(ggml_backend_cuda_context & ctx,
|
| 12 |
+
const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * ids, ggml_tensor * dst, const ggml_cuda_mm_fusion_args_host * fusion = nullptr);
|
| 13 |
+
|
| 14 |
+
void ggml_cuda_op_mul_mat_vec_q(
|
| 15 |
+
ggml_backend_cuda_context & ctx,
|
| 16 |
+
const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, const char * src0_dd_i, const float * src1_ddf_i,
|
| 17 |
+
const char * src1_ddq_i, float * dst_dd_i, const int64_t row_low, const int64_t row_high, const int64_t src1_ncols,
|
| 18 |
+
const int64_t src1_padded_row_size, cudaStream_t stream);
|
backend/llama.cpp/ggml/src/ggml-cuda/norm.cu
ADDED
|
@@ -0,0 +1,698 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "norm.cuh"
|
| 2 |
+
#include <cstdint>
|
| 3 |
+
|
| 4 |
+
template <int block_size>
|
| 5 |
+
static __global__ void norm_f32(
|
| 6 |
+
const float * x, float * dst, const int ncols, const int64_t stride_row, const int64_t stride_channel,
|
| 7 |
+
const int64_t stride_sample, const float eps) {
|
| 8 |
+
const int nrows = gridDim.x;
|
| 9 |
+
const int nchannels = gridDim.y;
|
| 10 |
+
|
| 11 |
+
const int row = blockIdx.x;
|
| 12 |
+
const int channel = blockIdx.y;
|
| 13 |
+
const int sample = blockIdx.z;
|
| 14 |
+
const int tid = threadIdx.x;
|
| 15 |
+
|
| 16 |
+
x += sample*stride_sample + channel*stride_channel + row*stride_row;
|
| 17 |
+
dst += ((sample*nchannels + channel)*nrows + row)*ncols;
|
| 18 |
+
|
| 19 |
+
float2 mean_var = make_float2(0.0f, 0.0f);
|
| 20 |
+
|
| 21 |
+
ggml_cuda_pdl_sync();
|
| 22 |
+
for (int col = tid; col < ncols; col += block_size) {
|
| 23 |
+
const float xi = x[col];
|
| 24 |
+
mean_var.x += xi;
|
| 25 |
+
mean_var.y += xi * xi;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
// sum up partial sums
|
| 29 |
+
extern __shared__ float2 s_sum2[];
|
| 30 |
+
mean_var = block_reduce<block_reduce_method::SUM, block_size>(mean_var, s_sum2);
|
| 31 |
+
|
| 32 |
+
const float mean = mean_var.x / ncols;
|
| 33 |
+
const float var = mean_var.y / ncols - mean * mean;
|
| 34 |
+
const float inv_std = rsqrtf(var + eps);
|
| 35 |
+
|
| 36 |
+
for (int col = tid; col < ncols; col += block_size) {
|
| 37 |
+
dst[col] = (x[col] - mean) * inv_std;
|
| 38 |
+
}
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
template <int block_size>
|
| 42 |
+
static __global__ void group_norm_f32(const float * x, float * dst, const int group_size, const int ne_elements, const float eps) {
|
| 43 |
+
// blockIdx.x: num_groups idx
|
| 44 |
+
// threadIdx.x: block_size idx
|
| 45 |
+
const int start = blockIdx.x*group_size + threadIdx.x;
|
| 46 |
+
const int end = min(blockIdx.x*group_size + group_size, ne_elements);
|
| 47 |
+
|
| 48 |
+
float tmp = 0.0f; // partial sum for thread in warp
|
| 49 |
+
|
| 50 |
+
ggml_cuda_pdl_sync();
|
| 51 |
+
for (int j = start; j < end; j += block_size) {
|
| 52 |
+
tmp += x[j];
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
extern __shared__ float s_sum[];
|
| 56 |
+
tmp = block_reduce<block_reduce_method::SUM, block_size>(tmp, s_sum);
|
| 57 |
+
|
| 58 |
+
const float mean = tmp / group_size;
|
| 59 |
+
tmp = 0.0f;
|
| 60 |
+
|
| 61 |
+
for (int j = start; j < end; j += block_size) {
|
| 62 |
+
const float xi = x[j] - mean;
|
| 63 |
+
dst[j] = xi;
|
| 64 |
+
tmp += xi * xi;
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
tmp = block_reduce<block_reduce_method::SUM, block_size>(tmp, s_sum);
|
| 68 |
+
|
| 69 |
+
const float variance = tmp / group_size;
|
| 70 |
+
const float scale = rsqrtf(variance + eps);
|
| 71 |
+
for (int j = start; j < end; j += block_size) {
|
| 72 |
+
dst[j] *= scale;
|
| 73 |
+
}
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
template <int block_size, bool do_multiply = false, bool do_add = false>
|
| 77 |
+
static __global__ void rms_norm_f32(const float * x,
|
| 78 |
+
float * dst,
|
| 79 |
+
const int ncols,
|
| 80 |
+
const int64_t stride_row,
|
| 81 |
+
const int64_t stride_channel,
|
| 82 |
+
const int64_t stride_sample,
|
| 83 |
+
const float eps,
|
| 84 |
+
const float * mul = nullptr,
|
| 85 |
+
const int64_t mul_stride_row = 0,
|
| 86 |
+
const int64_t mul_stride_channel = 0,
|
| 87 |
+
const int64_t mul_stride_sample = 0,
|
| 88 |
+
const uint3 mul_ncols_packed = make_uint3(0, 0, 0),
|
| 89 |
+
const uint3 mul_nrows_packed = make_uint3(0, 0, 0),
|
| 90 |
+
const uint3 mul_nchannels_packed = make_uint3(0, 0, 0),
|
| 91 |
+
const uint3 mul_nsamples_packed = make_uint3(0, 0, 0),
|
| 92 |
+
const float * add = nullptr,
|
| 93 |
+
const int64_t add_stride_row = 0,
|
| 94 |
+
const int64_t add_stride_channel = 0,
|
| 95 |
+
const int64_t add_stride_sample = 0,
|
| 96 |
+
const uint3 add_ncols_packed = make_uint3(0, 0, 0),
|
| 97 |
+
const uint3 add_nrows_packed = make_uint3(0, 0, 0),
|
| 98 |
+
const uint3 add_nchannels_packed = make_uint3(0, 0, 0),
|
| 99 |
+
const uint3 add_nsamples_packed = make_uint3(0, 0, 0)) {
|
| 100 |
+
ggml_cuda_pdl_lc();
|
| 101 |
+
const int nrows = gridDim.x;
|
| 102 |
+
const int nchannels = gridDim.y;
|
| 103 |
+
|
| 104 |
+
const int row = blockIdx.x;
|
| 105 |
+
const int channel = blockIdx.y;
|
| 106 |
+
const int sample = blockIdx.z;
|
| 107 |
+
const int tid = threadIdx.x;
|
| 108 |
+
|
| 109 |
+
static_assert(!do_add || do_multiply, "fusing add is not supported without multiplying");
|
| 110 |
+
|
| 111 |
+
x += sample*stride_sample + channel*stride_channel + row*stride_row;
|
| 112 |
+
dst += ((sample*nchannels + channel)*nrows + row)*ncols;
|
| 113 |
+
|
| 114 |
+
if constexpr (do_multiply) {
|
| 115 |
+
const uint32_t mul_row = fastmodulo(row, mul_nrows_packed);
|
| 116 |
+
const uint32_t mul_channel = fastmodulo(channel, mul_nchannels_packed);
|
| 117 |
+
const uint32_t mul_sample = fastmodulo(sample, mul_nsamples_packed);
|
| 118 |
+
mul += mul_sample * mul_stride_sample + mul_channel * mul_stride_channel + mul_row * mul_stride_row;
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
if constexpr (do_add) {
|
| 122 |
+
const int add_row = fastmodulo(row, add_nrows_packed);
|
| 123 |
+
const int add_channel = fastmodulo(channel, add_nchannels_packed);
|
| 124 |
+
const int add_sample = fastmodulo(sample, add_nsamples_packed);
|
| 125 |
+
add += add_sample * add_stride_sample + add_channel * add_stride_channel + add_row * add_stride_row;
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
float tmp = 0.0f; // partial sum for thread in warp
|
| 129 |
+
|
| 130 |
+
ggml_cuda_pdl_sync();
|
| 131 |
+
for (int col = tid; col < ncols; col += block_size) {
|
| 132 |
+
const float xi = x[col];
|
| 133 |
+
tmp += xi * xi;
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
// sum up partial sums
|
| 137 |
+
extern __shared__ float s_sum[];
|
| 138 |
+
tmp = block_reduce<block_reduce_method::SUM, block_size>(tmp, s_sum);
|
| 139 |
+
|
| 140 |
+
const float mean = tmp / ncols;
|
| 141 |
+
const float scale = rsqrtf(mean + eps);
|
| 142 |
+
|
| 143 |
+
for (int col = tid; col < ncols; col += block_size) {
|
| 144 |
+
if constexpr (do_multiply && do_add) {
|
| 145 |
+
const int mul_col = fastmodulo(col, mul_ncols_packed);
|
| 146 |
+
const int add_col = fastmodulo(col, add_ncols_packed);
|
| 147 |
+
dst[col] = scale * x[col] * mul[mul_col] + add[add_col];
|
| 148 |
+
} else if constexpr (do_multiply) {
|
| 149 |
+
const int mul_col = fastmodulo(col, mul_ncols_packed);
|
| 150 |
+
dst[col] = scale * x[col] * mul[mul_col];
|
| 151 |
+
} else {
|
| 152 |
+
dst[col] = scale * x[col];
|
| 153 |
+
}
|
| 154 |
+
}
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
template <int block_size>
|
| 158 |
+
static __global__ void rms_norm_back_f32(
|
| 159 |
+
const float * grad, const float * xf, float * dst, const int ncols, const float eps) {
|
| 160 |
+
const int row = blockIdx.x*blockDim.y + threadIdx.y;
|
| 161 |
+
const int tid = threadIdx.x;
|
| 162 |
+
|
| 163 |
+
grad += int64_t(row)*ncols;
|
| 164 |
+
xf += int64_t(row)*ncols;
|
| 165 |
+
dst += int64_t(row)*ncols;
|
| 166 |
+
|
| 167 |
+
float sum_xx = 0.0f; // sum for squares of x, equivalent to forward pass
|
| 168 |
+
float sum_xg = 0.0f; // sum for x * gradient, needed because RMS norm mixes inputs
|
| 169 |
+
|
| 170 |
+
ggml_cuda_pdl_sync();
|
| 171 |
+
for (int col = tid; col < ncols; col += block_size) {
|
| 172 |
+
const float xfi = xf[col];
|
| 173 |
+
sum_xx += xfi * xfi;
|
| 174 |
+
sum_xg += xfi * grad[col];
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
// sum up partial sums
|
| 178 |
+
sum_xx = warp_reduce_sum(sum_xx);
|
| 179 |
+
sum_xg = warp_reduce_sum(sum_xg);
|
| 180 |
+
if constexpr (block_size > WARP_SIZE) {
|
| 181 |
+
static_assert(block_size == 1024, "unexpected block_size");
|
| 182 |
+
__shared__ float s_sum_xx[32];
|
| 183 |
+
__shared__ float s_sum_xg[32];
|
| 184 |
+
const int warp_id = threadIdx.x / WARP_SIZE;
|
| 185 |
+
const int lane_id = threadIdx.x % WARP_SIZE;
|
| 186 |
+
if (lane_id == 0) {
|
| 187 |
+
s_sum_xx[warp_id] = sum_xx;
|
| 188 |
+
s_sum_xg[warp_id] = sum_xg;
|
| 189 |
+
}
|
| 190 |
+
__syncthreads();
|
| 191 |
+
|
| 192 |
+
sum_xx = s_sum_xx[lane_id];
|
| 193 |
+
sum_xx = warp_reduce_sum(sum_xx);
|
| 194 |
+
|
| 195 |
+
sum_xg = s_sum_xg[lane_id];
|
| 196 |
+
sum_xg = warp_reduce_sum(sum_xg);
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
const float mean_eps = sum_xx / ncols + eps;
|
| 200 |
+
const float sum_eps = sum_xx + ncols*eps;
|
| 201 |
+
|
| 202 |
+
const float scale_grad = rsqrtf(mean_eps);
|
| 203 |
+
const float scale_x = -scale_grad * sum_xg/sum_eps;
|
| 204 |
+
|
| 205 |
+
for (int col = tid; col < ncols; col += block_size) {
|
| 206 |
+
dst[col] = scale_grad*grad[col] + scale_x*xf[col];
|
| 207 |
+
}
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
// template <int block_size>
|
| 211 |
+
// static __global__ void l2_norm_f32(const float * x, float * dst, const int ncols, const float eps) {
|
| 212 |
+
// const int row = blockIdx.x*blockDim.y + threadIdx.y;
|
| 213 |
+
// const int tid = threadIdx.x;
|
| 214 |
+
|
| 215 |
+
// float tmp = 0.0f; // partial sum for thread in warp
|
| 216 |
+
|
| 217 |
+
// for (int col = tid; col < ncols; col += block_size) {
|
| 218 |
+
// const float xi = x[row*ncols + col];
|
| 219 |
+
// tmp += xi * xi;
|
| 220 |
+
// }
|
| 221 |
+
|
| 222 |
+
// // sum up partial sums
|
| 223 |
+
// tmp = warp_reduce_sum(tmp);
|
| 224 |
+
// if (block_size > WARP_SIZE) {
|
| 225 |
+
// __shared__ float s_sum[32];
|
| 226 |
+
// int warp_id = threadIdx.x / WARP_SIZE;
|
| 227 |
+
// int lane_id = threadIdx.x % WARP_SIZE;
|
| 228 |
+
// if (lane_id == 0) {
|
| 229 |
+
// s_sum[warp_id] = tmp;
|
| 230 |
+
// }
|
| 231 |
+
// __syncthreads();
|
| 232 |
+
// tmp = s_sum[lane_id];
|
| 233 |
+
// tmp = warp_reduce_sum(tmp);
|
| 234 |
+
// }
|
| 235 |
+
|
| 236 |
+
// // from https://pytorch.org/docs/stable/generated/torch.nn.functional.normalize.html
|
| 237 |
+
// const float scale = rsqrtf(fmaxf(tmp, eps * eps));
|
| 238 |
+
|
| 239 |
+
// for (int col = tid; col < ncols; col += block_size) {
|
| 240 |
+
// dst[row*ncols + col] = scale * x[row*ncols + col];
|
| 241 |
+
// }
|
| 242 |
+
// }
|
| 243 |
+
|
| 244 |
+
template <int block_size>
|
| 245 |
+
static __global__ void l2_norm_f32(
|
| 246 |
+
const float * x, float * dst, const int ncols, const int64_t stride_row, const int64_t stride_channel,
|
| 247 |
+
const int64_t stride_sample, const float eps) {
|
| 248 |
+
const int nrows = gridDim.x;
|
| 249 |
+
const int nchannels = gridDim.y;
|
| 250 |
+
|
| 251 |
+
const int row = blockIdx.x;
|
| 252 |
+
const int channel = blockIdx.y;
|
| 253 |
+
const int sample = blockIdx.z;
|
| 254 |
+
const int tid = threadIdx.x;
|
| 255 |
+
|
| 256 |
+
x += sample*stride_sample + channel*stride_channel + row*stride_row;
|
| 257 |
+
dst += ((sample*nchannels + channel)*nrows + row)*ncols;
|
| 258 |
+
|
| 259 |
+
float tmp = 0.0f; // partial sum for thread in warp
|
| 260 |
+
|
| 261 |
+
ggml_cuda_pdl_sync();
|
| 262 |
+
for (int col = tid; col < ncols; col += block_size) {
|
| 263 |
+
const float xi = x[col];
|
| 264 |
+
tmp += xi * xi;
|
| 265 |
+
}
|
| 266 |
+
|
| 267 |
+
// sum up partial sums
|
| 268 |
+
extern __shared__ float s_sum[];
|
| 269 |
+
tmp = block_reduce<block_reduce_method::SUM, block_size>(tmp, s_sum);
|
| 270 |
+
ggml_cuda_pdl_lc();
|
| 271 |
+
|
| 272 |
+
// from https://pytorch.org/docs/stable/generated/torch.nn.functional.normalize.html
|
| 273 |
+
const float scale = rsqrtf(fmaxf(tmp, eps * eps));
|
| 274 |
+
|
| 275 |
+
for (int col = tid; col < ncols; col += block_size) {
|
| 276 |
+
dst[col] = scale * x[col];
|
| 277 |
+
}
|
| 278 |
+
}
|
| 279 |
+
|
| 280 |
+
static void norm_f32_cuda(
|
| 281 |
+
const float * x, float * dst, const int ncols, const int nrows, const int nchannels, const int nsamples,
|
| 282 |
+
const int64_t stride_row, const int64_t stride_channel, const int64_t stride_sample, const float eps, cudaStream_t stream) {
|
| 283 |
+
const dim3 blocks_num(nrows, nchannels, nsamples);
|
| 284 |
+
if (ncols < 1024) {
|
| 285 |
+
const dim3 block_dims(WARP_SIZE, 1, 1);
|
| 286 |
+
norm_f32<WARP_SIZE><<<blocks_num, block_dims, 0, stream>>>(x, dst, ncols, stride_row, stride_channel, stride_sample, eps);
|
| 287 |
+
} else {
|
| 288 |
+
const dim3 block_dims(1024, 1, 1);
|
| 289 |
+
norm_f32<1024><<<blocks_num, block_dims, block_dims.x > WARP_SIZE ? 32 * sizeof(float2): 0, stream>>>(x, dst, ncols, stride_row, stride_channel, stride_sample, eps);
|
| 290 |
+
}
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
static void group_norm_f32_cuda(
|
| 294 |
+
const float * x, float * dst, const int num_groups, const float eps, const int group_size, const int ne_elements, cudaStream_t stream) {
|
| 295 |
+
if (group_size < 1024) {
|
| 296 |
+
const dim3 block_dims(WARP_SIZE, 1, 1);
|
| 297 |
+
group_norm_f32<WARP_SIZE><<<num_groups, block_dims, 0, stream>>>(x, dst, group_size, ne_elements, eps);
|
| 298 |
+
} else {
|
| 299 |
+
const dim3 block_dims(1024, 1, 1);
|
| 300 |
+
group_norm_f32<1024><<<num_groups, block_dims, block_dims.x > WARP_SIZE ? 32 * sizeof(float): 0, stream>>>(x, dst, group_size, ne_elements, eps);
|
| 301 |
+
}
|
| 302 |
+
}
|
| 303 |
+
|
| 304 |
+
static void rms_norm_f32_cuda(
|
| 305 |
+
const float * x, float * dst, const int ncols, const int nrows, const int nchannels, const int nsamples,
|
| 306 |
+
const int64_t stride_row, const int64_t stride_channel, const int64_t stride_sample, const float eps, cudaStream_t stream) {
|
| 307 |
+
const dim3 blocks_num(nrows, nchannels, nsamples);
|
| 308 |
+
if (ncols < 1024) {
|
| 309 |
+
const dim3 block_dims(256, 1, 1);
|
| 310 |
+
const ggml_cuda_kernel_launch_params launch_params = {blocks_num, block_dims, block_dims.x > WARP_SIZE ? 32 * sizeof(float): 0, stream};
|
| 311 |
+
ggml_cuda_kernel_launch(rms_norm_f32<256, false>, launch_params,
|
| 312 |
+
x, dst, ncols, stride_row, stride_channel, stride_sample, eps,
|
| 313 |
+
// underlying cudaLaunchKernelEx does not support default params
|
| 314 |
+
nullptr, 0, 0, 0, make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0),
|
| 315 |
+
nullptr, 0, 0, 0, make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0));
|
| 316 |
+
} else {
|
| 317 |
+
const dim3 block_dims(1024, 1, 1);
|
| 318 |
+
const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params{blocks_num, block_dims, block_dims.x > WARP_SIZE ? 32 * sizeof(float): 0, stream};
|
| 319 |
+
ggml_cuda_kernel_launch(rms_norm_f32<1024, false>, launch_params, x, dst, ncols, stride_row, stride_channel, stride_sample, eps,
|
| 320 |
+
// underlying cudaLaunchKernelEx does not support default params
|
| 321 |
+
nullptr, 0, 0, 0, make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0),
|
| 322 |
+
nullptr, 0, 0, 0, make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0));
|
| 323 |
+
}
|
| 324 |
+
}
|
| 325 |
+
|
| 326 |
+
static void rms_norm_mul_f32_cuda(const float * x,
|
| 327 |
+
const float * mul,
|
| 328 |
+
const float * add,
|
| 329 |
+
float * dst,
|
| 330 |
+
const int ncols,
|
| 331 |
+
const int nrows,
|
| 332 |
+
const int nchannels,
|
| 333 |
+
const int nsamples,
|
| 334 |
+
const int64_t stride_row,
|
| 335 |
+
const int64_t stride_channel,
|
| 336 |
+
const int64_t stride_sample,
|
| 337 |
+
const int64_t mul_stride_row,
|
| 338 |
+
const int64_t mul_stride_channel,
|
| 339 |
+
const int64_t mul_stride_sample,
|
| 340 |
+
const uint32_t mul_ncols,
|
| 341 |
+
const uint32_t mul_nrows,
|
| 342 |
+
const uint32_t mul_nchannels,
|
| 343 |
+
const uint32_t mul_nsamples,
|
| 344 |
+
const int64_t add_stride_row,
|
| 345 |
+
const int64_t add_stride_channel,
|
| 346 |
+
const int64_t add_stride_sample,
|
| 347 |
+
const uint32_t add_ncols,
|
| 348 |
+
const uint32_t add_nrows,
|
| 349 |
+
const uint32_t add_nchannels,
|
| 350 |
+
const uint32_t add_nsamples,
|
| 351 |
+
const float eps,
|
| 352 |
+
cudaStream_t stream) {
|
| 353 |
+
const dim3 blocks_num(nrows, nchannels, nsamples);
|
| 354 |
+
if (mul == nullptr) {
|
| 355 |
+
rms_norm_f32_cuda(x, dst, ncols, nrows, nchannels, nsamples, stride_row, stride_channel, stride_sample, eps, stream);
|
| 356 |
+
return;
|
| 357 |
+
}
|
| 358 |
+
if (add == nullptr) {
|
| 359 |
+
const uint3 mul_ncols_packed = init_fastdiv_values(mul_ncols);
|
| 360 |
+
const uint3 mul_nrows_packed = init_fastdiv_values(mul_nrows);
|
| 361 |
+
const uint3 mul_nchannels_packed = init_fastdiv_values(mul_nchannels);
|
| 362 |
+
const uint3 mul_nsamples_packed = init_fastdiv_values(mul_nsamples);
|
| 363 |
+
if (ncols < 1024) {
|
| 364 |
+
const dim3 block_dims(256, 1, 1);
|
| 365 |
+
const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params{blocks_num, block_dims, block_dims.x > WARP_SIZE ? 32 * sizeof(float): 0, stream};
|
| 366 |
+
ggml_cuda_kernel_launch(rms_norm_f32<256, true>, launch_params,
|
| 367 |
+
x, dst, ncols, stride_row, stride_channel, stride_sample, eps, mul, mul_stride_row, mul_stride_channel,
|
| 368 |
+
mul_stride_sample, mul_ncols_packed, mul_nrows_packed, mul_nchannels_packed, mul_nsamples_packed,
|
| 369 |
+
// underlying cudaLaunchKernelEx does not support default params
|
| 370 |
+
nullptr, 0, 0, 0, make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0));
|
| 371 |
+
} else {
|
| 372 |
+
const dim3 block_dims(1024, 1, 1);
|
| 373 |
+
const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params{blocks_num, block_dims, block_dims.x > WARP_SIZE ? 32 * sizeof(float): 0, stream};
|
| 374 |
+
ggml_cuda_kernel_launch(rms_norm_f32<1024, true>, launch_params,
|
| 375 |
+
x, dst, ncols, stride_row, stride_channel, stride_sample, eps, mul, mul_stride_row, mul_stride_channel,
|
| 376 |
+
mul_stride_sample, mul_ncols_packed, mul_nrows_packed, mul_nchannels_packed, mul_nsamples_packed,
|
| 377 |
+
// underlying cudaLaunchKernelEx does not support default params
|
| 378 |
+
nullptr, 0, 0, 0, make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0), make_uint3(0, 0, 0));
|
| 379 |
+
}
|
| 380 |
+
} else {
|
| 381 |
+
const uint3 mul_ncols_packed = init_fastdiv_values(mul_ncols);
|
| 382 |
+
const uint3 mul_nrows_packed = init_fastdiv_values(mul_nrows);
|
| 383 |
+
const uint3 mul_nchannels_packed = init_fastdiv_values(mul_nchannels);
|
| 384 |
+
const uint3 mul_nsamples_packed = init_fastdiv_values(mul_nsamples);
|
| 385 |
+
|
| 386 |
+
const uint3 add_ncols_packed = init_fastdiv_values(add_ncols);
|
| 387 |
+
const uint3 add_nrows_packed = init_fastdiv_values(add_nrows);
|
| 388 |
+
const uint3 add_nchannels_packed = init_fastdiv_values(add_nchannels);
|
| 389 |
+
const uint3 add_nsamples_packed = init_fastdiv_values(add_nsamples);
|
| 390 |
+
if (ncols < 1024) {
|
| 391 |
+
const dim3 block_dims(256, 1, 1);
|
| 392 |
+
const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params{blocks_num, block_dims,block_dims.x > WARP_SIZE ? 32 * sizeof(float): 0, stream};
|
| 393 |
+
ggml_cuda_kernel_launch(rms_norm_f32<256, true, true>, launch_params,
|
| 394 |
+
x, dst, ncols, stride_row, stride_channel, stride_sample, eps, mul, mul_stride_row, mul_stride_channel,
|
| 395 |
+
mul_stride_sample, mul_ncols_packed, mul_nrows_packed, mul_nchannels_packed, mul_nsamples_packed, add,
|
| 396 |
+
add_stride_row, add_stride_channel, add_stride_sample, add_ncols_packed, add_nrows_packed,
|
| 397 |
+
add_nchannels_packed, add_nsamples_packed);
|
| 398 |
+
} else {
|
| 399 |
+
const dim3 block_dims(1024, 1, 1);
|
| 400 |
+
const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params{blocks_num, block_dims, block_dims.x > WARP_SIZE ? 32 * sizeof(float): 0, stream};
|
| 401 |
+
ggml_cuda_kernel_launch(rms_norm_f32<1024, true, true>, launch_params,
|
| 402 |
+
x, dst, ncols, stride_row, stride_channel, stride_sample, eps, mul, mul_stride_row, mul_stride_channel,
|
| 403 |
+
mul_stride_sample, mul_ncols_packed, mul_nrows_packed, mul_nchannels_packed, mul_nsamples_packed, add,
|
| 404 |
+
add_stride_row, add_stride_channel, add_stride_sample, add_ncols_packed, add_nrows_packed,
|
| 405 |
+
add_nchannels_packed, add_nsamples_packed);
|
| 406 |
+
}
|
| 407 |
+
}
|
| 408 |
+
}
|
| 409 |
+
|
| 410 |
+
static void rms_norm_back_f32_cuda(const float * grad, const float * xf, float * dst, const int ncols, const int nrows, const float eps, cudaStream_t stream) {
|
| 411 |
+
if (ncols < 1024) {
|
| 412 |
+
const dim3 block_dims(WARP_SIZE, 1, 1);
|
| 413 |
+
rms_norm_back_f32<WARP_SIZE><<<nrows, block_dims, 0, stream>>>(grad, xf, dst, ncols, eps);
|
| 414 |
+
} else {
|
| 415 |
+
const dim3 block_dims(1024, 1, 1);
|
| 416 |
+
rms_norm_back_f32<1024><<<nrows, block_dims, 0, stream>>>(grad, xf, dst, ncols, eps);
|
| 417 |
+
}
|
| 418 |
+
}
|
| 419 |
+
|
| 420 |
+
static void l2_norm_f32_cuda(
|
| 421 |
+
const float * x, float * dst, const int ncols, const int nrows, const int nchannels, const int nsamples,
|
| 422 |
+
const int64_t stride_row, const int64_t stride_channel, const int64_t stride_sample, const float eps, cudaStream_t stream) {
|
| 423 |
+
const dim3 blocks_num(nrows, nchannels, nsamples);
|
| 424 |
+
if (ncols < 1024) {
|
| 425 |
+
const dim3 block_dims(WARP_SIZE, 1, 1);
|
| 426 |
+
const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params{blocks_num, block_dims, 0, stream};
|
| 427 |
+
ggml_cuda_kernel_launch(l2_norm_f32<WARP_SIZE>, launch_params, x, dst, ncols, stride_row, stride_channel, stride_sample, eps);
|
| 428 |
+
} else {
|
| 429 |
+
const dim3 block_dims(1024, 1, 1);
|
| 430 |
+
const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params{blocks_num, block_dims, block_dims.x > WARP_SIZE ? 32 * sizeof(float): 0, stream};
|
| 431 |
+
ggml_cuda_kernel_launch(l2_norm_f32<1024>, launch_params, x, dst, ncols, stride_row, stride_channel, stride_sample, eps);
|
| 432 |
+
}
|
| 433 |
+
}
|
| 434 |
+
|
| 435 |
+
void ggml_cuda_op_norm(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 436 |
+
const ggml_tensor * src0 = dst->src[0];
|
| 437 |
+
const float * src0_d = (const float *) src0->data;
|
| 438 |
+
float * dst_d = (float *) dst->data;
|
| 439 |
+
cudaStream_t stream = ctx.stream();
|
| 440 |
+
|
| 441 |
+
GGML_ASSERT(src0->type == GGML_TYPE_F32);
|
| 442 |
+
GGML_ASSERT( dst->type == GGML_TYPE_F32);
|
| 443 |
+
|
| 444 |
+
GGML_TENSOR_UNARY_OP_LOCALS;
|
| 445 |
+
|
| 446 |
+
float eps;
|
| 447 |
+
memcpy(&eps, dst->op_params, sizeof(float));
|
| 448 |
+
GGML_ASSERT(eps >= 0.0f);
|
| 449 |
+
|
| 450 |
+
const size_t ts0 = ggml_type_size(src0->type);
|
| 451 |
+
GGML_ASSERT(nb00 == ts0);
|
| 452 |
+
const int64_t s01 = nb01 / ts0;
|
| 453 |
+
const int64_t s02 = nb02 / ts0;
|
| 454 |
+
const int64_t s03 = nb03 / ts0;
|
| 455 |
+
|
| 456 |
+
norm_f32_cuda(src0_d, dst_d, ne00, ne01, ne02, ne03, s01, s02, s03, eps, stream);
|
| 457 |
+
}
|
| 458 |
+
|
| 459 |
+
void ggml_cuda_op_group_norm(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 460 |
+
const ggml_tensor * src0 = dst->src[0];
|
| 461 |
+
const float * src0_d = (const float *)src0->data;
|
| 462 |
+
float * dst_d = (float *)dst->data;
|
| 463 |
+
cudaStream_t stream = ctx.stream();
|
| 464 |
+
|
| 465 |
+
GGML_ASSERT(src0->type == GGML_TYPE_F32);
|
| 466 |
+
GGML_ASSERT( dst->type == GGML_TYPE_F32);
|
| 467 |
+
|
| 468 |
+
int num_groups = dst->op_params[0];
|
| 469 |
+
|
| 470 |
+
float eps;
|
| 471 |
+
memcpy(&eps, dst->op_params + 1, sizeof(float));
|
| 472 |
+
GGML_ASSERT(eps >= 0.0f);
|
| 473 |
+
|
| 474 |
+
int group_size = src0->ne[0] * src0->ne[1] * ((src0->ne[2] + num_groups - 1) / num_groups);
|
| 475 |
+
group_norm_f32_cuda(src0_d, dst_d, num_groups * src0->ne[3], eps, group_size, ggml_nelements(src0), stream);
|
| 476 |
+
}
|
| 477 |
+
|
| 478 |
+
void ggml_cuda_op_rms_norm(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 479 |
+
const ggml_tensor * src0 = dst->src[0];
|
| 480 |
+
const float * src0_d = (const float *) src0->data;
|
| 481 |
+
float * dst_d = (float *) dst->data;
|
| 482 |
+
cudaStream_t stream = ctx.stream();
|
| 483 |
+
|
| 484 |
+
GGML_ASSERT(src0->type == GGML_TYPE_F32);
|
| 485 |
+
GGML_ASSERT( dst->type == GGML_TYPE_F32);
|
| 486 |
+
|
| 487 |
+
GGML_TENSOR_UNARY_OP_LOCALS;
|
| 488 |
+
|
| 489 |
+
float eps;
|
| 490 |
+
memcpy(&eps, dst->op_params, sizeof(float));
|
| 491 |
+
GGML_ASSERT(eps >= 0.0f);
|
| 492 |
+
|
| 493 |
+
const size_t ts0 = ggml_type_size(src0->type);
|
| 494 |
+
GGML_ASSERT(nb00 == ts0);
|
| 495 |
+
const int64_t s01 = nb01 / ts0;
|
| 496 |
+
const int64_t s02 = nb02 / ts0;
|
| 497 |
+
const int64_t s03 = nb03 / ts0;
|
| 498 |
+
|
| 499 |
+
rms_norm_f32_cuda(src0_d, dst_d, ne00, ne01, ne02, ne03, s01, s02, s03, eps, stream);
|
| 500 |
+
}
|
| 501 |
+
|
| 502 |
+
void ggml_cuda_op_rms_norm_fused(ggml_backend_cuda_context & ctx, ggml_tensor * dst, ggml_tensor * mul_tensor) {
|
| 503 |
+
const ggml_tensor * rms_norm_src = (ggml_tensor *) dst->src[0];
|
| 504 |
+
float eps = 0.0f;
|
| 505 |
+
|
| 506 |
+
memcpy(&eps, dst->op_params, sizeof(float));
|
| 507 |
+
|
| 508 |
+
const float * src0_d = (const float *) rms_norm_src->data;
|
| 509 |
+
const float * mul_d = nullptr;
|
| 510 |
+
const ggml_tensor * mul_src = nullptr;
|
| 511 |
+
|
| 512 |
+
if (mul_tensor->src[0] == dst) {
|
| 513 |
+
mul_d = (float *) mul_tensor->src[1]->data;
|
| 514 |
+
mul_src = mul_tensor->src[1];
|
| 515 |
+
} else if(mul_tensor->src[1] == dst) {
|
| 516 |
+
mul_d = (float *) mul_tensor->src[0]->data;
|
| 517 |
+
mul_src = mul_tensor->src[0];
|
| 518 |
+
} else {
|
| 519 |
+
GGML_ASSERT(false);
|
| 520 |
+
}
|
| 521 |
+
|
| 522 |
+
float * dst_d = (float *) mul_tensor->data;
|
| 523 |
+
cudaStream_t stream = ctx.stream();
|
| 524 |
+
|
| 525 |
+
GGML_ASSERT(rms_norm_src->type == GGML_TYPE_F32);
|
| 526 |
+
GGML_ASSERT(dst->type == GGML_TYPE_F32);
|
| 527 |
+
GGML_ASSERT(mul_tensor->type == GGML_TYPE_F32);
|
| 528 |
+
GGML_ASSERT(eps >= 0.0f);
|
| 529 |
+
|
| 530 |
+
const int64_t ne00 = rms_norm_src->ne[0];
|
| 531 |
+
const int64_t ne01 = rms_norm_src->ne[1];
|
| 532 |
+
const int64_t ne02 = rms_norm_src->ne[2];
|
| 533 |
+
const int64_t ne03 = rms_norm_src->ne[3];
|
| 534 |
+
|
| 535 |
+
const size_t ts0 = ggml_type_size(rms_norm_src->type);
|
| 536 |
+
GGML_ASSERT(rms_norm_src->nb[0] == ts0);
|
| 537 |
+
const int64_t s01 = rms_norm_src->nb[1] / ts0;
|
| 538 |
+
const int64_t s02 = rms_norm_src->nb[2] / ts0;
|
| 539 |
+
const int64_t s03 = rms_norm_src->nb[3] / ts0;
|
| 540 |
+
|
| 541 |
+
const size_t ts_mul = ggml_type_size(mul_src->type);
|
| 542 |
+
GGML_ASSERT(mul_src->nb[0] == ts_mul);
|
| 543 |
+
const int64_t mul_s01 = mul_src->nb[1] / ts_mul;
|
| 544 |
+
const int64_t mul_s02 = mul_src->nb[2] / ts_mul;
|
| 545 |
+
const int64_t mul_s03 = mul_src->nb[3] / ts_mul;
|
| 546 |
+
|
| 547 |
+
const int mul_ncols = mul_src->ne[0];
|
| 548 |
+
const int mul_nrows = mul_src->ne[1];
|
| 549 |
+
const int mul_nchannels = mul_src->ne[2];
|
| 550 |
+
const int mul_nsamples = mul_src->ne[3];
|
| 551 |
+
|
| 552 |
+
rms_norm_mul_f32_cuda(src0_d, mul_d, nullptr, dst_d,
|
| 553 |
+
ne00, ne01, ne02, ne03,
|
| 554 |
+
/*s00*/ s01, s02, s03,
|
| 555 |
+
/*mul_s00*/ mul_s01, mul_s02, mul_s03,
|
| 556 |
+
mul_ncols, mul_nrows, mul_nchannels, mul_nsamples,
|
| 557 |
+
/*add_s00*/ 0, 0, 0,
|
| 558 |
+
0, 0, 0, 0,
|
| 559 |
+
eps, stream);
|
| 560 |
+
}
|
| 561 |
+
|
| 562 |
+
void ggml_cuda_op_rms_norm_fused_add(ggml_backend_cuda_context & ctx,
|
| 563 |
+
ggml_tensor * dst,
|
| 564 |
+
ggml_tensor * mul_tensor,
|
| 565 |
+
ggml_tensor * add_tensor) {
|
| 566 |
+
const ggml_tensor * rms_norm_src = (ggml_tensor *) dst->src[0];
|
| 567 |
+
float eps = 0.0f;
|
| 568 |
+
|
| 569 |
+
memcpy(&eps, dst->op_params, sizeof(float));
|
| 570 |
+
|
| 571 |
+
const float * src0_d = (const float *) rms_norm_src->data;
|
| 572 |
+
const float * mul_d = nullptr;
|
| 573 |
+
const ggml_tensor * mul_src = nullptr;
|
| 574 |
+
|
| 575 |
+
if (mul_tensor->src[0] == dst) {
|
| 576 |
+
mul_d = (float *) mul_tensor->src[1]->data;
|
| 577 |
+
mul_src = mul_tensor->src[1];
|
| 578 |
+
} else if (mul_tensor->src[1] == dst) {
|
| 579 |
+
mul_d = (float *) mul_tensor->src[0]->data;
|
| 580 |
+
mul_src = mul_tensor->src[0];
|
| 581 |
+
} else {
|
| 582 |
+
GGML_ASSERT(false);
|
| 583 |
+
}
|
| 584 |
+
|
| 585 |
+
const float * add_d = nullptr;
|
| 586 |
+
const ggml_tensor * add_src = nullptr;
|
| 587 |
+
|
| 588 |
+
if (add_tensor->src[0] == mul_tensor) {
|
| 589 |
+
add_d = (float *) add_tensor->src[1]->data;
|
| 590 |
+
add_src = add_tensor->src[1];
|
| 591 |
+
} else if (add_tensor->src[1] == mul_tensor) {
|
| 592 |
+
add_d = (float *) add_tensor->src[0]->data;
|
| 593 |
+
add_src = add_tensor->src[0];
|
| 594 |
+
} else {
|
| 595 |
+
GGML_ASSERT(false);
|
| 596 |
+
}
|
| 597 |
+
|
| 598 |
+
float * dst_d = (float *) add_tensor->data;
|
| 599 |
+
cudaStream_t stream = ctx.stream();
|
| 600 |
+
|
| 601 |
+
GGML_ASSERT(rms_norm_src->type == GGML_TYPE_F32);
|
| 602 |
+
GGML_ASSERT(dst->type == GGML_TYPE_F32);
|
| 603 |
+
GGML_ASSERT(mul_tensor->type == GGML_TYPE_F32);
|
| 604 |
+
GGML_ASSERT(add_tensor->type == GGML_TYPE_F32);
|
| 605 |
+
GGML_ASSERT(eps >= 0.0f);
|
| 606 |
+
|
| 607 |
+
const int64_t ne00 = rms_norm_src->ne[0];
|
| 608 |
+
const int64_t ne01 = rms_norm_src->ne[1];
|
| 609 |
+
const int64_t ne02 = rms_norm_src->ne[2];
|
| 610 |
+
const int64_t ne03 = rms_norm_src->ne[3];
|
| 611 |
+
|
| 612 |
+
const size_t ts0 = ggml_type_size(rms_norm_src->type);
|
| 613 |
+
GGML_ASSERT(rms_norm_src->nb[0] == ts0);
|
| 614 |
+
const int64_t s01 = rms_norm_src->nb[1] / ts0;
|
| 615 |
+
const int64_t s02 = rms_norm_src->nb[2] / ts0;
|
| 616 |
+
const int64_t s03 = rms_norm_src->nb[3] / ts0;
|
| 617 |
+
|
| 618 |
+
const size_t ts_mul = ggml_type_size(mul_src->type);
|
| 619 |
+
GGML_ASSERT(mul_src->nb[0] == ts_mul);
|
| 620 |
+
const int64_t mul_s01 = mul_src->nb[1] / ts_mul;
|
| 621 |
+
const int64_t mul_s02 = mul_src->nb[2] / ts_mul;
|
| 622 |
+
const int64_t mul_s03 = mul_src->nb[3] / ts_mul;
|
| 623 |
+
|
| 624 |
+
const int mul_ncols = mul_src->ne[0];
|
| 625 |
+
const int mul_nrows = mul_src->ne[1];
|
| 626 |
+
const int mul_nchannels = mul_src->ne[2];
|
| 627 |
+
const int mul_nsamples = mul_src->ne[3];
|
| 628 |
+
|
| 629 |
+
const size_t ts_add = ggml_type_size(add_src->type);
|
| 630 |
+
GGML_ASSERT(add_src->nb[0] == ts_add);
|
| 631 |
+
const int64_t add_s01 = add_src->nb[1] / ts_add;
|
| 632 |
+
const int64_t add_s02 = add_src->nb[2] / ts_add;
|
| 633 |
+
const int64_t add_s03 = add_src->nb[3] / ts_add;
|
| 634 |
+
|
| 635 |
+
const int add_ncols = add_src->ne[0];
|
| 636 |
+
const int add_nrows = add_src->ne[1];
|
| 637 |
+
const int add_nchannels = add_src->ne[2];
|
| 638 |
+
const int add_nsamples = add_src->ne[3];
|
| 639 |
+
|
| 640 |
+
rms_norm_mul_f32_cuda(src0_d, mul_d,add_d,dst_d,
|
| 641 |
+
ne00,ne01, ne02, ne03,
|
| 642 |
+
/*s00*/ s01, s02, s03,
|
| 643 |
+
/*mul_s00*/ mul_s01, mul_s02, mul_s03,
|
| 644 |
+
mul_ncols, mul_nrows, mul_nchannels, mul_nsamples,
|
| 645 |
+
/*add_s00*/ add_s01, add_s02, add_s03,
|
| 646 |
+
add_ncols, add_nrows, add_nchannels, add_nsamples,
|
| 647 |
+
eps, stream);
|
| 648 |
+
}
|
| 649 |
+
|
| 650 |
+
void ggml_cuda_op_rms_norm_back(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 651 |
+
const ggml_tensor * grad = dst->src[0]; // gradients
|
| 652 |
+
const ggml_tensor * src0f = dst->src[1]; // src0 from forward pass
|
| 653 |
+
|
| 654 |
+
const float * grad_d = (const float *) grad->data;
|
| 655 |
+
const float * src0f_d = (const float *) src0f->data;
|
| 656 |
+
float * dst_d = (float *) dst->data;
|
| 657 |
+
|
| 658 |
+
cudaStream_t stream = ctx.stream();
|
| 659 |
+
|
| 660 |
+
GGML_ASSERT(ggml_is_contiguous(grad));
|
| 661 |
+
|
| 662 |
+
GGML_ASSERT( grad->type == GGML_TYPE_F32);
|
| 663 |
+
GGML_ASSERT(src0f->type == GGML_TYPE_F32);
|
| 664 |
+
GGML_ASSERT( dst->type == GGML_TYPE_F32);
|
| 665 |
+
|
| 666 |
+
const int64_t ne00 = src0f->ne[0];
|
| 667 |
+
const int64_t nrows = ggml_nrows(src0f);
|
| 668 |
+
|
| 669 |
+
float eps;
|
| 670 |
+
memcpy(&eps, dst->op_params, sizeof(float));
|
| 671 |
+
GGML_ASSERT(eps >= 0.0f);
|
| 672 |
+
|
| 673 |
+
rms_norm_back_f32_cuda(grad_d, src0f_d, dst_d, ne00, nrows, eps, stream);
|
| 674 |
+
}
|
| 675 |
+
|
| 676 |
+
void ggml_cuda_op_l2_norm(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 677 |
+
const ggml_tensor * src0 = dst->src[0];
|
| 678 |
+
const float * src0_d = (const float *) src0->data;
|
| 679 |
+
float * dst_d = (float *) dst->data;
|
| 680 |
+
cudaStream_t stream = ctx.stream();
|
| 681 |
+
|
| 682 |
+
GGML_ASSERT(src0->type == GGML_TYPE_F32);
|
| 683 |
+
GGML_ASSERT( dst->type == GGML_TYPE_F32);
|
| 684 |
+
|
| 685 |
+
GGML_TENSOR_UNARY_OP_LOCALS;
|
| 686 |
+
|
| 687 |
+
float eps;
|
| 688 |
+
memcpy(&eps, dst->op_params, sizeof(float));
|
| 689 |
+
GGML_ASSERT(eps >= 0.0f);
|
| 690 |
+
|
| 691 |
+
const size_t ts0 = ggml_type_size(src0->type);
|
| 692 |
+
GGML_ASSERT(nb00 == ts0);
|
| 693 |
+
const int64_t s01 = nb01 / ts0;
|
| 694 |
+
const int64_t s02 = nb02 / ts0;
|
| 695 |
+
const int64_t s03 = nb03 / ts0;
|
| 696 |
+
|
| 697 |
+
l2_norm_f32_cuda(src0_d, dst_d, ne00, ne01, ne02, ne03, s01, s02, s03, eps, stream);
|
| 698 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/norm.cuh
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
|
| 3 |
+
void ggml_cuda_op_norm(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
| 4 |
+
|
| 5 |
+
void ggml_cuda_op_group_norm(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
| 6 |
+
|
| 7 |
+
void ggml_cuda_op_rms_norm(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
| 8 |
+
|
| 9 |
+
void ggml_cuda_op_rms_norm_fused(ggml_backend_cuda_context & ctx, ggml_tensor * dst, ggml_tensor * mul_tensor);
|
| 10 |
+
|
| 11 |
+
void ggml_cuda_op_rms_norm_fused_add(ggml_backend_cuda_context & ctx,
|
| 12 |
+
ggml_tensor * dst,
|
| 13 |
+
ggml_tensor * mul_tensor,
|
| 14 |
+
ggml_tensor * add_tensor);
|
| 15 |
+
|
| 16 |
+
void ggml_cuda_op_rms_norm_back(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
| 17 |
+
|
| 18 |
+
void ggml_cuda_op_l2_norm(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
backend/llama.cpp/ggml/src/ggml-cuda/opt-step-adamw.cu
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "ggml-impl.h"
|
| 2 |
+
#include "opt-step-adamw.cuh"
|
| 3 |
+
|
| 4 |
+
#include <cstdint>
|
| 5 |
+
|
| 6 |
+
static __global__ void opt_step_adamw_f32(
|
| 7 |
+
float * __restrict__ x, const float * __restrict__ g, float * __restrict__ g_m, float * __restrict__ g_v,
|
| 8 |
+
const float * __restrict__ pars, const int64_t k) {
|
| 9 |
+
|
| 10 |
+
const int64_t i = (int64_t) blockIdx.x*blockDim.x + threadIdx.x;
|
| 11 |
+
|
| 12 |
+
if (i >= k) {
|
| 13 |
+
return;
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
const float alpha = pars[0];
|
| 17 |
+
const float beta1 = pars[1];
|
| 18 |
+
const float beta2 = pars[2];
|
| 19 |
+
const float eps = pars[3];
|
| 20 |
+
const float wd = pars[4];
|
| 21 |
+
const float beta1h = pars[5];
|
| 22 |
+
const float beta2h = pars[6];
|
| 23 |
+
|
| 24 |
+
const float gi = g[i];
|
| 25 |
+
const float gmi = g_m[i]*beta1 + gi*(1.0f - beta1);
|
| 26 |
+
const float gvi = g_v[i]*beta2 + gi*gi*(1.0f - beta2);
|
| 27 |
+
|
| 28 |
+
g_m[i] = gmi;
|
| 29 |
+
g_v[i] = gvi;
|
| 30 |
+
|
| 31 |
+
const float mh = gmi*beta1h;
|
| 32 |
+
const float vh = sqrtf(gvi*beta2h) + eps;
|
| 33 |
+
|
| 34 |
+
x[i] = x[i]*(1.0f - alpha*wd) - alpha*mh/vh;
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
static void opt_step_adamw_f32_cuda(
|
| 38 |
+
float * x, const float * g, float * g_m, float * g_v, const float * pars, const int64_t k, cudaStream_t stream) {
|
| 39 |
+
|
| 40 |
+
const dim3 block_dims(CUDA_OPT_STEP_ADAMW_BLOCK_SIZE, 1, 1);
|
| 41 |
+
const dim3 block_nums((k + CUDA_OPT_STEP_ADAMW_BLOCK_SIZE - 1) / CUDA_OPT_STEP_ADAMW_BLOCK_SIZE, 1, 1);
|
| 42 |
+
opt_step_adamw_f32<<<block_nums, block_dims, 0, stream>>>(x, g, g_m, g_v, pars, k);
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
void ggml_cuda_opt_step_adamw(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 46 |
+
const ggml_tensor * src0 = dst->src[0];
|
| 47 |
+
const ggml_tensor * src0_grad = dst->src[1];
|
| 48 |
+
const ggml_tensor * src0_grad_m = dst->src[2];
|
| 49 |
+
const ggml_tensor * src0_grad_v = dst->src[3];
|
| 50 |
+
const ggml_tensor * adamw_params = dst->src[4];
|
| 51 |
+
|
| 52 |
+
GGML_ASSERT(src0->type == GGML_TYPE_F32);
|
| 53 |
+
GGML_ASSERT(src0_grad->type == GGML_TYPE_F32);
|
| 54 |
+
GGML_ASSERT(src0_grad_m->type == GGML_TYPE_F32);
|
| 55 |
+
GGML_ASSERT(src0_grad_v->type == GGML_TYPE_F32);
|
| 56 |
+
GGML_ASSERT(adamw_params->type == GGML_TYPE_F32);
|
| 57 |
+
GGML_ASSERT(ggml_is_contiguous(src0));
|
| 58 |
+
GGML_ASSERT(ggml_is_contiguous(src0_grad));
|
| 59 |
+
GGML_ASSERT(ggml_is_contiguous(src0_grad_m));
|
| 60 |
+
GGML_ASSERT(ggml_is_contiguous(src0_grad_v));
|
| 61 |
+
GGML_ASSERT(ggml_is_contiguous(adamw_params));
|
| 62 |
+
GGML_ASSERT(ggml_are_same_shape(src0, src0_grad));
|
| 63 |
+
GGML_ASSERT(ggml_are_same_shape(src0, src0_grad_m));
|
| 64 |
+
GGML_ASSERT(ggml_are_same_shape(src0, src0_grad_v));
|
| 65 |
+
GGML_ASSERT(ggml_nelements(adamw_params) == 7);
|
| 66 |
+
|
| 67 |
+
float * src0_d = (float *) src0->data;
|
| 68 |
+
const float * src0_grad_d = (const float *) src0_grad->data;
|
| 69 |
+
float * src0_grad_m_d = (float *) src0_grad_m->data;
|
| 70 |
+
float * src0_grad_v_d = (float *) src0_grad_v->data;
|
| 71 |
+
const float * adamw_params_d = (const float *) adamw_params->data;
|
| 72 |
+
|
| 73 |
+
cudaStream_t stream = ctx.stream();
|
| 74 |
+
|
| 75 |
+
const int64_t ne = ggml_nelements(src0);
|
| 76 |
+
|
| 77 |
+
opt_step_adamw_f32_cuda(src0_d, src0_grad_d, src0_grad_m_d, src0_grad_v_d, adamw_params_d, ne, stream);
|
| 78 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/opt-step-adamw.cuh
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
|
| 3 |
+
#define CUDA_OPT_STEP_ADAMW_BLOCK_SIZE 256
|
| 4 |
+
|
| 5 |
+
void ggml_cuda_opt_step_adamw(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
backend/llama.cpp/ggml/src/ggml-cuda/opt-step-sgd.cu
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "ggml-impl.h"
|
| 2 |
+
#include "opt-step-sgd.cuh"
|
| 3 |
+
|
| 4 |
+
#include <cstdint>
|
| 5 |
+
|
| 6 |
+
static __global__ void opt_step_sgd_f32(
|
| 7 |
+
float * __restrict__ x, const float * __restrict__ g,
|
| 8 |
+
const float * __restrict__ pars, const int64_t k) {
|
| 9 |
+
|
| 10 |
+
const int64_t i = (int64_t) blockIdx.x*blockDim.x + threadIdx.x;
|
| 11 |
+
|
| 12 |
+
if (i >= k) {
|
| 13 |
+
return;
|
| 14 |
+
}
|
| 15 |
+
x[i] = x[i] * (1.0f - pars[0] * pars[1]) - pars[0] * g[i];
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
static void opt_step_sgd_f32_cuda(
|
| 19 |
+
float * x, const float * g, const float * __restrict__ pars, const int64_t k, cudaStream_t stream) {
|
| 20 |
+
|
| 21 |
+
const dim3 block_dims(CUDA_OPT_STEP_SGD_BLOCK_SIZE, 1, 1);
|
| 22 |
+
const dim3 block_nums((k + CUDA_OPT_STEP_SGD_BLOCK_SIZE - 1) / CUDA_OPT_STEP_SGD_BLOCK_SIZE, 1, 1);
|
| 23 |
+
opt_step_sgd_f32<<<block_nums, block_dims, 0, stream>>>(x, g, pars, k);
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
void ggml_cuda_opt_step_sgd(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 27 |
+
const ggml_tensor * src0 = dst->src[0];
|
| 28 |
+
const ggml_tensor * src0_grad = dst->src[1];
|
| 29 |
+
const ggml_tensor * params = dst->src[2];
|
| 30 |
+
|
| 31 |
+
GGML_ASSERT(src0->type == GGML_TYPE_F32);
|
| 32 |
+
GGML_ASSERT(src0_grad->type == GGML_TYPE_F32);
|
| 33 |
+
GGML_ASSERT(params->type == GGML_TYPE_F32);
|
| 34 |
+
GGML_ASSERT(ggml_is_contiguous(src0));
|
| 35 |
+
GGML_ASSERT(ggml_is_contiguous(src0_grad));
|
| 36 |
+
GGML_ASSERT(ggml_is_contiguous(params));
|
| 37 |
+
GGML_ASSERT(ggml_are_same_shape(src0, src0_grad));
|
| 38 |
+
GGML_ASSERT(ggml_nelements(params) == 2);
|
| 39 |
+
|
| 40 |
+
float * src0_d = (float *) src0->data;
|
| 41 |
+
const float * src0_grad_d = (const float *) src0_grad->data;
|
| 42 |
+
const float * params_d = (const float *) params->data;
|
| 43 |
+
|
| 44 |
+
cudaStream_t stream = ctx.stream();
|
| 45 |
+
|
| 46 |
+
const int64_t ne = ggml_nelements(src0);
|
| 47 |
+
|
| 48 |
+
opt_step_sgd_f32_cuda(src0_d, src0_grad_d, params_d, ne, stream);
|
| 49 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/opt-step-sgd.cuh
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
|
| 3 |
+
#define CUDA_OPT_STEP_SGD_BLOCK_SIZE 256
|
| 4 |
+
|
| 5 |
+
void ggml_cuda_opt_step_sgd(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
backend/llama.cpp/ggml/src/ggml-cuda/out-prod.cu
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "out-prod.cuh"
|
| 2 |
+
|
| 3 |
+
#include <cstdint>
|
| 4 |
+
|
| 5 |
+
static __global__ void k_compute_out_prod_ptrs(
|
| 6 |
+
const float * src0_d, const float * src1_d, float * dst_d,
|
| 7 |
+
const float ** ptrs_a, const float ** ptrs_b, float ** ptrs_c,
|
| 8 |
+
const int64_t ne2, const int64_t ne3,
|
| 9 |
+
const int64_t dps2, const int64_t dps3,
|
| 10 |
+
const size_t s02, const size_t s03,
|
| 11 |
+
const size_t s12, const size_t s13,
|
| 12 |
+
const size_t s2, const size_t s3) {
|
| 13 |
+
const int64_t i2 = blockIdx.x*blockDim.x + threadIdx.x;
|
| 14 |
+
const int64_t i3 = blockIdx.y*blockDim.y + threadIdx.y;
|
| 15 |
+
|
| 16 |
+
if (i2 >= ne2 || i3 >= ne3) {
|
| 17 |
+
return;
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
const int64_t idx = i3*ne2 + i2;
|
| 21 |
+
|
| 22 |
+
ptrs_a[idx] = src0_d + (i3/dps3)*s03 + (i2/dps2)*s02;
|
| 23 |
+
ptrs_b[idx] = src1_d + i3 *s13 + i2 *s12;
|
| 24 |
+
ptrs_c[idx] = dst_d + i3 *s3 + i2 *s2;
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
void ggml_cuda_out_prod(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 28 |
+
const ggml_tensor * src0 = dst->src[0];
|
| 29 |
+
const ggml_tensor * src1 = dst->src[1];
|
| 30 |
+
|
| 31 |
+
GGML_TENSOR_BINARY_OP_LOCALS
|
| 32 |
+
|
| 33 |
+
GGML_ASSERT(src0->type == GGML_TYPE_F32);
|
| 34 |
+
GGML_ASSERT(src1->type == GGML_TYPE_F32);
|
| 35 |
+
GGML_ASSERT(dst->type == GGML_TYPE_F32);
|
| 36 |
+
|
| 37 |
+
GGML_ASSERT(ne01 == ne11);
|
| 38 |
+
GGML_ASSERT(ne0 == ne00);
|
| 39 |
+
GGML_ASSERT(ne1 == ne10);
|
| 40 |
+
|
| 41 |
+
GGML_ASSERT(ne2 % src0->ne[2] == 0);
|
| 42 |
+
GGML_ASSERT(ne3 % src0->ne[3] == 0);
|
| 43 |
+
|
| 44 |
+
GGML_ASSERT(ne2 == src1->ne[2]);
|
| 45 |
+
GGML_ASSERT(ne3 == src1->ne[3]);
|
| 46 |
+
|
| 47 |
+
const float * src0_d = (const float *) src0->data;
|
| 48 |
+
const float * src1_d = (const float *) src1->data;
|
| 49 |
+
float * dst_d = (float *) dst->data;
|
| 50 |
+
|
| 51 |
+
cudaStream_t stream = ctx.stream();
|
| 52 |
+
cublasHandle_t handle = ctx.cublas_handle();
|
| 53 |
+
|
| 54 |
+
const float alpha = 1.0f;
|
| 55 |
+
const float beta = 0.0f;
|
| 56 |
+
|
| 57 |
+
CUBLAS_CHECK(cublasSetStream(handle, stream));
|
| 58 |
+
|
| 59 |
+
const int64_t lda = nb01 / sizeof(float);
|
| 60 |
+
const int64_t ldc = nb1 / sizeof(float);
|
| 61 |
+
|
| 62 |
+
const bool src1_T = ggml_is_transposed(src1);
|
| 63 |
+
const cublasOperation_t src1_cublas_op = src1_T ? CUBLAS_OP_N : CUBLAS_OP_T;
|
| 64 |
+
const int64_t ldb = (src1_T ? nb10 : nb11) / sizeof(float);
|
| 65 |
+
GGML_ASSERT( (src1_T ? nb11 : nb10) == sizeof(float));
|
| 66 |
+
|
| 67 |
+
// data strides in dimensions 2/3
|
| 68 |
+
const size_t s02 = nb02 / sizeof(float);
|
| 69 |
+
const size_t s03 = nb03 / sizeof(float);
|
| 70 |
+
const size_t s12 = nb12 / sizeof(float);
|
| 71 |
+
const size_t s13 = nb13 / sizeof(float);
|
| 72 |
+
const size_t s2 = nb2 / sizeof(float);
|
| 73 |
+
const size_t s3 = nb3 / sizeof(float);
|
| 74 |
+
|
| 75 |
+
// dps == dst per src0, used for group query attention
|
| 76 |
+
const int64_t dps2 = ne2 / ne02;
|
| 77 |
+
const int64_t dps3 = ne3 / ne03;
|
| 78 |
+
|
| 79 |
+
if (dps2 == 1 && ne2 > 1) {
|
| 80 |
+
// src0 has uniform stride s02 along dim 2; batch the inner loop with a strided GEMM
|
| 81 |
+
GGML_ASSERT(ne2 <= std::numeric_limits<int>::max());
|
| 82 |
+
const int batch_count = (int) ne2;
|
| 83 |
+
for (int64_t i3 = 0; i3 < ne3; ++i3) {
|
| 84 |
+
CUBLAS_CHECK(
|
| 85 |
+
cublasSgemmStridedBatched(handle, CUBLAS_OP_N, src1_cublas_op,
|
| 86 |
+
ne0, ne1, ne01,
|
| 87 |
+
&alpha, src0_d + (i3/dps3)*s03, lda, s02,
|
| 88 |
+
src1_d + i3 *s13, ldb, s12,
|
| 89 |
+
&beta, dst_d + i3 *s3, ldc, s2,
|
| 90 |
+
batch_count));
|
| 91 |
+
}
|
| 92 |
+
} else if (ne2 > 1 || ne3 > 1) {
|
| 93 |
+
// dps2 > 1 (src0 broadcast along dim 2 with non-uniform stride) or multiple GEMMs
|
| 94 |
+
// along dim 3: compute per-GEMM pointers on the device and use a single batched GEMM.
|
| 95 |
+
GGML_ASSERT(ne3 > 0);
|
| 96 |
+
GGML_ASSERT(ne2 <= (int64_t) std::numeric_limits<int>::max() / ne3);
|
| 97 |
+
const int batch_count = (int) (ne2 * ne3);
|
| 98 |
+
|
| 99 |
+
ggml_cuda_pool_alloc<const float *> ptrs_a(ctx.pool(), batch_count);
|
| 100 |
+
ggml_cuda_pool_alloc<const float *> ptrs_b(ctx.pool(), batch_count);
|
| 101 |
+
ggml_cuda_pool_alloc< float *> ptrs_c(ctx.pool(), batch_count);
|
| 102 |
+
|
| 103 |
+
const dim3 block_dims(16, 16);
|
| 104 |
+
const dim3 grid_dims((ne2 + block_dims.x - 1)/block_dims.x, (ne3 + block_dims.y - 1)/block_dims.y);
|
| 105 |
+
k_compute_out_prod_ptrs<<<grid_dims, block_dims, 0, stream>>>(
|
| 106 |
+
src0_d, src1_d, dst_d,
|
| 107 |
+
ptrs_a.get(), ptrs_b.get(), ptrs_c.get(),
|
| 108 |
+
ne2, ne3, dps2, dps3, s02, s03, s12, s13, s2, s3);
|
| 109 |
+
CUDA_CHECK(cudaGetLastError());
|
| 110 |
+
|
| 111 |
+
CUBLAS_CHECK(
|
| 112 |
+
cublasSgemmBatched(handle, CUBLAS_OP_N, src1_cublas_op,
|
| 113 |
+
ne0, ne1, ne01,
|
| 114 |
+
&alpha, ptrs_a.get(), lda,
|
| 115 |
+
ptrs_b.get(), ldb,
|
| 116 |
+
&beta, ptrs_c.get(), ldc,
|
| 117 |
+
batch_count));
|
| 118 |
+
} else {
|
| 119 |
+
// ne2 == 1 && ne3 == 1: single GEMM
|
| 120 |
+
CUBLAS_CHECK(
|
| 121 |
+
cublasSgemm(handle, CUBLAS_OP_N, src1_cublas_op,
|
| 122 |
+
ne0, ne1, ne01,
|
| 123 |
+
&alpha, src0_d, lda,
|
| 124 |
+
src1_d, ldb,
|
| 125 |
+
&beta, dst_d, ldc));
|
| 126 |
+
}
|
| 127 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/out-prod.cuh
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
|
| 3 |
+
void ggml_cuda_out_prod(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
backend/llama.cpp/ggml/src/ggml-cuda/pad.cu
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "pad.cuh"
|
| 2 |
+
|
| 3 |
+
#include <stdint.h>
|
| 4 |
+
|
| 5 |
+
__device__ __forceinline__ int64_t wrap_around(int64_t coord, int64_t size) {
|
| 6 |
+
// + size ensures negatives are handled properly
|
| 7 |
+
return (coord + size) % size;
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
+
static __global__ void pad_f32(const float * src, size_t s00, size_t s01, size_t s02, size_t s03, float * dst,
|
| 11 |
+
const int lp0, const int rp0, const int lp1, const int rp1,
|
| 12 |
+
const int lp2, const int rp2, const int lp3, const int rp3,
|
| 13 |
+
const int ne0, const int ne1, const int ne2, const int ne3,
|
| 14 |
+
const bool circular) {
|
| 15 |
+
// blockIdx.z: i3*ne2+i2
|
| 16 |
+
// blockIdx.y: i1
|
| 17 |
+
// blockIDx.x: i0 / CUDA_PAD_BLOCK_SIZE
|
| 18 |
+
// gridDim.y: ne1
|
| 19 |
+
int i0 = threadIdx.x + blockIdx.x * blockDim.x;
|
| 20 |
+
int i1 = blockIdx.y;
|
| 21 |
+
int i2 = blockIdx.z % ne2;
|
| 22 |
+
int i3 = blockIdx.z / ne2;
|
| 23 |
+
|
| 24 |
+
if (i0 >= ne0 || i1 >= ne1 || i2 >= ne2 || i3 >= ne3) {
|
| 25 |
+
return;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
const int64_t dst_idx = i3 * (ne0 * ne1 * ne2) + i2 * (ne0 * ne1) + i1 * ne0 + i0;
|
| 29 |
+
|
| 30 |
+
if (!circular) {
|
| 31 |
+
if ((i0 >= lp0 && i0 < ne0 - rp0) && (i1 >= lp1 && i1 < ne1 - rp1) && (i2 >= lp2 && i2 < ne2 - rp2) &&
|
| 32 |
+
(i3 >= lp3 && i3 < ne3 - rp3)) {
|
| 33 |
+
const int64_t i00 = i0 - lp0;
|
| 34 |
+
const int64_t i01 = i1 - lp1;
|
| 35 |
+
const int64_t i02 = i2 - lp2;
|
| 36 |
+
const int64_t i03 = i3 - lp3;
|
| 37 |
+
|
| 38 |
+
const int64_t src_idx = i03 * s03 + i02 * s02 + i01 * s01 + i00 * s00;
|
| 39 |
+
|
| 40 |
+
dst[dst_idx] = src[src_idx];
|
| 41 |
+
} else {
|
| 42 |
+
dst[dst_idx] = 0.0f;
|
| 43 |
+
}
|
| 44 |
+
}
|
| 45 |
+
// circular means on a torus, so x and y wrap around
|
| 46 |
+
else {
|
| 47 |
+
const int64_t ne00 = ne0 - lp0 - rp0;
|
| 48 |
+
const int64_t ne01 = ne1 - lp1 - rp1;
|
| 49 |
+
const int64_t ne02 = ne2 - lp2 - rp2;
|
| 50 |
+
const int64_t ne03 = ne3 - lp3 - rp3;
|
| 51 |
+
|
| 52 |
+
const int64_t i00 = wrap_around(i0 - lp0, ne00);
|
| 53 |
+
const int64_t i01 = wrap_around(i1 - lp1, ne01);
|
| 54 |
+
const int64_t i02 = wrap_around(i2 - lp2, ne02);
|
| 55 |
+
const int64_t i03 = wrap_around(i3 - lp3, ne03);
|
| 56 |
+
|
| 57 |
+
const int64_t src_idx = i03 * s03 + i02 * s02 + i01 * s01 + i00 * s00;
|
| 58 |
+
|
| 59 |
+
dst[dst_idx] = src[src_idx];
|
| 60 |
+
}
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
static void pad_f32_cuda(const float * src, size_t s00, size_t s01, size_t s02, size_t s03, float * dst,
|
| 65 |
+
const int lp0, const int rp0, const int lp1, const int rp1,
|
| 66 |
+
const int lp2, const int rp2, const int lp3, const int rp3,
|
| 67 |
+
const int ne0, const int ne1, const int ne2, const int ne3,
|
| 68 |
+
const bool circular, cudaStream_t stream) {
|
| 69 |
+
int num_blocks = (ne0 + CUDA_PAD_BLOCK_SIZE - 1) / CUDA_PAD_BLOCK_SIZE;
|
| 70 |
+
dim3 gridDim(num_blocks, ne1, ne2 * ne3);
|
| 71 |
+
pad_f32<<<gridDim, CUDA_PAD_BLOCK_SIZE, 0, stream>>>(src, s00, s01, s02, s03, dst,
|
| 72 |
+
lp0, rp0, lp1, rp1, lp2, rp2, lp3, rp3,
|
| 73 |
+
ne0, ne1, ne2, ne3, circular);
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
void ggml_cuda_op_pad(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 77 |
+
const ggml_tensor * src0 = dst->src[0];
|
| 78 |
+
const float * src0_d = (const float *) src0->data;
|
| 79 |
+
float * dst_d = (float *) dst->data;
|
| 80 |
+
cudaStream_t stream = ctx.stream();
|
| 81 |
+
|
| 82 |
+
GGML_TENSOR_UNARY_OP_LOCALS;
|
| 83 |
+
|
| 84 |
+
GGML_ASSERT(src0->type == GGML_TYPE_F32);
|
| 85 |
+
GGML_ASSERT(dst->type == GGML_TYPE_F32);
|
| 86 |
+
|
| 87 |
+
const int32_t lp0 = ((const int32_t *) (dst->op_params))[0];
|
| 88 |
+
const int32_t rp0 = ((const int32_t *) (dst->op_params))[1];
|
| 89 |
+
const int32_t lp1 = ((const int32_t *) (dst->op_params))[2];
|
| 90 |
+
const int32_t rp1 = ((const int32_t *) (dst->op_params))[3];
|
| 91 |
+
const int32_t lp2 = ((const int32_t *) (dst->op_params))[4];
|
| 92 |
+
const int32_t rp2 = ((const int32_t *) (dst->op_params))[5];
|
| 93 |
+
const int32_t lp3 = ((const int32_t *) (dst->op_params))[6];
|
| 94 |
+
const int32_t rp3 = ((const int32_t *) (dst->op_params))[7];
|
| 95 |
+
const int32_t circular = ((const int32_t *) (dst->op_params))[8];
|
| 96 |
+
|
| 97 |
+
const size_t s00 = nb00 / ggml_type_size(src0->type);
|
| 98 |
+
const size_t s01 = nb01 / ggml_type_size(src0->type);
|
| 99 |
+
const size_t s02 = nb02 / ggml_type_size(src0->type);
|
| 100 |
+
const size_t s03 = nb03 / ggml_type_size(src0->type);
|
| 101 |
+
|
| 102 |
+
pad_f32_cuda(src0_d, s00, s01, s02, s03, dst_d,
|
| 103 |
+
lp0, rp0, lp1, rp1, lp2, rp2, lp3, rp3,
|
| 104 |
+
dst->ne[0], dst->ne[1], dst->ne[2], dst->ne[3],
|
| 105 |
+
(bool) circular, stream);
|
| 106 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/pad.cuh
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
|
| 3 |
+
#define CUDA_PAD_BLOCK_SIZE 256
|
| 4 |
+
|
| 5 |
+
void ggml_cuda_op_pad(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
backend/llama.cpp/ggml/src/ggml-cuda/pad_reflect_1d.cu
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "pad_reflect_1d.cuh"
|
| 2 |
+
|
| 3 |
+
static __global__ __launch_bounds__(CUDA_PAD_REFLECT_1D_BLOCK_SIZE, 1) void
|
| 4 |
+
pad_reflect_1d_kernel_f32(
|
| 5 |
+
const void * __restrict__ src0,
|
| 6 |
+
void * __restrict__ dst,
|
| 7 |
+
const int64_t ne0,
|
| 8 |
+
const int64_t ne00,
|
| 9 |
+
const uint3 ne01,
|
| 10 |
+
const int64_t ne02,
|
| 11 |
+
const int64_t ne03,
|
| 12 |
+
const int64_t nb00,
|
| 13 |
+
const int64_t nb01,
|
| 14 |
+
const int64_t nb02,
|
| 15 |
+
const int64_t nb03,
|
| 16 |
+
const int64_t nb0,
|
| 17 |
+
const int64_t nb1,
|
| 18 |
+
const int64_t nb2,
|
| 19 |
+
const int64_t nb3,
|
| 20 |
+
const int p0,
|
| 21 |
+
const int p1) {
|
| 22 |
+
const int64_t i3 = blockIdx.z;
|
| 23 |
+
const int64_t i2 = blockIdx.y;
|
| 24 |
+
|
| 25 |
+
const uint2 div_mod_packed = fast_div_modulo(blockIdx.x, ne01);
|
| 26 |
+
const int64_t tile1 = div_mod_packed.y; // i1
|
| 27 |
+
const int64_t tile0 = div_mod_packed.x; // nth i0 tile
|
| 28 |
+
const int64_t i1 = tile1;
|
| 29 |
+
const int64_t i0 = threadIdx.x + tile0 * blockDim.x;
|
| 30 |
+
|
| 31 |
+
// ne01.z is original value of unpacked ne01 (see init_fastdiv_values in common.cuh)
|
| 32 |
+
if (i0 >= ne0 || i1 >= ne01.z || i2 >= ne02 || i3 >= ne03) {
|
| 33 |
+
return;
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
const char * src0_ptr = (const char *) src0 + i3 * nb03 + i2 * nb02 + i1 * nb01;
|
| 37 |
+
char * dst_ptr = (char *) dst + i3 * nb3 + i2 * nb2 + i1 * nb1;
|
| 38 |
+
|
| 39 |
+
const int64_t rel_i0 = i0 - p0; // relative i0 in src0
|
| 40 |
+
int64_t src_idx;
|
| 41 |
+
|
| 42 |
+
if (rel_i0 < 0) {
|
| 43 |
+
// Left padding - reflect
|
| 44 |
+
src_idx = -rel_i0;
|
| 45 |
+
} else if (rel_i0 < ne00) {
|
| 46 |
+
// Middle - copy
|
| 47 |
+
src_idx = rel_i0;
|
| 48 |
+
} else {
|
| 49 |
+
// Right padding - reflect
|
| 50 |
+
src_idx = 2 * ne00 - 2 - rel_i0;
|
| 51 |
+
}
|
| 52 |
+
const float value = *(const float *) (src0_ptr + src_idx * nb00);
|
| 53 |
+
*(float *) (dst_ptr + i0 * nb0) = value;
|
| 54 |
+
|
| 55 |
+
GGML_UNUSED(p1);
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
void ggml_cuda_op_pad_reflect_1d(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 59 |
+
const ggml_tensor * src0 = dst->src[0];
|
| 60 |
+
cudaStream_t stream = ctx.stream();
|
| 61 |
+
|
| 62 |
+
GGML_ASSERT(src0->type == GGML_TYPE_F32);
|
| 63 |
+
GGML_ASSERT(dst->type == GGML_TYPE_F32);
|
| 64 |
+
|
| 65 |
+
const int32_t * opts = (const int32_t *) dst->op_params;
|
| 66 |
+
const int p0 = opts[0];
|
| 67 |
+
const int p1 = opts[1];
|
| 68 |
+
|
| 69 |
+
const int64_t ne00 = src0->ne[0];
|
| 70 |
+
const int64_t ne01 = src0->ne[1];
|
| 71 |
+
const uint3 ne01_packed = init_fastdiv_values(ne01);
|
| 72 |
+
const int64_t ne02 = src0->ne[2];
|
| 73 |
+
const int64_t ne03 = src0->ne[3];
|
| 74 |
+
|
| 75 |
+
const int64_t ne0 = dst->ne[0];
|
| 76 |
+
|
| 77 |
+
// sanity: padded length matches
|
| 78 |
+
GGML_ASSERT(ne0 == ne00 + p0 + p1);
|
| 79 |
+
|
| 80 |
+
constexpr int64_t bx = CUDA_PAD_REFLECT_1D_BLOCK_SIZE; // threads per block (x)
|
| 81 |
+
const int64_t tiles0 = (ne0 + bx - 1) / bx; // number of tiles along i0
|
| 82 |
+
// grid.x covers i1 and all tiles of i0: [ne01 * tiles0]
|
| 83 |
+
// grid.y covers i2: [ne02]
|
| 84 |
+
// grid.z covers i3: [ne03]
|
| 85 |
+
const dim3 grid_dims((unsigned) (ne01 * tiles0), (unsigned) ne02, (unsigned) ne03);
|
| 86 |
+
const dim3 block_dims((unsigned) bx, 1, 1);
|
| 87 |
+
|
| 88 |
+
pad_reflect_1d_kernel_f32<<<grid_dims, block_dims, 0, stream>>>(
|
| 89 |
+
src0->data, dst->data, ne0, ne00, ne01_packed, ne02, ne03, src0->nb[0], src0->nb[1], src0->nb[2], src0->nb[3],
|
| 90 |
+
dst->nb[0], dst->nb[1], dst->nb[2], dst->nb[3], p0, p1);
|
| 91 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/pad_reflect_1d.cuh
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
|
| 3 |
+
#define CUDA_PAD_REFLECT_1D_BLOCK_SIZE 256
|
| 4 |
+
|
| 5 |
+
void ggml_cuda_op_pad_reflect_1d(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
backend/llama.cpp/ggml/src/ggml-cuda/pool2d.cu
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "pool2d.cuh"
|
| 2 |
+
|
| 3 |
+
template <typename Ti, typename To>
|
| 4 |
+
static __global__ void pool2d_nchw_kernel(
|
| 5 |
+
const int ih, const int iw, const int oh, const int ow,
|
| 6 |
+
const int kh, const int kw, const int sh, const int sw,
|
| 7 |
+
const int ph, const int pw, const int parallel_elements,
|
| 8 |
+
const Ti* src, To* dst, const enum ggml_op_pool op) {
|
| 9 |
+
int idx = threadIdx.x + blockIdx.x * blockDim.x;
|
| 10 |
+
if (idx >= parallel_elements) {
|
| 11 |
+
return;
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
const int I_HW = ih * iw;
|
| 15 |
+
const int O_HW = oh * ow;
|
| 16 |
+
const int nc = idx / O_HW;
|
| 17 |
+
const int cur_oh = idx % O_HW / ow;
|
| 18 |
+
const int cur_ow = idx % O_HW % ow;
|
| 19 |
+
const Ti* i_ptr = src + nc * I_HW;
|
| 20 |
+
To* o_ptr = dst + nc * O_HW;
|
| 21 |
+
const int start_h = cur_oh * sh - ph;
|
| 22 |
+
const int bh = max(0, start_h);
|
| 23 |
+
const int eh = min(ih, start_h + kh);
|
| 24 |
+
const int start_w = cur_ow * sw - pw;
|
| 25 |
+
const int bw = max(0, start_w);
|
| 26 |
+
const int ew = min(iw, start_w + kw);
|
| 27 |
+
const To scale = 1. / (kh * kw);
|
| 28 |
+
To res = 0;
|
| 29 |
+
|
| 30 |
+
switch (op) {
|
| 31 |
+
case GGML_OP_POOL_AVG: res = 0; break;
|
| 32 |
+
case GGML_OP_POOL_MAX: res = -FLT_MAX; break;
|
| 33 |
+
default: assert(false);
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
for (int i = bh; i < eh; i += 1) {
|
| 37 |
+
for (int j = bw; j < ew; j += 1) {
|
| 38 |
+
#if __CUDA_ARCH__ >= 350
|
| 39 |
+
Ti cur = __ldg(i_ptr + i * iw + j);
|
| 40 |
+
#else
|
| 41 |
+
Ti cur = i_ptr[i * iw + j];
|
| 42 |
+
#endif
|
| 43 |
+
switch (op) {
|
| 44 |
+
case GGML_OP_POOL_AVG: res += cur * scale; break;
|
| 45 |
+
case GGML_OP_POOL_MAX: res = max(res, (To)cur); break;
|
| 46 |
+
default: assert(false);
|
| 47 |
+
}
|
| 48 |
+
}
|
| 49 |
+
}
|
| 50 |
+
o_ptr[cur_oh * ow + cur_ow] = res;
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
static void pool2d_nchw_kernel_f32_f32_cuda(
|
| 54 |
+
const int ih, const int iw, const int oh, const int ow,
|
| 55 |
+
const int kh, const int kw, const int sh, const int sw,
|
| 56 |
+
const int ph, const int pw, const int parallel_elements,
|
| 57 |
+
const float * src, float * dst, const enum ggml_op_pool op,
|
| 58 |
+
cudaStream_t stream) {
|
| 59 |
+
|
| 60 |
+
const int num_blocks = (parallel_elements + CUDA_POOL2D_BLOCK_SIZE - 1) / CUDA_POOL2D_BLOCK_SIZE;
|
| 61 |
+
dim3 block_nums(num_blocks);
|
| 62 |
+
pool2d_nchw_kernel<<<block_nums, CUDA_POOL2D_BLOCK_SIZE, 0, stream>>>(ih, iw, oh, ow, kh, kw, sh, sw, ph, pw, parallel_elements, src, dst, op);
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
void ggml_cuda_op_pool2d(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 66 |
+
const ggml_tensor * src0 = dst->src[0];
|
| 67 |
+
const float * src0_d = (const float *)src0->data;
|
| 68 |
+
float * dst_d = (float *)dst->data;
|
| 69 |
+
cudaStream_t stream = ctx.stream();
|
| 70 |
+
|
| 71 |
+
GGML_ASSERT(src0->type == GGML_TYPE_F32);
|
| 72 |
+
GGML_ASSERT( dst->type == GGML_TYPE_F32);
|
| 73 |
+
|
| 74 |
+
const int32_t * opts = (const int32_t *)dst->op_params;
|
| 75 |
+
enum ggml_op_pool op = static_cast<ggml_op_pool>(opts[0]);
|
| 76 |
+
const int k0 = opts[1];
|
| 77 |
+
const int k1 = opts[2];
|
| 78 |
+
const int s0 = opts[3];
|
| 79 |
+
const int s1 = opts[4];
|
| 80 |
+
const int p0 = opts[5];
|
| 81 |
+
const int p1 = opts[6];
|
| 82 |
+
|
| 83 |
+
const int64_t IH = src0->ne[1];
|
| 84 |
+
const int64_t IW = src0->ne[0];
|
| 85 |
+
|
| 86 |
+
const int64_t N = dst->ne[3];
|
| 87 |
+
const int64_t OC = dst->ne[2];
|
| 88 |
+
const int64_t OH = dst->ne[1];
|
| 89 |
+
const int64_t OW = dst->ne[0];
|
| 90 |
+
|
| 91 |
+
const int parallel_elements = N * OC * OH * OW;
|
| 92 |
+
|
| 93 |
+
pool2d_nchw_kernel_f32_f32_cuda(IH, IW, OH, OW, k1, k0, s1, s0, p1, p0, parallel_elements, src0_d, dst_d, op, stream);
|
| 94 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/pool2d.cuh
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
|
| 3 |
+
#define CUDA_POOL2D_BLOCK_SIZE 256
|
| 4 |
+
|
| 5 |
+
void ggml_cuda_op_pool2d(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
backend/llama.cpp/ggml/src/ggml-cuda/quantize.cu
ADDED
|
@@ -0,0 +1,450 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "quantize.cuh"
|
| 2 |
+
#include <cstdint>
|
| 3 |
+
|
| 4 |
+
__launch_bounds__(CUDA_QUANTIZE_BLOCK_SIZE, 1)
|
| 5 |
+
static __global__ void quantize_q8_1(
|
| 6 |
+
const float * x_ptr, void * vy_ptr,
|
| 7 |
+
const int64_t ne00, const int64_t s01, const int64_t s02, const int64_t s03,
|
| 8 |
+
const int64_t ne0, const uint32_t ne1, const uint3 ne2) {
|
| 9 |
+
ggml_cuda_pdl_lc();
|
| 10 |
+
const float * GGML_CUDA_RESTRICT x = x_ptr;
|
| 11 |
+
void * GGML_CUDA_RESTRICT vy = vy_ptr;
|
| 12 |
+
const int64_t i0 = (int64_t)blockDim.x*blockIdx.x + threadIdx.x;
|
| 13 |
+
|
| 14 |
+
if (i0 >= ne0) {
|
| 15 |
+
return;
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
const int64_t i3 = fastdiv(blockIdx.z, ne2);
|
| 19 |
+
const int64_t i2 = blockIdx.z - i3*ne2.z;
|
| 20 |
+
const int64_t i1 = blockIdx.y;
|
| 21 |
+
|
| 22 |
+
const int64_t & i00 = i0;
|
| 23 |
+
const int64_t & i01 = i1;
|
| 24 |
+
const int64_t & i02 = i2;
|
| 25 |
+
const int64_t & i03 = i3;
|
| 26 |
+
|
| 27 |
+
const int64_t i_cont = ((i3*ne2.z + i2) * ne1 + i1) * ne0 + i0;
|
| 28 |
+
|
| 29 |
+
block_q8_1 * y = (block_q8_1 *) vy;
|
| 30 |
+
|
| 31 |
+
const int64_t ib = i_cont / QK8_1; // block index
|
| 32 |
+
const int64_t iqs = i_cont % QK8_1; // quant index
|
| 33 |
+
|
| 34 |
+
ggml_cuda_pdl_sync();
|
| 35 |
+
const float xi = i0 < ne00 ? x[i03*s03 + i02*s02 + i01*s01 + i00] : 0.0f;
|
| 36 |
+
float amax = fabsf(xi);
|
| 37 |
+
float sum = xi;
|
| 38 |
+
|
| 39 |
+
amax = warp_reduce_max<QK8_1>(amax);
|
| 40 |
+
sum = warp_reduce_sum<QK8_1>(sum);
|
| 41 |
+
|
| 42 |
+
const float d = amax / 127.0f;
|
| 43 |
+
const int8_t q = amax == 0.0f ? 0 : roundf(xi / d);
|
| 44 |
+
|
| 45 |
+
y[ib].qs[iqs] = q;
|
| 46 |
+
|
| 47 |
+
if (iqs > 0) {
|
| 48 |
+
return;
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
y[ib].ds = make_half2(d, sum);
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
__device__ __forceinline__ uint8_t compute_e8m0_scale(float amax) {
|
| 55 |
+
if (!(amax > 0.0f)) {
|
| 56 |
+
return 0;
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
// FP4 E2M1: max exponent (unbiased) is 2.
|
| 60 |
+
constexpr int FP4_E2M1_EMAX = 2;
|
| 61 |
+
|
| 62 |
+
const float e = log2f(amax);
|
| 63 |
+
|
| 64 |
+
// "even" -> round-to-nearest integer, ties-to-even
|
| 65 |
+
const int e_int = __float2int_rn(e);
|
| 66 |
+
|
| 67 |
+
const int shared_exp = e_int - FP4_E2M1_EMAX;
|
| 68 |
+
|
| 69 |
+
int biased = shared_exp + 127;
|
| 70 |
+
|
| 71 |
+
biased = max(biased, 0);
|
| 72 |
+
biased = min(biased, 254);
|
| 73 |
+
|
| 74 |
+
return static_cast<uint8_t>(biased);
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
static __global__ void quantize_mmq_nvfp4(
|
| 79 |
+
const float * __restrict__ x, const int32_t * __restrict__ ids, void * __restrict__ vy,
|
| 80 |
+
const int64_t ne00, const int64_t s01, const int64_t s02, const int64_t s03,
|
| 81 |
+
const int64_t ne0, const int64_t ne1, const int64_t ne2) {
|
| 82 |
+
#if defined(BLACKWELL_MMA_AVAILABLE)
|
| 83 |
+
|
| 84 |
+
const int64_t i0_base = ((int64_t) blockDim.x * blockIdx.y + threadIdx.x) * QK_NVFP4_SUB;
|
| 85 |
+
if (i0_base >= ne0) {
|
| 86 |
+
return;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
const int64_t i1 = blockIdx.x;
|
| 90 |
+
const int64_t i2 = blockIdx.z % ne2;
|
| 91 |
+
const int64_t i3 = blockIdx.z / ne2;
|
| 92 |
+
const int64_t i01 = ids ? ids[i1] : i1;
|
| 93 |
+
const int64_t k_block = i0_base / QK_K;
|
| 94 |
+
const int64_t blocks_per_col = (ne0 + QK_K - 1) / QK_K;
|
| 95 |
+
if (k_block >= blocks_per_col) {
|
| 96 |
+
return;
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
const int64_t ib = blockIdx.z * ((int64_t) blocks_per_col * ne1) + k_block * ne1 + blockIdx.x;
|
| 100 |
+
block_fp4_mmq * y = (block_fp4_mmq *) vy;
|
| 101 |
+
block_fp4_mmq * yb = y + ib;
|
| 102 |
+
|
| 103 |
+
const int sub = (i0_base % QK_K) / QK_NVFP4_SUB;
|
| 104 |
+
|
| 105 |
+
float vals_raw[QK_NVFP4_SUB];
|
| 106 |
+
float amax_raw = 0.0f;
|
| 107 |
+
const int64_t base_idx = i3 * s03 + i2 * s02 + i01 * s01;
|
| 108 |
+
#pragma unroll
|
| 109 |
+
for (int k = 0; k < QK_NVFP4_SUB; k++) {
|
| 110 |
+
const int64_t i00 = i0_base + k;
|
| 111 |
+
if (i00 < ne00) {
|
| 112 |
+
const float v = x[base_idx + i00];
|
| 113 |
+
vals_raw[k] = v;
|
| 114 |
+
amax_raw = fmaxf(amax_raw, fabsf(v));
|
| 115 |
+
} else {
|
| 116 |
+
vals_raw[k] = 0.0f;
|
| 117 |
+
}
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
static constexpr int test_offsets[5] = { 0, -1, 1, -2, 2};
|
| 121 |
+
const int first_fp8_code = (int) ggml_cuda_fp32_to_ue4m3(amax_raw / 6.0f);
|
| 122 |
+
|
| 123 |
+
float best_err = FLT_MAX;
|
| 124 |
+
uint8_t fp8_code = 0;
|
| 125 |
+
float subblock_scale = 0.0f;
|
| 126 |
+
|
| 127 |
+
#pragma unroll // Check +/- 2 to find best code to reduce NVFP4 activation loss. Negligible overhead on Blackwell.
|
| 128 |
+
for (int i = 0; i < 5; i++) {
|
| 129 |
+
const int test_code = first_fp8_code + test_offsets[i];
|
| 130 |
+
if (test_code < 0 || test_code > 0x7e) {
|
| 131 |
+
continue;
|
| 132 |
+
}
|
| 133 |
+
const uint8_t code = (uint8_t) test_code;
|
| 134 |
+
const float test_scale = ggml_cuda_ue4m3_to_fp32(code);
|
| 135 |
+
const float test_inv_scale = test_scale > 0.0f ? 0.5f / test_scale : 0.0f;
|
| 136 |
+
float cur_err = 0.0f;
|
| 137 |
+
#pragma unroll
|
| 138 |
+
for (int k = 0; k < QK_NVFP4_SUB; ++k) {
|
| 139 |
+
const float v = vals_raw[k];
|
| 140 |
+
const uint8_t q = ggml_cuda_float_to_fp4_e2m1(v, test_inv_scale);
|
| 141 |
+
const float err_diff = fabsf(v) - fabsf(kvalues_mxfp4[q & 0x7]) * test_scale;
|
| 142 |
+
cur_err = fmaf(err_diff, err_diff, cur_err);
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
if (cur_err < best_err) {
|
| 146 |
+
best_err = cur_err;
|
| 147 |
+
fp8_code = test_code;
|
| 148 |
+
subblock_scale = test_scale;
|
| 149 |
+
}
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
const float inv_scale = subblock_scale > 0.0f ? 0.5f / subblock_scale : 0.0f;
|
| 153 |
+
uint32_t q0 = 0;
|
| 154 |
+
uint32_t q1 = 0;
|
| 155 |
+
#pragma unroll // this is faster than the previous __nv_fp4x4_e2m1
|
| 156 |
+
for (int k = 0; k < QK_NVFP4_SUB / 4; ++k) {
|
| 157 |
+
q0 |= (uint32_t) ggml_cuda_float_to_fp4_e2m1(vals_raw[k + 0], inv_scale) << (8 * k);
|
| 158 |
+
q0 |= (uint32_t) ggml_cuda_float_to_fp4_e2m1(vals_raw[k + 8], inv_scale) << (8 * k + 4);
|
| 159 |
+
q1 |= (uint32_t) ggml_cuda_float_to_fp4_e2m1(vals_raw[k + 4], inv_scale) << (8 * k);
|
| 160 |
+
q1 |= (uint32_t) ggml_cuda_float_to_fp4_e2m1(vals_raw[k + 12], inv_scale) << (8 * k + 4);
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
uint32_t * yqs = reinterpret_cast<uint32_t *>(yb->qs);
|
| 164 |
+
yqs[2 * sub + 0] = q0;
|
| 165 |
+
yqs[2 * sub + 1] = q1;
|
| 166 |
+
reinterpret_cast<uint8_t *>(yb->d4)[sub] = fp8_code;
|
| 167 |
+
#else
|
| 168 |
+
NO_DEVICE_CODE; // This is for Blackwell NVFP4 activations only.
|
| 169 |
+
#endif // defined(BLACKWELL_MMA_AVAILABLE)
|
| 170 |
+
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
// quantize values in the format mxfp4 is stored which is interleaved nibbles
|
| 174 |
+
// i.e. a block a0-a31 is represented as a0a16,a1a17 ...a15a31
|
| 175 |
+
static __global__ void quantize_mmq_mxfp4(const float * __restrict__ x,
|
| 176 |
+
const int32_t * __restrict__ ids,
|
| 177 |
+
void * __restrict__ vy,
|
| 178 |
+
const int64_t ne00,
|
| 179 |
+
const int64_t s01,
|
| 180 |
+
const int64_t s02,
|
| 181 |
+
const int64_t s03,
|
| 182 |
+
const int64_t ne0,
|
| 183 |
+
const int ne1,
|
| 184 |
+
const int ne2) {
|
| 185 |
+
constexpr int vals_per_scale = 32;
|
| 186 |
+
constexpr int vals_per_warp = 2 * vals_per_scale; // Each warp processes 2 blocks of 32 = 64 values
|
| 187 |
+
|
| 188 |
+
const int warp_id = threadIdx.y;
|
| 189 |
+
const int lane_id_32 = threadIdx.x;
|
| 190 |
+
|
| 191 |
+
const int nwarps = blockDim.y;
|
| 192 |
+
|
| 193 |
+
const int64_t warp_start_offset = (blockIdx.y * nwarps + warp_id) * vals_per_warp;
|
| 194 |
+
|
| 195 |
+
if (warp_start_offset >= ne0) {
|
| 196 |
+
return;
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
const int64_t i1 = blockIdx.x;
|
| 200 |
+
const int64_t i2 = blockIdx.z % ne2;
|
| 201 |
+
const int64_t i3 = blockIdx.z / ne2;
|
| 202 |
+
|
| 203 |
+
ggml_cuda_pdl_sync();
|
| 204 |
+
const int64_t i01 = ids ? ids[i1] : i1;
|
| 205 |
+
const int64_t i02 = i2;
|
| 206 |
+
const int64_t i03 = i3;
|
| 207 |
+
|
| 208 |
+
block_fp4_mmq * y = (block_fp4_mmq *) vy;
|
| 209 |
+
|
| 210 |
+
const int64_t block_fp4_mmq_size = 8 * QK_MXFP4; // 256 values
|
| 211 |
+
const int64_t ib0 = blockIdx.z * ((int64_t) ne1 * (ne0 / block_fp4_mmq_size));
|
| 212 |
+
const int64_t ib = ib0 + (warp_start_offset / block_fp4_mmq_size) * ne1 + blockIdx.x;
|
| 213 |
+
const int64_t quad_idx_in_block = (warp_start_offset % block_fp4_mmq_size) / vals_per_warp;
|
| 214 |
+
|
| 215 |
+
const int group_id = lane_id_32 / 4;
|
| 216 |
+
const int lane_in_group = lane_id_32 % 4;
|
| 217 |
+
const int base = group_id * 2;
|
| 218 |
+
char2 * yqs2 = (char2 *) y[ib].qs;
|
| 219 |
+
|
| 220 |
+
const int64_t base_pos = i03 * s03 + i02 * s02 + i01 * s01;
|
| 221 |
+
|
| 222 |
+
uint8_t scales[2];
|
| 223 |
+
|
| 224 |
+
#pragma unroll
|
| 225 |
+
for (int b = 0; b < 2; ++b) {
|
| 226 |
+
const int64_t i0 = warp_start_offset + b * vals_per_scale + lane_id_32;
|
| 227 |
+
const float xi = (i0 < ne00) ? x[base_pos + i0] : 0.0f;
|
| 228 |
+
|
| 229 |
+
float amax = fabsf(xi);
|
| 230 |
+
#pragma unroll
|
| 231 |
+
for (int mask = 16; mask > 0; mask >>= 1) {
|
| 232 |
+
amax = fmaxf(amax, __shfl_xor_sync(0xFFFFFFFF, amax, mask, WARP_SIZE));
|
| 233 |
+
}
|
| 234 |
+
|
| 235 |
+
const uint8_t e = compute_e8m0_scale(amax);
|
| 236 |
+
scales[b] = e;
|
| 237 |
+
const float inv_s = (amax == 0.0f) ? 0.0f : __frcp_rn(ggml_cuda_e8m0_to_fp32(e));
|
| 238 |
+
|
| 239 |
+
#if CUDART_VERSION >= 12080
|
| 240 |
+
const float scaled_val = xi * inv_s;
|
| 241 |
+
|
| 242 |
+
const float val0 = __shfl_sync(0xFFFFFFFF, scaled_val, base, WARP_SIZE);
|
| 243 |
+
const float val1 = __shfl_sync(0xFFFFFFFF, scaled_val, base + 16, WARP_SIZE);
|
| 244 |
+
const float val2 = __shfl_sync(0xFFFFFFFF, scaled_val, base + 1, WARP_SIZE);
|
| 245 |
+
const float val3 = __shfl_sync(0xFFFFFFFF, scaled_val, base + 17, WARP_SIZE);
|
| 246 |
+
|
| 247 |
+
if (lane_in_group == 0) {
|
| 248 |
+
__nv_fp4x4_e2m1 fp4_packed(make_float4(val0, val1, val2, val3));
|
| 249 |
+
|
| 250 |
+
yqs2[quad_idx_in_block * 16 + b * 8 + group_id] = *(char2 *) &fp4_packed;
|
| 251 |
+
}
|
| 252 |
+
#else
|
| 253 |
+
// Fallback: manual FP4 conversion using LUT
|
| 254 |
+
const uint8_t q_val = ggml_cuda_float_to_fp4_e2m1(xi, inv_s);
|
| 255 |
+
|
| 256 |
+
const uint8_t q_lo_0 = __shfl_sync(0xFFFFFFFF, q_val, base, WARP_SIZE);
|
| 257 |
+
const uint8_t q_lo_1 = __shfl_sync(0xFFFFFFFF, q_val, base + 1, WARP_SIZE);
|
| 258 |
+
const uint8_t q_hi_0 = __shfl_sync(0xFFFFFFFF, q_val, base + 16, WARP_SIZE);
|
| 259 |
+
const uint8_t q_hi_1 = __shfl_sync(0xFFFFFFFF, q_val, base + 17, WARP_SIZE);
|
| 260 |
+
|
| 261 |
+
if (lane_in_group == 0) {
|
| 262 |
+
char2 q;
|
| 263 |
+
q.x = (q_hi_0 << 4) | q_lo_0;
|
| 264 |
+
q.y = (q_hi_1 << 4) | q_lo_1;
|
| 265 |
+
yqs2[quad_idx_in_block * 16 + b * 8 + group_id] = q;
|
| 266 |
+
}
|
| 267 |
+
#endif // CUDART_VERSION >= 12080
|
| 268 |
+
}
|
| 269 |
+
|
| 270 |
+
if (lane_id_32 == 0) {
|
| 271 |
+
// Store 2 scales packed into 1 uint32
|
| 272 |
+
y[ib].d4[quad_idx_in_block] = (scales[1] << 8) | scales[0];
|
| 273 |
+
}
|
| 274 |
+
}
|
| 275 |
+
|
| 276 |
+
template <mmq_q8_1_ds_layout ds_layout>
|
| 277 |
+
static __global__ void quantize_mmq_q8_1(
|
| 278 |
+
const float * __restrict__ x, const int32_t * __restrict__ ids, void * __restrict__ vy,
|
| 279 |
+
const int64_t ne00, const int64_t s01, const int64_t s02, const int64_t s03,
|
| 280 |
+
const int64_t ne0, const int ne1, const int ne2) {
|
| 281 |
+
|
| 282 |
+
constexpr int vals_per_scale = ds_layout == MMQ_Q8_1_DS_LAYOUT_D2S6 ? 64 : 32;
|
| 283 |
+
constexpr int vals_per_sum = ds_layout == MMQ_Q8_1_DS_LAYOUT_D2S6 ? 16 : 32;
|
| 284 |
+
|
| 285 |
+
const int64_t i0 = ((int64_t)blockDim.x*blockIdx.y + threadIdx.x)*4;
|
| 286 |
+
|
| 287 |
+
if (i0 >= ne0) {
|
| 288 |
+
return;
|
| 289 |
+
}
|
| 290 |
+
|
| 291 |
+
const int64_t i1 = blockIdx.x;
|
| 292 |
+
const int64_t i2 = blockIdx.z % ne2;
|
| 293 |
+
const int64_t i3 = blockIdx.z / ne2;
|
| 294 |
+
|
| 295 |
+
const int64_t i00 = i0;
|
| 296 |
+
ggml_cuda_pdl_sync();
|
| 297 |
+
const int64_t i01 = ids ? ids[i1] : i1;
|
| 298 |
+
const int64_t i02 = i2;
|
| 299 |
+
const int64_t i03 = i3;
|
| 300 |
+
|
| 301 |
+
const float4 * x4 = (const float4 *) x;
|
| 302 |
+
|
| 303 |
+
block_q8_1_mmq * y = (block_q8_1_mmq *) vy;
|
| 304 |
+
|
| 305 |
+
const int64_t ib0 = blockIdx.z*((int64_t)gridDim.x*gridDim.y*blockDim.x/QK8_1); // first block of channel
|
| 306 |
+
const int64_t ib = ib0 + (i0 / (4*QK8_1))*ne1 + blockIdx.x; // block index in channel
|
| 307 |
+
const int64_t iqs = i0 % (4*QK8_1); // quant index in block
|
| 308 |
+
|
| 309 |
+
// Load 4 floats per thread and calculate max. abs. value between them:
|
| 310 |
+
const float4 xi = i0 < ne00 ? x4[(i03*s03 + i02*s02 + i01*s01 + i00)/4] : make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
| 311 |
+
float amax = fabsf(xi.x);
|
| 312 |
+
amax = fmaxf(amax, fabsf(xi.y));
|
| 313 |
+
amax = fmaxf(amax, fabsf(xi.z));
|
| 314 |
+
amax = fmaxf(amax, fabsf(xi.w));
|
| 315 |
+
|
| 316 |
+
// Exchange max. abs. value between vals_per_scale/4 threads.
|
| 317 |
+
#pragma unroll
|
| 318 |
+
for (int offset = vals_per_scale/8; offset > 0; offset >>= 1) {
|
| 319 |
+
amax = fmaxf(amax, __shfl_xor_sync(0xFFFFFFFF, amax, offset, WARP_SIZE));
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
float sum;
|
| 323 |
+
if (ds_layout != MMQ_Q8_1_DS_LAYOUT_D4) {
|
| 324 |
+
sum = xi.x + xi.y + xi.z + xi.w;
|
| 325 |
+
|
| 326 |
+
// Calculate sums across vals_per_sum/4 threads.
|
| 327 |
+
#pragma unroll
|
| 328 |
+
for (int offset = vals_per_sum/8; offset > 0; offset >>= 1) {
|
| 329 |
+
sum += __shfl_xor_sync(0xFFFFFFFF, sum, offset, WARP_SIZE);
|
| 330 |
+
}
|
| 331 |
+
}
|
| 332 |
+
|
| 333 |
+
const float d_inv = 127.0f / amax;
|
| 334 |
+
char4 q;
|
| 335 |
+
q.x = roundf(xi.x*d_inv);
|
| 336 |
+
q.y = roundf(xi.y*d_inv);
|
| 337 |
+
q.z = roundf(xi.z*d_inv);
|
| 338 |
+
q.w = roundf(xi.w*d_inv);
|
| 339 |
+
|
| 340 |
+
// Write back 4 int8 values as a single 32 bit value for better memory bandwidth:
|
| 341 |
+
char4 * yqs4 = (char4 *) y[ib].qs;
|
| 342 |
+
yqs4[iqs/4] = q;
|
| 343 |
+
|
| 344 |
+
if (ds_layout == MMQ_Q8_1_DS_LAYOUT_D2S6) {
|
| 345 |
+
if (iqs % 16 != 0 || iqs >= 96) {
|
| 346 |
+
return;
|
| 347 |
+
}
|
| 348 |
+
|
| 349 |
+
y[ib].d2s6[2 + iqs/16] = sum;
|
| 350 |
+
|
| 351 |
+
if (iqs % 64 != 0) {
|
| 352 |
+
return;
|
| 353 |
+
}
|
| 354 |
+
|
| 355 |
+
const float d = 1.0f / d_inv;
|
| 356 |
+
|
| 357 |
+
y[ib].d2s6[iqs/64] = d;
|
| 358 |
+
|
| 359 |
+
return;
|
| 360 |
+
}
|
| 361 |
+
|
| 362 |
+
if (iqs % 32 != 0) {
|
| 363 |
+
return;
|
| 364 |
+
}
|
| 365 |
+
|
| 366 |
+
const float d = 1.0f / d_inv;
|
| 367 |
+
|
| 368 |
+
if (ds_layout == MMQ_Q8_1_DS_LAYOUT_DS4) {
|
| 369 |
+
y[ib].ds4[iqs/32] = make_half2(d, sum);
|
| 370 |
+
} else {
|
| 371 |
+
y[ib].d4[iqs/32] = d;
|
| 372 |
+
}
|
| 373 |
+
}
|
| 374 |
+
|
| 375 |
+
void quantize_row_q8_1_cuda(
|
| 376 |
+
const float * x, const int32_t * ids, void * vy, const ggml_type type_src0,
|
| 377 |
+
const int64_t ne00, const int64_t s01, const int64_t s02, const int64_t s03,
|
| 378 |
+
const int64_t ne0, const int64_t ne1, const int64_t ne2, const int64_t ne3, cudaStream_t stream) {
|
| 379 |
+
GGML_ASSERT(!ids);
|
| 380 |
+
GGML_ASSERT(ne0 % QK8_1 == 0);
|
| 381 |
+
|
| 382 |
+
const uint3 ne2_fastdiv = init_fastdiv_values(ne2);
|
| 383 |
+
|
| 384 |
+
const int64_t block_num_x = (ne0 + CUDA_QUANTIZE_BLOCK_SIZE - 1) / CUDA_QUANTIZE_BLOCK_SIZE;
|
| 385 |
+
const dim3 num_blocks(block_num_x, ne1, ne2*ne3);
|
| 386 |
+
const dim3 block_size(CUDA_QUANTIZE_BLOCK_SIZE, 1, 1);
|
| 387 |
+
const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params(num_blocks, block_size, 0, stream);
|
| 388 |
+
ggml_cuda_kernel_launch(quantize_q8_1, launch_params, x, vy, ne00, s01, s02, s03, ne0, ne1, ne2_fastdiv);
|
| 389 |
+
GGML_UNUSED(type_src0);
|
| 390 |
+
}
|
| 391 |
+
|
| 392 |
+
void quantize_mmq_q8_1_cuda(
|
| 393 |
+
const float * x, const int32_t * ids, void * vy, const ggml_type type_src0,
|
| 394 |
+
const int64_t ne00, const int64_t s01, const int64_t s02, const int64_t s03,
|
| 395 |
+
const int64_t ne0, const int64_t ne1, const int64_t ne2, const int64_t ne3, cudaStream_t stream) {
|
| 396 |
+
GGML_ASSERT(ne00 % 4 == 0);
|
| 397 |
+
GGML_ASSERT(ne0 % (4*QK8_1) == 0);
|
| 398 |
+
|
| 399 |
+
// ne1 tends to assume the highest values, therefore use it as the "x" dimension of the CUDA grid:
|
| 400 |
+
const int64_t block_num_y = (ne0 + 4*CUDA_QUANTIZE_BLOCK_SIZE_MMQ - 1) / (4*CUDA_QUANTIZE_BLOCK_SIZE_MMQ);
|
| 401 |
+
const dim3 num_blocks(ne1, block_num_y, ne2*ne3);
|
| 402 |
+
const dim3 block_size(CUDA_QUANTIZE_BLOCK_SIZE_MMQ, 1, 1);
|
| 403 |
+
switch (mmq_get_q8_1_ds_layout(type_src0)) {
|
| 404 |
+
case MMQ_Q8_1_DS_LAYOUT_D4:
|
| 405 |
+
quantize_mmq_q8_1<MMQ_Q8_1_DS_LAYOUT_D4>
|
| 406 |
+
<<<num_blocks, block_size, 0, stream>>>(x, ids, vy, ne00, s01, s02, s03, ne0, ne1, ne2);
|
| 407 |
+
break;
|
| 408 |
+
case MMQ_Q8_1_DS_LAYOUT_DS4:
|
| 409 |
+
quantize_mmq_q8_1<MMQ_Q8_1_DS_LAYOUT_DS4>
|
| 410 |
+
<<<num_blocks, block_size, 0, stream>>>(x, ids, vy, ne00, s01, s02, s03, ne0, ne1, ne2);
|
| 411 |
+
break;
|
| 412 |
+
case MMQ_Q8_1_DS_LAYOUT_D2S6:
|
| 413 |
+
quantize_mmq_q8_1<MMQ_Q8_1_DS_LAYOUT_D2S6>
|
| 414 |
+
<<<num_blocks, block_size, 0, stream>>>(x, ids, vy, ne00, s01, s02, s03, ne0, ne1, ne2);
|
| 415 |
+
break;
|
| 416 |
+
default:
|
| 417 |
+
GGML_ABORT("fatal error");
|
| 418 |
+
break;
|
| 419 |
+
}
|
| 420 |
+
}
|
| 421 |
+
|
| 422 |
+
void quantize_mmq_fp4_cuda(
|
| 423 |
+
const float * x, const int32_t * ids, void * vy, const ggml_type type_src0,
|
| 424 |
+
const int64_t ne00, const int64_t s01, const int64_t s02, const int64_t s03,
|
| 425 |
+
const int64_t ne0, const int64_t ne1, const int64_t ne2, const int64_t ne3, cudaStream_t stream) {
|
| 426 |
+
GGML_ASSERT(type_src0 == GGML_TYPE_MXFP4 || type_src0 == GGML_TYPE_NVFP4);
|
| 427 |
+
GGML_ASSERT(ne0 > 0);
|
| 428 |
+
|
| 429 |
+
if (type_src0 == GGML_TYPE_NVFP4) {
|
| 430 |
+
GGML_ASSERT(ne00 % QK_NVFP4 == 0);
|
| 431 |
+
constexpr int nvfp4_block_size = 128;
|
| 432 |
+
const int64_t block_num_y = (ne0 + QK_NVFP4_SUB * nvfp4_block_size - 1) / (QK_NVFP4_SUB * nvfp4_block_size);
|
| 433 |
+
const dim3 block_size(nvfp4_block_size, 1, 1);
|
| 434 |
+
const dim3 num_blocks(ne1, block_num_y, ne2 * ne3);
|
| 435 |
+
quantize_mmq_nvfp4<<<num_blocks, block_size, 0, stream>>>(
|
| 436 |
+
x, ids, vy, ne00, s01, s02, s03, ne0, ne1, ne2);
|
| 437 |
+
} else {
|
| 438 |
+
GGML_ASSERT(ne0 % (2 * QK_MXFP4) == 0);
|
| 439 |
+
|
| 440 |
+
constexpr int nwarps = 8;
|
| 441 |
+
constexpr int vals_per_warp = 2 * QK_MXFP4;
|
| 442 |
+
constexpr int vals_per_block = nwarps * vals_per_warp;
|
| 443 |
+
|
| 444 |
+
const int64_t block_num_y = (ne0 + vals_per_block - 1) / vals_per_block;
|
| 445 |
+
const dim3 num_blocks(ne1, block_num_y, ne2 * ne3);
|
| 446 |
+
const dim3 block_size(WARP_SIZE, nwarps, 1);
|
| 447 |
+
|
| 448 |
+
quantize_mmq_mxfp4<<<num_blocks, block_size, 0, stream>>>(x, ids, vy, ne00, s01, s02, s03, ne0, ne1, ne2);
|
| 449 |
+
}
|
| 450 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/quantize.cuh
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include "common.cuh"
|
| 4 |
+
#include "mmq.cuh"
|
| 5 |
+
|
| 6 |
+
#include <cstdint>
|
| 7 |
+
|
| 8 |
+
#define CUDA_QUANTIZE_BLOCK_SIZE 256
|
| 9 |
+
#define CUDA_QUANTIZE_BLOCK_SIZE_MMQ 128
|
| 10 |
+
|
| 11 |
+
static_assert(MATRIX_ROW_PADDING % CUDA_QUANTIZE_BLOCK_SIZE == 0, "Risk of out-of-bounds access.");
|
| 12 |
+
static_assert(MATRIX_ROW_PADDING % (4*CUDA_QUANTIZE_BLOCK_SIZE_MMQ) == 0, "Risk of out-of-bounds access.");
|
| 13 |
+
|
| 14 |
+
typedef void (*quantize_cuda_t)(
|
| 15 |
+
const float * x, const int32_t * ids, void * vy,
|
| 16 |
+
ggml_type type_src0, int64_t ne00, int64_t s01, int64_t s02, int64_t s03,
|
| 17 |
+
int64_t ne0, int64_t ne1, int64_t ne2, int64_t ne3, cudaStream_t stream);
|
| 18 |
+
|
| 19 |
+
void quantize_row_q8_1_cuda(
|
| 20 |
+
const float * x, const int32_t * ids, void * vy,
|
| 21 |
+
ggml_type type_src0, int64_t ne00, int64_t s01, int64_t s02, int64_t s03,
|
| 22 |
+
int64_t ne0, int64_t ne1, int64_t ne2, int64_t ne3, cudaStream_t stream);
|
| 23 |
+
|
| 24 |
+
void quantize_mmq_q8_1_cuda(
|
| 25 |
+
const float * x, const int32_t * ids, void * vy,
|
| 26 |
+
ggml_type type_src0, int64_t ne00, int64_t s01, int64_t s02, int64_t s03,
|
| 27 |
+
int64_t ne0, int64_t ne1, int64_t ne2, int64_t ne3, cudaStream_t stream);
|
| 28 |
+
|
| 29 |
+
void quantize_mmq_fp4_cuda(const float * x,
|
| 30 |
+
const int32_t * ids,
|
| 31 |
+
void * vy,
|
| 32 |
+
ggml_type type_src0,
|
| 33 |
+
int64_t ne00,
|
| 34 |
+
int64_t s01,
|
| 35 |
+
int64_t s02,
|
| 36 |
+
int64_t s03,
|
| 37 |
+
int64_t ne0,
|
| 38 |
+
int64_t ne1,
|
| 39 |
+
int64_t ne2,
|
| 40 |
+
int64_t ne3,
|
| 41 |
+
cudaStream_t stream);
|
backend/llama.cpp/ggml/src/ggml-cuda/reduce_rows.cuh
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
|
| 3 |
+
// Row reduction kernel template - compute sum (norm=false) or mean (norm=true)
|
| 4 |
+
template <bool norm>
|
| 5 |
+
static __global__ void reduce_rows_f32(const float * x_ptr, float * dst_ptr, const int ncols) {
|
| 6 |
+
const float * GGML_CUDA_RESTRICT x = x_ptr;
|
| 7 |
+
float * GGML_CUDA_RESTRICT dst = dst_ptr;
|
| 8 |
+
const int row = blockIdx.x;
|
| 9 |
+
const int col = threadIdx.x;
|
| 10 |
+
|
| 11 |
+
float sum = 0.0f;
|
| 12 |
+
const int num_unroll = 8;
|
| 13 |
+
float temp[num_unroll];
|
| 14 |
+
float sum_temp[num_unroll] = { 0.0f };
|
| 15 |
+
|
| 16 |
+
ggml_cuda_pdl_sync();
|
| 17 |
+
for (int i = col; i < ncols;) {
|
| 18 |
+
for (int j = 0; j < num_unroll; ++j) {
|
| 19 |
+
if (i < ncols) {
|
| 20 |
+
temp[j] = x[row * ncols + i];
|
| 21 |
+
} else {
|
| 22 |
+
temp[j] = 0;
|
| 23 |
+
}
|
| 24 |
+
i += blockDim.x;
|
| 25 |
+
}
|
| 26 |
+
for (int j = 0; j < num_unroll; ++j) {
|
| 27 |
+
sum_temp[j] += temp[j];
|
| 28 |
+
}
|
| 29 |
+
}
|
| 30 |
+
for (int j = 0; j < num_unroll; ++j) {
|
| 31 |
+
sum += sum_temp[j];
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
// sum up partial sums
|
| 35 |
+
__shared__ float shared_vals[32];
|
| 36 |
+
sum = block_reduce<block_reduce_method::SUM>(sum, shared_vals);
|
| 37 |
+
|
| 38 |
+
if (col != 0) {
|
| 39 |
+
return;
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
dst[row] = norm ? sum / ncols : sum;
|
| 43 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/roll.cu
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "ggml-cuda/common.cuh"
|
| 2 |
+
#include "roll.cuh"
|
| 3 |
+
|
| 4 |
+
static __forceinline__ __device__ int64_t wrap_index(const int64_t idx, const int64_t ne) {
|
| 5 |
+
if (idx < 0) {
|
| 6 |
+
return idx + ne;
|
| 7 |
+
}
|
| 8 |
+
if (idx >= ne) {
|
| 9 |
+
return idx - ne;
|
| 10 |
+
}
|
| 11 |
+
return idx;
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
static __global__ void roll_f32_cuda(const float * __restrict__ src,
|
| 15 |
+
float * __restrict__ dst,
|
| 16 |
+
const int64_t ne00,
|
| 17 |
+
const int64_t ne01,
|
| 18 |
+
const int64_t ne02,
|
| 19 |
+
const int64_t ne03,
|
| 20 |
+
const int s0,
|
| 21 |
+
const int s1,
|
| 22 |
+
const int s2,
|
| 23 |
+
const int s3) {
|
| 24 |
+
const int64_t idx = int64_t(blockDim.x) * blockIdx.x + threadIdx.x;
|
| 25 |
+
const int64_t n_elements = ne00 * ne01 * ne02 * ne03;
|
| 26 |
+
|
| 27 |
+
if (idx >= n_elements) {
|
| 28 |
+
return;
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
const int64_t i0 = idx % ne00;
|
| 32 |
+
const int64_t i1 = (idx / ne00) % ne01;
|
| 33 |
+
const int64_t i2 = (idx / (ne00 * ne01)) % ne02;
|
| 34 |
+
const int64_t i3 = (idx / (ne00 * ne01 * ne02)) % ne03;
|
| 35 |
+
|
| 36 |
+
const int64_t d0 = wrap_index(i0 - s0, ne00);
|
| 37 |
+
const int64_t d1 = wrap_index(i1 - s1, ne01);
|
| 38 |
+
const int64_t d2 = wrap_index(i2 - s2, ne02);
|
| 39 |
+
const int64_t d3 = wrap_index(i3 - s3, ne03);
|
| 40 |
+
|
| 41 |
+
dst[i3 * (ne00 * ne01 * ne02) + i2 * (ne01 * ne00) + i1 * ne00 + i0] =
|
| 42 |
+
src[d3 * (ne00 * ne01 * ne02) + d2 * (ne01 * ne00) + d1 * ne00 + d0];
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
void ggml_cuda_op_roll(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 46 |
+
int s0 = dst->op_params[0];
|
| 47 |
+
int s1 = dst->op_params[1];
|
| 48 |
+
int s2 = dst->op_params[2];
|
| 49 |
+
int s3 = dst->op_params[3];
|
| 50 |
+
|
| 51 |
+
const ggml_tensor * src0 = dst->src[0];
|
| 52 |
+
const float * src0_d = (const float *) dst->src[0]->data;
|
| 53 |
+
float * dst_d = (float *) dst->data;
|
| 54 |
+
|
| 55 |
+
GGML_TENSOR_UNARY_OP_LOCALS;
|
| 56 |
+
|
| 57 |
+
GGML_ASSERT(dst->src[0]->type == GGML_TYPE_F32);
|
| 58 |
+
GGML_ASSERT(ggml_are_same_shape(dst->src[0], dst));
|
| 59 |
+
|
| 60 |
+
cudaStream_t stream = ctx.stream();
|
| 61 |
+
|
| 62 |
+
int64_t sz = (ne00 * ne01 * ne02 * ne03);
|
| 63 |
+
int64_t num_blocks = (sz + CUDA_ROLL_BLOCK_SIZE - 1) / CUDA_ROLL_BLOCK_SIZE;
|
| 64 |
+
|
| 65 |
+
roll_f32_cuda<<<num_blocks, CUDA_ROLL_BLOCK_SIZE, 0, stream>>>(
|
| 66 |
+
src0_d, dst_d, ne00, ne01, ne02, ne03, s0, s1, s2, s3);
|
| 67 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/roll.cuh
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
|
| 3 |
+
#define CUDA_ROLL_BLOCK_SIZE 256
|
| 4 |
+
|
| 5 |
+
void ggml_cuda_op_roll(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
backend/llama.cpp/ggml/src/ggml-cuda/rope.cu
ADDED
|
@@ -0,0 +1,672 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "convert.cuh"
|
| 2 |
+
#include "ggml-cuda/common.cuh"
|
| 3 |
+
#include "ggml.h"
|
| 4 |
+
#include "rope.cuh"
|
| 5 |
+
|
| 6 |
+
struct rope_corr_dims {
|
| 7 |
+
float v[2];
|
| 8 |
+
};
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
struct mrope_sections {
|
| 12 |
+
int v[4];
|
| 13 |
+
};
|
| 14 |
+
|
| 15 |
+
static __device__ float rope_yarn_ramp(const float low, const float high, const int i0) {
|
| 16 |
+
const float y = (i0 / 2 - low) / max(0.001f, high - low);
|
| 17 |
+
return 1.0f - min(1.0f, max(0.0f, y));
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
// YaRN algorithm based on LlamaYaRNScaledRotaryEmbedding.py from https://github.com/jquesnelle/yarn
|
| 21 |
+
// MIT licensed. Copyright (c) 2023 Jeffrey Quesnelle and Bowen Peng.
|
| 22 |
+
template<bool forward>
|
| 23 |
+
static __device__ void rope_yarn(
|
| 24 |
+
const float theta_extrap, const float freq_scale, const rope_corr_dims corr_dims, const int64_t i0, const float ext_factor,
|
| 25 |
+
float mscale, float & cos_theta, float & sin_theta) {
|
| 26 |
+
// Get n-d rotational scaling corrected for extrapolation
|
| 27 |
+
float theta_interp = freq_scale * theta_extrap;
|
| 28 |
+
float theta = theta_interp;
|
| 29 |
+
if (ext_factor != 0.0f) {
|
| 30 |
+
float ramp_mix = rope_yarn_ramp(corr_dims.v[0], corr_dims.v[1], i0) * ext_factor;
|
| 31 |
+
theta = theta_interp * (1 - ramp_mix) + theta_extrap * ramp_mix;
|
| 32 |
+
|
| 33 |
+
// Get n-d magnitude scaling corrected for interpolation
|
| 34 |
+
mscale *= 1.0f + 0.1f * logf(1.0f / freq_scale);
|
| 35 |
+
}
|
| 36 |
+
cos_theta = cosf(theta) * mscale;
|
| 37 |
+
sin_theta = sinf(theta) * mscale;
|
| 38 |
+
if (!forward) {
|
| 39 |
+
sin_theta *= -1.0f;
|
| 40 |
+
}
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
template <bool forward, bool has_ff, typename T, typename D>
|
| 44 |
+
static __global__ void rope_norm(const T * x,
|
| 45 |
+
D * dst,
|
| 46 |
+
const int ne00,
|
| 47 |
+
const int ne01,
|
| 48 |
+
const int ne02,
|
| 49 |
+
const int s01,
|
| 50 |
+
const int s02,
|
| 51 |
+
const int s03,
|
| 52 |
+
const int s1,
|
| 53 |
+
const int s2,
|
| 54 |
+
const int s3,
|
| 55 |
+
const int n_dims,
|
| 56 |
+
const int32_t * pos,
|
| 57 |
+
const float freq_scale,
|
| 58 |
+
const float ext_factor,
|
| 59 |
+
const float attn_factor,
|
| 60 |
+
const rope_corr_dims corr_dims,
|
| 61 |
+
const float theta_scale,
|
| 62 |
+
const float * freq_factors,
|
| 63 |
+
const int64_t * row_indices,
|
| 64 |
+
const int set_rows_stride) {
|
| 65 |
+
const int i0 = 2*(blockDim.y*blockIdx.y + threadIdx.y);
|
| 66 |
+
|
| 67 |
+
if (i0 >= ne00) {
|
| 68 |
+
return;
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
const int row_dst = blockDim.x*blockIdx.x + threadIdx.x;
|
| 72 |
+
|
| 73 |
+
const uint32_t i3 = row_dst / (ne01 * ne02);
|
| 74 |
+
const uint32_t i2 = (row_dst - i3 * ne01 * ne02) / ne01;
|
| 75 |
+
const uint32_t i1 = row_dst - i3 * ne01 * ne02 - i2 * ne01;
|
| 76 |
+
|
| 77 |
+
int idst = i0 + i1 * s1 + i2 * s2 + i3 * s3;
|
| 78 |
+
const int ix = i0 + i1 * s01 + i2 * s02 + i3 * s03;
|
| 79 |
+
// Fusion optimization: ROPE + VIEW + SET_ROWS.
|
| 80 |
+
// The rope output is viewed as a 1D tensor and offset based on a row index in row_indices.
|
| 81 |
+
if (set_rows_stride != 0) {
|
| 82 |
+
idst = i1 * s1 + i0;
|
| 83 |
+
idst += row_indices[i2] * set_rows_stride;
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
const auto & store_coaelsced = [&](float x0, float x1) {
|
| 87 |
+
if constexpr (std::is_same_v<float, D>) {
|
| 88 |
+
float2 v = make_float2(x0, x1);
|
| 89 |
+
ggml_cuda_memcpy_1<8>(dst + idst, &v);
|
| 90 |
+
} else if constexpr (std::is_same_v<half, D>) {
|
| 91 |
+
half2 v = make_half2(x0, x1);
|
| 92 |
+
ggml_cuda_memcpy_1<4>(dst + idst, &v);
|
| 93 |
+
}
|
| 94 |
+
};
|
| 95 |
+
if (i0 >= n_dims) {
|
| 96 |
+
store_coaelsced(x[ix + 0], x[ix + 1]);
|
| 97 |
+
return;
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
const float theta_base = pos[i2]*powf(theta_scale, i0/2.0f);
|
| 101 |
+
|
| 102 |
+
const float freq_factor = has_ff ? freq_factors[i0/2] : 1.0f;
|
| 103 |
+
|
| 104 |
+
float cos_theta;
|
| 105 |
+
float sin_theta;
|
| 106 |
+
|
| 107 |
+
rope_yarn<forward>(theta_base/freq_factor, freq_scale, corr_dims, i0, ext_factor, attn_factor, cos_theta, sin_theta);
|
| 108 |
+
|
| 109 |
+
const float x0 = x[ix + 0];
|
| 110 |
+
const float x1 = x[ix + 1];
|
| 111 |
+
|
| 112 |
+
store_coaelsced(x0 * cos_theta - x1 * sin_theta, x0 * sin_theta + x1 * cos_theta);
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
template <bool forward, bool has_ff, typename T, typename D>
|
| 116 |
+
static __global__ void rope_neox(const T * x,
|
| 117 |
+
D * dst,
|
| 118 |
+
const int ne00,
|
| 119 |
+
const int ne01,
|
| 120 |
+
const int ne02,
|
| 121 |
+
const int s01,
|
| 122 |
+
const int s02,
|
| 123 |
+
const int s03,
|
| 124 |
+
const int s1,
|
| 125 |
+
const int s2,
|
| 126 |
+
const int s3,
|
| 127 |
+
const int n_dims,
|
| 128 |
+
const int32_t * pos,
|
| 129 |
+
const float freq_scale,
|
| 130 |
+
const float ext_factor,
|
| 131 |
+
const float attn_factor,
|
| 132 |
+
const rope_corr_dims corr_dims,
|
| 133 |
+
const float theta_scale,
|
| 134 |
+
const float * freq_factors,
|
| 135 |
+
const int64_t * row_indices,
|
| 136 |
+
const int set_rows_stride) {
|
| 137 |
+
ggml_cuda_pdl_lc();
|
| 138 |
+
const int i0 = 2*(blockDim.y*blockIdx.y + threadIdx.y);
|
| 139 |
+
|
| 140 |
+
if (i0 >= ne00) {
|
| 141 |
+
return;
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
const int row_dst = blockDim.x*blockIdx.x + threadIdx.x;
|
| 145 |
+
|
| 146 |
+
const uint32_t i3 = row_dst / (ne01 * ne02);
|
| 147 |
+
const uint32_t i2 = (row_dst - i3 * ne01 * ne02) / ne01;
|
| 148 |
+
const uint32_t i1 = row_dst - i3 * ne01 * ne02 - i2 * ne01;
|
| 149 |
+
|
| 150 |
+
int idst = i0 / 2 + i1 * s1 + i2 * s2 + i3 * s3;
|
| 151 |
+
const int ix = i0 / 2 + i1 * s01 + i2 * s02 + i3 * s03;
|
| 152 |
+
ggml_cuda_pdl_sync();
|
| 153 |
+
|
| 154 |
+
// Fusion optimization: ROPE + VIEW + SET_ROWS.
|
| 155 |
+
// The rope output is viewed as a 1D tensor and offset based on a row index in row_indices.
|
| 156 |
+
if (set_rows_stride != 0) {
|
| 157 |
+
idst = i1 * s1 + i0 / 2;
|
| 158 |
+
idst += row_indices[i2] * set_rows_stride;
|
| 159 |
+
}
|
| 160 |
+
|
| 161 |
+
if (i0 >= n_dims) {
|
| 162 |
+
dst[idst + i0 / 2 + 0] = ggml_cuda_cast<D>(x[ix + i0 / 2 + 0]);
|
| 163 |
+
dst[idst + i0 / 2 + 1] = ggml_cuda_cast<D>(x[ix + i0 / 2 + 1]);
|
| 164 |
+
|
| 165 |
+
return;
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
const float theta_base = pos[i2]*powf(theta_scale, i0/2.0f);
|
| 169 |
+
|
| 170 |
+
const float freq_factor = has_ff ? freq_factors[i0/2] : 1.0f;
|
| 171 |
+
|
| 172 |
+
float cos_theta;
|
| 173 |
+
float sin_theta;
|
| 174 |
+
|
| 175 |
+
rope_yarn<forward>(theta_base/freq_factor, freq_scale, corr_dims, i0, ext_factor, attn_factor, cos_theta, sin_theta);
|
| 176 |
+
|
| 177 |
+
const float x0 = x[ix + 0];
|
| 178 |
+
const float x1 = x[ix + n_dims/2];
|
| 179 |
+
|
| 180 |
+
dst[idst + 0] = ggml_cuda_cast<D>(x0 * cos_theta - x1 * sin_theta);
|
| 181 |
+
dst[idst + n_dims / 2] = ggml_cuda_cast<D>(x0 * sin_theta + x1 * cos_theta);
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
template <bool forward, bool has_ff, typename T>
|
| 185 |
+
static __global__ void rope_multi(const T * x,
|
| 186 |
+
T * dst,
|
| 187 |
+
const int ne00,
|
| 188 |
+
const int ne01,
|
| 189 |
+
const int ne02,
|
| 190 |
+
const int s01,
|
| 191 |
+
const int s02,
|
| 192 |
+
const int s03,
|
| 193 |
+
const int s1,
|
| 194 |
+
const int s2,
|
| 195 |
+
const int s3,
|
| 196 |
+
const int n_dims,
|
| 197 |
+
const int32_t * pos,
|
| 198 |
+
const float freq_scale,
|
| 199 |
+
const float ext_factor,
|
| 200 |
+
const float attn_factor,
|
| 201 |
+
const rope_corr_dims corr_dims,
|
| 202 |
+
const float theta_scale,
|
| 203 |
+
const float * freq_factors,
|
| 204 |
+
const mrope_sections sections,
|
| 205 |
+
const bool is_imrope) {
|
| 206 |
+
const int i0 = 2 * (blockDim.y * blockIdx.y + threadIdx.y);
|
| 207 |
+
|
| 208 |
+
if (i0 >= ne00) {
|
| 209 |
+
return;
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
const int row_dst = blockDim.x*blockIdx.x + threadIdx.x;
|
| 213 |
+
|
| 214 |
+
const uint32_t i3 = row_dst / (ne01 * ne02);
|
| 215 |
+
const uint32_t i2 = (row_dst - i3 * ne01 * ne02) / ne01;
|
| 216 |
+
const uint32_t i1 = row_dst - i3 * ne01 * ne02 - i2 * ne01;
|
| 217 |
+
|
| 218 |
+
int idst = i0 / 2 + i1 * s1 + i2 * s2 + i3 * s3;
|
| 219 |
+
const int ix = i0 / 2 + i1 * s01 + i2 * s02 + i3 * s03;
|
| 220 |
+
|
| 221 |
+
ggml_cuda_pdl_sync();
|
| 222 |
+
if (i0 >= n_dims) {
|
| 223 |
+
dst[idst + i0/2 + 0] = x[ix + i0/2 + 0];
|
| 224 |
+
dst[idst + i0/2 + 1] = x[ix + i0/2 + 1];
|
| 225 |
+
|
| 226 |
+
return;
|
| 227 |
+
}
|
| 228 |
+
|
| 229 |
+
const int sect_dims = sections.v[0] + sections.v[1] + sections.v[2] + sections.v[3];
|
| 230 |
+
const int sec_w = sections.v[1] + sections.v[0];
|
| 231 |
+
const int sector = (i0 / 2) % sect_dims;
|
| 232 |
+
|
| 233 |
+
float theta_base = 0.0;
|
| 234 |
+
if (is_imrope) {
|
| 235 |
+
if (sector % 3 == 1 && sector < 3 * sections.v[1]) { // h
|
| 236 |
+
theta_base = pos[i2 + ne02 * 1] * powf(theta_scale, i0 / 2.0f);
|
| 237 |
+
} else if (sector % 3 == 2 && sector < 3 * sections.v[2]) { // w
|
| 238 |
+
theta_base = pos[i2 + ne02 * 2] * powf(theta_scale, i0 / 2.0f);
|
| 239 |
+
} else if (sector % 3 == 0 && sector < 3 * sections.v[0]) { // t
|
| 240 |
+
theta_base = pos[i2] * powf(theta_scale, i0 / 2.0f);
|
| 241 |
+
} else {
|
| 242 |
+
theta_base = pos[i2 + ne02 * 3] * powf(theta_scale, i0 / 2.0f);
|
| 243 |
+
}
|
| 244 |
+
} else {
|
| 245 |
+
if (sector < sections.v[0]) {
|
| 246 |
+
theta_base = pos[i2] * powf(theta_scale, i0 / 2.0f);
|
| 247 |
+
} else if (sector >= sections.v[0] && sector < sec_w) {
|
| 248 |
+
theta_base = pos[i2 + ne02 * 1] * powf(theta_scale, i0 / 2.0f);
|
| 249 |
+
} else if (sector >= sec_w && sector < sec_w + sections.v[2]) {
|
| 250 |
+
theta_base = pos[i2 + ne02 * 2] * powf(theta_scale, i0 / 2.0f);
|
| 251 |
+
} else if (sector >= sec_w + sections.v[2]) {
|
| 252 |
+
theta_base = pos[i2 + ne02 * 3] * powf(theta_scale, i0 / 2.0f);
|
| 253 |
+
}
|
| 254 |
+
}
|
| 255 |
+
|
| 256 |
+
const float freq_factor = has_ff ? freq_factors[i0/2] : 1.0f;
|
| 257 |
+
|
| 258 |
+
float cos_theta;
|
| 259 |
+
float sin_theta;
|
| 260 |
+
|
| 261 |
+
rope_yarn<forward>(theta_base/freq_factor, freq_scale, corr_dims, i0, ext_factor, attn_factor, cos_theta, sin_theta);
|
| 262 |
+
|
| 263 |
+
const float x0 = x[ix + 0];
|
| 264 |
+
const float x1 = x[ix + n_dims/2];
|
| 265 |
+
|
| 266 |
+
dst[idst + 0] = x0*cos_theta - x1*sin_theta;
|
| 267 |
+
dst[idst + n_dims/2] = x0*sin_theta + x1*cos_theta;
|
| 268 |
+
}
|
| 269 |
+
|
| 270 |
+
template <bool forward, bool has_ff, typename T>
|
| 271 |
+
static __global__ void rope_vision(const T * x,
|
| 272 |
+
T * dst,
|
| 273 |
+
const int ne00,
|
| 274 |
+
const int ne01,
|
| 275 |
+
const int ne02,
|
| 276 |
+
const int s01,
|
| 277 |
+
const int s02,
|
| 278 |
+
const int s03,
|
| 279 |
+
const int s1,
|
| 280 |
+
const int s2,
|
| 281 |
+
const int s3,
|
| 282 |
+
const int n_dims,
|
| 283 |
+
const int32_t * pos,
|
| 284 |
+
const float freq_scale,
|
| 285 |
+
const float ext_factor,
|
| 286 |
+
const float attn_factor,
|
| 287 |
+
const rope_corr_dims corr_dims,
|
| 288 |
+
const float theta_scale,
|
| 289 |
+
const float * freq_factors,
|
| 290 |
+
const mrope_sections sections) {
|
| 291 |
+
const int i0 = 2*(blockDim.y*blockIdx.y + threadIdx.y);
|
| 292 |
+
|
| 293 |
+
if (i0 >= ne00) {
|
| 294 |
+
return;
|
| 295 |
+
}
|
| 296 |
+
|
| 297 |
+
const int row_dst = blockDim.x*blockIdx.x + threadIdx.x;
|
| 298 |
+
|
| 299 |
+
const uint32_t i3 = row_dst / (ne01 * ne02);
|
| 300 |
+
const uint32_t i2 = (row_dst - i3 * ne01 * ne02) / ne01;
|
| 301 |
+
const uint32_t i1 = row_dst - i3 * ne01 * ne02 - i2 * ne01;
|
| 302 |
+
|
| 303 |
+
int idst = i0 / 2 + i1 * s1 + i2 * s2 + i3 * s3;
|
| 304 |
+
const int ix = i0 / 2 + i1 * s01 + i2 * s02 + i3 * s03;
|
| 305 |
+
|
| 306 |
+
ggml_cuda_pdl_sync();
|
| 307 |
+
const int sect_dims = sections.v[0] + sections.v[1];
|
| 308 |
+
const int sec_w = sections.v[1] + sections.v[0];
|
| 309 |
+
const int sector = (i0 / 2) % sect_dims;
|
| 310 |
+
|
| 311 |
+
float theta_base = 0.0;
|
| 312 |
+
if (sector < sections.v[0]) {
|
| 313 |
+
const int p = sector;
|
| 314 |
+
theta_base = pos[i2] * powf(theta_scale, p);
|
| 315 |
+
} else if (sector >= sections.v[0] && sector < sec_w) {
|
| 316 |
+
const int p = sector - sections.v[0];
|
| 317 |
+
theta_base = pos[i2 + ne02] * powf(theta_scale, p);
|
| 318 |
+
}
|
| 319 |
+
|
| 320 |
+
const float freq_factor = has_ff ? freq_factors[i0/2] : 1.0f;
|
| 321 |
+
|
| 322 |
+
float cos_theta;
|
| 323 |
+
float sin_theta;
|
| 324 |
+
|
| 325 |
+
rope_yarn<forward>(theta_base/freq_factor, freq_scale, corr_dims, i0, ext_factor, attn_factor, cos_theta, sin_theta);
|
| 326 |
+
|
| 327 |
+
const float x0 = x[ix + 0];
|
| 328 |
+
const float x1 = x[ix + n_dims];
|
| 329 |
+
|
| 330 |
+
dst[idst + 0] = x0*cos_theta - x1*sin_theta;
|
| 331 |
+
dst[idst + n_dims] = x0*sin_theta + x1*cos_theta;
|
| 332 |
+
}
|
| 333 |
+
|
| 334 |
+
template <bool forward, typename T, typename D>
|
| 335 |
+
static void rope_norm_cuda(const T * x,
|
| 336 |
+
D * dst,
|
| 337 |
+
const int ne00,
|
| 338 |
+
const int ne01,
|
| 339 |
+
const int ne02,
|
| 340 |
+
const int s01,
|
| 341 |
+
const int s02,
|
| 342 |
+
const int s03,
|
| 343 |
+
const int s1,
|
| 344 |
+
const int s2,
|
| 345 |
+
const int s3,
|
| 346 |
+
const int n_dims,
|
| 347 |
+
const int nr,
|
| 348 |
+
const int32_t * pos,
|
| 349 |
+
const float freq_scale,
|
| 350 |
+
const float freq_base,
|
| 351 |
+
const float ext_factor,
|
| 352 |
+
const float attn_factor,
|
| 353 |
+
const rope_corr_dims corr_dims,
|
| 354 |
+
const float * freq_factors,
|
| 355 |
+
const int64_t * row_indices,
|
| 356 |
+
const int set_rows_stride,
|
| 357 |
+
cudaStream_t stream) {
|
| 358 |
+
GGML_ASSERT(ne00 % 2 == 0);
|
| 359 |
+
const dim3 block_dims(1, CUDA_ROPE_BLOCK_SIZE, 1);
|
| 360 |
+
const int n_blocks_x = (ne00 + 2 * CUDA_ROPE_BLOCK_SIZE - 1) / (2 * CUDA_ROPE_BLOCK_SIZE);
|
| 361 |
+
const dim3 block_nums(nr, n_blocks_x, 1);
|
| 362 |
+
|
| 363 |
+
const float theta_scale = powf(freq_base, -2.0f / n_dims);
|
| 364 |
+
|
| 365 |
+
if (freq_factors == nullptr) {
|
| 366 |
+
rope_norm<forward, false><<<block_nums, block_dims, 0, stream>>>(
|
| 367 |
+
x, dst, ne00, ne01, ne02, s01, s02, s03, s1, s2, s3, n_dims, pos, freq_scale, ext_factor,
|
| 368 |
+
attn_factor, corr_dims, theta_scale, freq_factors, row_indices, set_rows_stride);
|
| 369 |
+
} else {
|
| 370 |
+
rope_norm<forward, true><<<block_nums, block_dims, 0, stream>>>(
|
| 371 |
+
x, dst, ne00, ne01, ne02, s01, s02, s03, s1, s2, s3, n_dims, pos, freq_scale, ext_factor,
|
| 372 |
+
attn_factor, corr_dims, theta_scale, freq_factors, row_indices, set_rows_stride);
|
| 373 |
+
}
|
| 374 |
+
}
|
| 375 |
+
|
| 376 |
+
template <bool forward, typename T, typename D>
|
| 377 |
+
static void rope_neox_cuda(const T * x,
|
| 378 |
+
D * dst,
|
| 379 |
+
const int ne00,
|
| 380 |
+
const int ne01,
|
| 381 |
+
const int ne02,
|
| 382 |
+
const int s01,
|
| 383 |
+
const int s02,
|
| 384 |
+
const int s03,
|
| 385 |
+
const int s1,
|
| 386 |
+
const int s2,
|
| 387 |
+
const int s3,
|
| 388 |
+
const int n_dims,
|
| 389 |
+
const int nr,
|
| 390 |
+
const int32_t * pos,
|
| 391 |
+
const float freq_scale,
|
| 392 |
+
const float freq_base,
|
| 393 |
+
const float ext_factor,
|
| 394 |
+
const float attn_factor,
|
| 395 |
+
const rope_corr_dims corr_dims,
|
| 396 |
+
const float * freq_factors,
|
| 397 |
+
const int64_t * row_indices,
|
| 398 |
+
const int set_rows_stride,
|
| 399 |
+
cudaStream_t stream) {
|
| 400 |
+
GGML_ASSERT(ne00 % 2 == 0);
|
| 401 |
+
const dim3 block_dims(1, CUDA_ROPE_BLOCK_SIZE, 1);
|
| 402 |
+
const int n_blocks_x = (ne00 + 2 * CUDA_ROPE_BLOCK_SIZE - 1) / (2 * CUDA_ROPE_BLOCK_SIZE);
|
| 403 |
+
const dim3 block_nums(nr, n_blocks_x, 1);
|
| 404 |
+
|
| 405 |
+
const float theta_scale = powf(freq_base, -2.0f / n_dims);
|
| 406 |
+
const ggml_cuda_kernel_launch_params launch_params = {block_nums, block_dims, 0, stream};
|
| 407 |
+
|
| 408 |
+
if (freq_factors == nullptr) {
|
| 409 |
+
ggml_cuda_kernel_launch(rope_neox<forward, false, T, D>, launch_params,
|
| 410 |
+
x, dst, ne00, ne01, ne02, s01, s02, s03, s1, s2, s3, n_dims, pos, freq_scale, ext_factor,
|
| 411 |
+
attn_factor, corr_dims, theta_scale, freq_factors, row_indices, set_rows_stride);
|
| 412 |
+
} else {
|
| 413 |
+
ggml_cuda_kernel_launch(rope_neox<forward, true, T, D>, launch_params,
|
| 414 |
+
x, dst, ne00, ne01, ne02, s01, s02, s03, s1, s2, s3, n_dims, pos, freq_scale, ext_factor,
|
| 415 |
+
attn_factor, corr_dims, theta_scale, freq_factors, row_indices, set_rows_stride);
|
| 416 |
+
}
|
| 417 |
+
}
|
| 418 |
+
|
| 419 |
+
template <bool forward, typename T>
|
| 420 |
+
static void rope_multi_cuda(const T * x,
|
| 421 |
+
T * dst,
|
| 422 |
+
const int ne00,
|
| 423 |
+
const int ne01,
|
| 424 |
+
const int ne02,
|
| 425 |
+
const int s01,
|
| 426 |
+
const int s02,
|
| 427 |
+
const int s03,
|
| 428 |
+
const int s1,
|
| 429 |
+
const int s2,
|
| 430 |
+
const int s3,
|
| 431 |
+
const int n_dims,
|
| 432 |
+
const int nr,
|
| 433 |
+
const int32_t * pos,
|
| 434 |
+
const float freq_scale,
|
| 435 |
+
const float freq_base,
|
| 436 |
+
const float ext_factor,
|
| 437 |
+
const float attn_factor,
|
| 438 |
+
const rope_corr_dims corr_dims,
|
| 439 |
+
const float * freq_factors,
|
| 440 |
+
const mrope_sections sections,
|
| 441 |
+
const bool is_imrope,
|
| 442 |
+
cudaStream_t stream) {
|
| 443 |
+
GGML_ASSERT(ne00 % 2 == 0);
|
| 444 |
+
const dim3 block_dims(1, CUDA_ROPE_BLOCK_SIZE, 1);
|
| 445 |
+
const int n_blocks_x = (ne00 + 2 * CUDA_ROPE_BLOCK_SIZE - 1) / (2 * CUDA_ROPE_BLOCK_SIZE);
|
| 446 |
+
const dim3 block_nums(nr, n_blocks_x, 1);
|
| 447 |
+
|
| 448 |
+
const float theta_scale = powf(freq_base, -2.0f / n_dims);
|
| 449 |
+
|
| 450 |
+
if (freq_factors == nullptr) {
|
| 451 |
+
const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params(block_nums, block_dims, 0, stream);
|
| 452 |
+
ggml_cuda_kernel_launch(rope_multi<forward, false, T>, launch_params,
|
| 453 |
+
x, dst, ne00, ne01, ne02, s01, s02, s03, s1, s2, s3, n_dims, pos, freq_scale, ext_factor,
|
| 454 |
+
attn_factor, corr_dims, theta_scale, freq_factors, sections, is_imrope);
|
| 455 |
+
} else {
|
| 456 |
+
const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params(block_nums, block_dims, 0, stream);
|
| 457 |
+
ggml_cuda_kernel_launch(rope_multi<forward, true, T>, launch_params,
|
| 458 |
+
x, dst, ne00, ne01, ne02, s01, s02, s03, s1, s2, s3, n_dims, pos, freq_scale, ext_factor,
|
| 459 |
+
attn_factor, corr_dims, theta_scale, freq_factors, sections, is_imrope);
|
| 460 |
+
}
|
| 461 |
+
}
|
| 462 |
+
|
| 463 |
+
template <bool forward, typename T>
|
| 464 |
+
static void rope_vision_cuda(const T * x,
|
| 465 |
+
T * dst,
|
| 466 |
+
const int ne00,
|
| 467 |
+
const int ne01,
|
| 468 |
+
const int ne02,
|
| 469 |
+
const int s01,
|
| 470 |
+
const int s02,
|
| 471 |
+
const int s03,
|
| 472 |
+
const int s1,
|
| 473 |
+
const int s2,
|
| 474 |
+
const int s3,
|
| 475 |
+
const int n_dims,
|
| 476 |
+
const int nr,
|
| 477 |
+
const int32_t * pos,
|
| 478 |
+
const float freq_scale,
|
| 479 |
+
const float freq_base,
|
| 480 |
+
const float ext_factor,
|
| 481 |
+
const float attn_factor,
|
| 482 |
+
const rope_corr_dims corr_dims,
|
| 483 |
+
const float * freq_factors,
|
| 484 |
+
const mrope_sections sections,
|
| 485 |
+
cudaStream_t stream) {
|
| 486 |
+
GGML_ASSERT(ne00 % 2 == 0);
|
| 487 |
+
const dim3 block_dims(1, CUDA_ROPE_BLOCK_SIZE, 1);
|
| 488 |
+
const int n_blocks_x = (ne00 + 2 * CUDA_ROPE_BLOCK_SIZE - 1) / (2 * CUDA_ROPE_BLOCK_SIZE);
|
| 489 |
+
const dim3 block_nums(nr, n_blocks_x, 1);
|
| 490 |
+
// break down (head_dim, heads, seq) into (CUDA_ROPE_BLOCK_SIZE, x, heads * seq)
|
| 491 |
+
// where x ~= ceil(head_dim / CUDA_ROPE_BLOCK_SIZE);
|
| 492 |
+
|
| 493 |
+
const float theta_scale = powf(freq_base, -2.0f/n_dims);
|
| 494 |
+
|
| 495 |
+
if (freq_factors == nullptr) {
|
| 496 |
+
rope_vision<forward, false, T><<<block_nums, block_dims, 0, stream>>>(
|
| 497 |
+
x, dst, ne00, ne01, ne02, s01, s02, s03, s1, s2, s3, n_dims, pos, freq_scale, ext_factor,
|
| 498 |
+
attn_factor, corr_dims, theta_scale, freq_factors, sections);
|
| 499 |
+
} else {
|
| 500 |
+
rope_vision<forward, true, T><<<block_nums, block_dims, 0, stream>>>(
|
| 501 |
+
x, dst, ne00, ne01, ne02, s01, s02, s03, s1, s2, s3, n_dims, pos, freq_scale, ext_factor,
|
| 502 |
+
attn_factor, corr_dims, theta_scale, freq_factors, sections);
|
| 503 |
+
}
|
| 504 |
+
}
|
| 505 |
+
|
| 506 |
+
template <bool forward>
|
| 507 |
+
void ggml_cuda_op_rope_impl(ggml_backend_cuda_context & ctx,
|
| 508 |
+
ggml_tensor * dst,
|
| 509 |
+
const ggml_tensor * set_rows = nullptr) {
|
| 510 |
+
const ggml_tensor * src0 = dst->src[0];
|
| 511 |
+
const ggml_tensor * src1 = dst->src[1];
|
| 512 |
+
const ggml_tensor * src2 = dst->src[2];
|
| 513 |
+
|
| 514 |
+
const float * src0_d = (const float *)src0->data;
|
| 515 |
+
const float * src1_d = (const float *)src1->data;
|
| 516 |
+
|
| 517 |
+
void * dst_d = dst->data;
|
| 518 |
+
const int64_t * row_indices = nullptr;
|
| 519 |
+
ggml_type dst_type = dst->type;
|
| 520 |
+
int set_rows_stride = 0;
|
| 521 |
+
|
| 522 |
+
if (set_rows != nullptr) {
|
| 523 |
+
GGML_ASSERT(forward);
|
| 524 |
+
dst_d = set_rows->data;
|
| 525 |
+
row_indices = (const int64_t *) set_rows->src[1]->data;
|
| 526 |
+
dst_type = set_rows->type;
|
| 527 |
+
set_rows_stride = set_rows->nb[1] / ggml_type_size(set_rows->type);
|
| 528 |
+
}
|
| 529 |
+
cudaStream_t stream = ctx.stream();
|
| 530 |
+
|
| 531 |
+
GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16);
|
| 532 |
+
GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16);
|
| 533 |
+
// When not fused, src0 and dst types must match
|
| 534 |
+
// When fused (ROPE+VIEW+SET_ROWS), src0 may be F32 and dst may be F16
|
| 535 |
+
GGML_ASSERT(src0->type == dst->type || (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F16));
|
| 536 |
+
|
| 537 |
+
const int64_t ne00 = src0->ne[0]; // head dims
|
| 538 |
+
const int64_t ne01 = src0->ne[1]; // num heads
|
| 539 |
+
const int64_t ne02 = src0->ne[2]; // num heads
|
| 540 |
+
const int64_t nr = ggml_nrows(src0);
|
| 541 |
+
|
| 542 |
+
const size_t s01 = src0->nb[1] / ggml_type_size(src0->type);
|
| 543 |
+
const size_t s02 = src0->nb[2] / ggml_type_size(src0->type);
|
| 544 |
+
const size_t s03 = src0->nb[3] / ggml_type_size(src0->type);
|
| 545 |
+
|
| 546 |
+
const size_t s1 = dst->nb[1] / ggml_type_size(dst->type);
|
| 547 |
+
const size_t s2 = dst->nb[2] / ggml_type_size(dst->type);
|
| 548 |
+
const size_t s3 = dst->nb[3] / ggml_type_size(dst->type);
|
| 549 |
+
|
| 550 |
+
//const int n_past = ((int32_t *) dst->op_params)[0];
|
| 551 |
+
const int n_dims = ((int32_t *) dst->op_params)[1];
|
| 552 |
+
const int mode = ((int32_t *) dst->op_params)[2];
|
| 553 |
+
//const int n_ctx = ((int32_t *) dst->op_params)[3];
|
| 554 |
+
const int n_ctx_orig = ((int32_t *) dst->op_params)[4];
|
| 555 |
+
mrope_sections sections;
|
| 556 |
+
|
| 557 |
+
// RoPE alteration for extended context
|
| 558 |
+
float freq_base;
|
| 559 |
+
float freq_scale;
|
| 560 |
+
float ext_factor;
|
| 561 |
+
float attn_factor;
|
| 562 |
+
float beta_fast;
|
| 563 |
+
float beta_slow;
|
| 564 |
+
|
| 565 |
+
memcpy(&freq_base, (int32_t *) dst->op_params + 5, sizeof(float));
|
| 566 |
+
memcpy(&freq_scale, (int32_t *) dst->op_params + 6, sizeof(float));
|
| 567 |
+
memcpy(&ext_factor, (int32_t *) dst->op_params + 7, sizeof(float));
|
| 568 |
+
memcpy(&attn_factor, (int32_t *) dst->op_params + 8, sizeof(float));
|
| 569 |
+
memcpy(&beta_fast, (int32_t *) dst->op_params + 9, sizeof(float));
|
| 570 |
+
memcpy(&beta_slow, (int32_t *) dst->op_params + 10, sizeof(float));
|
| 571 |
+
memcpy(§ions.v, (int32_t *) dst->op_params + 11, sizeof(int)*4);
|
| 572 |
+
|
| 573 |
+
const bool is_neox = mode & GGML_ROPE_TYPE_NEOX;
|
| 574 |
+
const bool is_mrope = mode & GGML_ROPE_TYPE_MROPE;
|
| 575 |
+
const bool is_imrope = mode == GGML_ROPE_TYPE_IMROPE;
|
| 576 |
+
const bool is_vision = mode == GGML_ROPE_TYPE_VISION;
|
| 577 |
+
|
| 578 |
+
if (is_mrope) {
|
| 579 |
+
GGML_ASSERT(sections.v[0] > 0 || sections.v[1] > 0 || sections.v[2] > 0);
|
| 580 |
+
}
|
| 581 |
+
|
| 582 |
+
if (is_vision) {
|
| 583 |
+
GGML_ASSERT(n_dims == ne00/2);
|
| 584 |
+
}
|
| 585 |
+
|
| 586 |
+
const int32_t * pos = (const int32_t *) src1_d;
|
| 587 |
+
|
| 588 |
+
const float * freq_factors = nullptr;
|
| 589 |
+
if (src2 != nullptr) {
|
| 590 |
+
freq_factors = (const float *) src2->data;
|
| 591 |
+
}
|
| 592 |
+
|
| 593 |
+
rope_corr_dims corr_dims;
|
| 594 |
+
ggml_rope_yarn_corr_dims(n_dims, n_ctx_orig, freq_base, beta_fast, beta_slow, corr_dims.v);
|
| 595 |
+
|
| 596 |
+
// compute
|
| 597 |
+
if (is_neox) {
|
| 598 |
+
if (src0->type == GGML_TYPE_F32 && dst_type == GGML_TYPE_F32) {
|
| 599 |
+
rope_neox_cuda<forward, float, float>((const float *) src0_d, (float *) dst_d, ne00, ne01, ne02, s01, s02,
|
| 600 |
+
s03, s1, s2, s3, n_dims, nr, pos, freq_scale, freq_base,
|
| 601 |
+
ext_factor, attn_factor, corr_dims, freq_factors, row_indices,
|
| 602 |
+
set_rows_stride, stream);
|
| 603 |
+
} else if (src0->type == GGML_TYPE_F32 && dst_type == GGML_TYPE_F16) {
|
| 604 |
+
rope_neox_cuda<forward, float, half>((const float *) src0_d, (half *) dst_d, ne00, ne01, ne02, s01, s02,
|
| 605 |
+
s03, s1, s2, s3, n_dims, nr, pos, freq_scale, freq_base,
|
| 606 |
+
ext_factor, attn_factor, corr_dims, freq_factors, row_indices,
|
| 607 |
+
set_rows_stride, stream);
|
| 608 |
+
} else if (src0->type == GGML_TYPE_F16 && dst_type == GGML_TYPE_F16) {
|
| 609 |
+
rope_neox_cuda<forward, half, half>((const half *) src0_d, (half *) dst_d, ne00, ne01, ne02, s01, s02,
|
| 610 |
+
s03, s1, s2, s3, n_dims, nr, pos, freq_scale, freq_base,
|
| 611 |
+
ext_factor, attn_factor, corr_dims, freq_factors, row_indices,
|
| 612 |
+
set_rows_stride, stream);
|
| 613 |
+
} else {
|
| 614 |
+
GGML_ABORT("fatal error");
|
| 615 |
+
}
|
| 616 |
+
} else if (is_mrope && !is_vision) {
|
| 617 |
+
if (src0->type == GGML_TYPE_F32) {
|
| 618 |
+
rope_multi_cuda<forward>((const float *) src0_d, (float *) dst_d, ne00, ne01, ne02, s01, s02, s03, s1,
|
| 619 |
+
s2, s3, n_dims, nr, pos, freq_scale, freq_base, ext_factor, attn_factor,
|
| 620 |
+
corr_dims, freq_factors, sections, is_imrope, stream);
|
| 621 |
+
} else if (src0->type == GGML_TYPE_F16) {
|
| 622 |
+
rope_multi_cuda<forward>((const half *) src0_d, (half *) dst_d, ne00, ne01, ne02, s01, s02, s03, s1,
|
| 623 |
+
s2, s3, n_dims, nr, pos, freq_scale, freq_base, ext_factor, attn_factor,
|
| 624 |
+
corr_dims, freq_factors, sections, is_imrope, stream);
|
| 625 |
+
} else {
|
| 626 |
+
GGML_ABORT("fatal error");
|
| 627 |
+
}
|
| 628 |
+
} else if (is_vision) {
|
| 629 |
+
if (src0->type == GGML_TYPE_F32) {
|
| 630 |
+
rope_vision_cuda<forward>((const float *) src0_d, (float *) dst_d, ne00, ne01, ne02, s01, s02, s03, s1,
|
| 631 |
+
s2, s3, n_dims, nr, pos, freq_scale, freq_base, ext_factor, attn_factor,
|
| 632 |
+
corr_dims, freq_factors, sections, stream);
|
| 633 |
+
} else if (src0->type == GGML_TYPE_F16) {
|
| 634 |
+
rope_vision_cuda<forward>((const half *) src0_d, (half *) dst_d, ne00, ne01, ne02, s01, s02, s03, s1,
|
| 635 |
+
s2, s3, n_dims, nr, pos, freq_scale, freq_base, ext_factor, attn_factor,
|
| 636 |
+
corr_dims, freq_factors, sections, stream);
|
| 637 |
+
} else {
|
| 638 |
+
GGML_ABORT("fatal error");
|
| 639 |
+
}
|
| 640 |
+
} else {
|
| 641 |
+
if (src0->type == GGML_TYPE_F32 && dst_type == GGML_TYPE_F32) {
|
| 642 |
+
rope_norm_cuda<forward, float, float>((const float *) src0_d, (float *) dst_d, ne00, ne01, ne02, s01, s02,
|
| 643 |
+
s03, s1, s2, s3, n_dims, nr, pos, freq_scale, freq_base,
|
| 644 |
+
ext_factor, attn_factor, corr_dims, freq_factors, row_indices,
|
| 645 |
+
set_rows_stride, stream);
|
| 646 |
+
} else if (src0->type == GGML_TYPE_F32 && dst_type == GGML_TYPE_F16) {
|
| 647 |
+
rope_norm_cuda<forward, float, half>((const float *) src0_d, (half *) dst_d, ne00, ne01, ne02, s01, s02,
|
| 648 |
+
s03, s1, s2, s3, n_dims, nr, pos, freq_scale, freq_base,
|
| 649 |
+
ext_factor, attn_factor, corr_dims, freq_factors, row_indices,
|
| 650 |
+
set_rows_stride, stream);
|
| 651 |
+
} else if (src0->type == GGML_TYPE_F16 && dst_type == GGML_TYPE_F16) {
|
| 652 |
+
rope_norm_cuda<forward, half, half>((const half *) src0_d, (half *) dst_d, ne00, ne01, ne02, s01, s02,
|
| 653 |
+
s03, s1, s2, s3, n_dims, nr, pos, freq_scale, freq_base,
|
| 654 |
+
ext_factor, attn_factor, corr_dims, freq_factors, row_indices,
|
| 655 |
+
set_rows_stride, stream);
|
| 656 |
+
} else {
|
| 657 |
+
GGML_ABORT("fatal error");
|
| 658 |
+
}
|
| 659 |
+
}
|
| 660 |
+
}
|
| 661 |
+
|
| 662 |
+
void ggml_cuda_op_rope(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 663 |
+
ggml_cuda_op_rope_impl<true>(ctx, dst);
|
| 664 |
+
}
|
| 665 |
+
|
| 666 |
+
void ggml_cuda_op_rope_back(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 667 |
+
ggml_cuda_op_rope_impl<false>(ctx, dst);
|
| 668 |
+
}
|
| 669 |
+
|
| 670 |
+
void ggml_cuda_op_rope_fused(ggml_backend_cuda_context & ctx, ggml_tensor * rope, ggml_tensor * set_rows) {
|
| 671 |
+
ggml_cuda_op_rope_impl<true>(ctx, rope, set_rows);
|
| 672 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/rope.cuh
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
|
| 3 |
+
#define CUDA_ROPE_BLOCK_SIZE 256
|
| 4 |
+
|
| 5 |
+
void ggml_cuda_op_rope(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
| 6 |
+
|
| 7 |
+
void ggml_cuda_op_rope_back(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
| 8 |
+
|
| 9 |
+
void ggml_cuda_op_rope_fused(ggml_backend_cuda_context & ctx, ggml_tensor * dst, ggml_tensor * set_rows);
|
backend/llama.cpp/ggml/src/ggml-cuda/scale.cu
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "scale.cuh"
|
| 2 |
+
|
| 3 |
+
#define MAX_GRIDDIM_X 0x7FFFFFFF
|
| 4 |
+
|
| 5 |
+
static __global__ void scale_f32(const float * x, float * dst, const float scale, const float bias, const int64_t nelements) {
|
| 6 |
+
ggml_cuda_pdl_lc();
|
| 7 |
+
int64_t tid = (int64_t)blockIdx.x * (int64_t)blockDim.x + (int64_t)threadIdx.x;
|
| 8 |
+
int64_t stride = (int64_t)blockDim.x * (int64_t)gridDim.x;
|
| 9 |
+
|
| 10 |
+
ggml_cuda_pdl_sync();
|
| 11 |
+
for (int64_t i = tid; i < nelements; i += stride) {
|
| 12 |
+
dst[i] = scale * x[i] + bias;
|
| 13 |
+
}
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
static void scale_f32_cuda(const float * x, float * dst, const float scale, const float bias, const int64_t nelements, cudaStream_t stream) {
|
| 17 |
+
const int64_t num_blocks = (nelements + CUDA_SCALE_BLOCK_SIZE - 1) / CUDA_SCALE_BLOCK_SIZE;
|
| 18 |
+
const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params(MIN(MAX_GRIDDIM_X, num_blocks), CUDA_SCALE_BLOCK_SIZE, 0, stream);
|
| 19 |
+
ggml_cuda_kernel_launch(scale_f32, launch_params, x, dst, scale, bias, nelements);
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
void ggml_cuda_op_scale(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 23 |
+
const ggml_tensor * src0 = dst->src[0];
|
| 24 |
+
const float * src0_d = (const float *)src0->data;
|
| 25 |
+
float * dst_d = (float *)dst->data;
|
| 26 |
+
cudaStream_t stream = ctx.stream();
|
| 27 |
+
|
| 28 |
+
GGML_ASSERT(src0->type == GGML_TYPE_F32);
|
| 29 |
+
GGML_ASSERT( dst->type == GGML_TYPE_F32);
|
| 30 |
+
|
| 31 |
+
float scale;
|
| 32 |
+
float bias;
|
| 33 |
+
memcpy(&scale, (float *) dst->op_params + 0, sizeof(float));
|
| 34 |
+
memcpy(&bias, (float *) dst->op_params + 1, sizeof(float));
|
| 35 |
+
|
| 36 |
+
scale_f32_cuda(src0_d, dst_d, scale, bias, ggml_nelements(src0), stream);
|
| 37 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/scale.cuh
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "common.cuh"
|
| 2 |
+
|
| 3 |
+
#define CUDA_SCALE_BLOCK_SIZE 256
|
| 4 |
+
|
| 5 |
+
void ggml_cuda_op_scale(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
backend/llama.cpp/ggml/src/ggml-cuda/set-rows.cu
ADDED
|
@@ -0,0 +1,398 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "set-rows.cuh"
|
| 2 |
+
#include "cpy-utils.cuh"
|
| 3 |
+
|
| 4 |
+
typedef void (*set_rows_kernel_t)(const char * src, char * dst);
|
| 5 |
+
|
| 6 |
+
// Generic quantized set_rows kernel template
|
| 7 |
+
template <typename idx_t, typename block_type, int qk, void (*quantize_func)(const float *, block_type *)>
|
| 8 |
+
static __global__ void k_set_rows_quant(const float * __restrict__ src0,
|
| 9 |
+
const idx_t * __restrict__ src1,
|
| 10 |
+
block_type * __restrict__ dst,
|
| 11 |
+
const int64_t ne_total,
|
| 12 |
+
const int64_t ne10,
|
| 13 |
+
const int64_t ne11,
|
| 14 |
+
const int64_t ne12,
|
| 15 |
+
const int64_t ne13,
|
| 16 |
+
const int64_t s01,
|
| 17 |
+
const int64_t s02,
|
| 18 |
+
const int64_t s03,
|
| 19 |
+
const int64_t s10,
|
| 20 |
+
const int64_t s11,
|
| 21 |
+
const int64_t s12,
|
| 22 |
+
const int64_t s1,
|
| 23 |
+
const int64_t s2,
|
| 24 |
+
const int64_t s3,
|
| 25 |
+
const uint3 ne00,
|
| 26 |
+
const uint3 ne01,
|
| 27 |
+
const uint3 ne02,
|
| 28 |
+
const uint3 ne11_fd,
|
| 29 |
+
const uint3 ne12_fd) {
|
| 30 |
+
const int64_t i = int64_t(blockDim.x) * blockIdx.x + threadIdx.x;
|
| 31 |
+
|
| 32 |
+
if (i >= ne_total) {
|
| 33 |
+
return;
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
const int64_t i_base = i * qk;
|
| 37 |
+
uint32_t tmp = (uint32_t) i_base;
|
| 38 |
+
uint2 div_mod;
|
| 39 |
+
|
| 40 |
+
div_mod = fast_div_modulo(tmp, ne00);
|
| 41 |
+
const int64_t i00 = div_mod.y;
|
| 42 |
+
tmp = div_mod.x;
|
| 43 |
+
|
| 44 |
+
div_mod = fast_div_modulo(tmp, ne01);
|
| 45 |
+
const int64_t i01 = div_mod.y;
|
| 46 |
+
tmp = div_mod.x;
|
| 47 |
+
|
| 48 |
+
div_mod = fast_div_modulo(tmp, ne02);
|
| 49 |
+
const int64_t i02 = div_mod.y;
|
| 50 |
+
const int64_t i03 = div_mod.x;
|
| 51 |
+
|
| 52 |
+
const int64_t i12 = fastmodulo((uint32_t) i03, ne12_fd);
|
| 53 |
+
const int64_t i11 = fastmodulo((uint32_t) i02, ne11_fd);
|
| 54 |
+
const int64_t i10 = i01;
|
| 55 |
+
|
| 56 |
+
ggml_cuda_pdl_sync();
|
| 57 |
+
const int64_t dst_row = *(src1 + i10*s10 + i11*s11 + i12*s12);
|
| 58 |
+
|
| 59 |
+
const float * src0_row = src0 + i01*s01 + i02*s02 + i03*s03;
|
| 60 |
+
block_type * dst_row_ptr = dst + (dst_row*s1 + i02*s2 + i03*s3) / sizeof(block_type);
|
| 61 |
+
|
| 62 |
+
const float * src_block = src0_row + i00;
|
| 63 |
+
block_type * dst_block = dst_row_ptr + i00 / qk;
|
| 64 |
+
|
| 65 |
+
quantize_func(src_block, dst_block);
|
| 66 |
+
|
| 67 |
+
GGML_UNUSED(ne10);
|
| 68 |
+
GGML_UNUSED(ne11);
|
| 69 |
+
GGML_UNUSED(ne12);
|
| 70 |
+
GGML_UNUSED(ne13);
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
// Template dispatch function for quantized set_rows
|
| 74 |
+
template<typename idx_t, typename block_type, int qk, void (*quantize_func)(const float*, block_type*)>
|
| 75 |
+
static void set_rows_cuda_quant(
|
| 76 |
+
const float * src0_d, const idx_t * src1_d, block_type * dst_d,
|
| 77 |
+
const int64_t ne00, const int64_t ne01, const int64_t ne02, const int64_t ne03,
|
| 78 |
+
const int64_t ne10, const int64_t ne11, const int64_t ne12, const int64_t ne13,
|
| 79 |
+
const size_t nb01, const size_t nb02, const size_t nb03,
|
| 80 |
+
const size_t nb10, const size_t nb11, const size_t nb12,
|
| 81 |
+
const size_t nb1, const size_t nb2, const size_t nb3,
|
| 82 |
+
cudaStream_t stream) {
|
| 83 |
+
|
| 84 |
+
GGML_ASSERT(ne00 % qk == 0);
|
| 85 |
+
const int64_t ne_total = (ne00 * ne01 * ne02 * ne03) / qk;
|
| 86 |
+
const int num_blocks = (ne_total + CUDA_SET_ROWS_BLOCK_SIZE - 1) / CUDA_SET_ROWS_BLOCK_SIZE;
|
| 87 |
+
const dim3 block_size(CUDA_SET_ROWS_BLOCK_SIZE);
|
| 88 |
+
const dim3 grid_size(num_blocks);
|
| 89 |
+
|
| 90 |
+
const int64_t s01 = nb01/sizeof(float);
|
| 91 |
+
const int64_t s02 = nb02/sizeof(float);
|
| 92 |
+
const int64_t s03 = nb03/sizeof(float);
|
| 93 |
+
const int64_t s10 = nb10/sizeof(idx_t);
|
| 94 |
+
const int64_t s11 = nb11/sizeof(idx_t);
|
| 95 |
+
const int64_t s12 = nb12/sizeof(idx_t);
|
| 96 |
+
const int64_t s1 = nb1;
|
| 97 |
+
const int64_t s2 = nb2;
|
| 98 |
+
const int64_t s3 = nb3;
|
| 99 |
+
|
| 100 |
+
if (ne_total > 0 && ne00 > 0 && ne01 > 0 && ne02 > 0 && ne11 > 0 && ne12 > 0) {
|
| 101 |
+
const uint3 ne00_fd = init_fastdiv_values((uint32_t) ne00);
|
| 102 |
+
const uint3 ne01_fd = init_fastdiv_values((uint32_t) ne01);
|
| 103 |
+
const uint3 ne02_fd = init_fastdiv_values((uint32_t) ne02);
|
| 104 |
+
const uint3 ne11_fd = init_fastdiv_values((uint32_t) ne11);
|
| 105 |
+
const uint3 ne12_fd = init_fastdiv_values((uint32_t) ne12);
|
| 106 |
+
|
| 107 |
+
k_set_rows_quant<idx_t, block_type, qk, quantize_func><<<grid_size, block_size, 0, stream>>>(
|
| 108 |
+
src0_d, src1_d, dst_d, ne_total, ne10, ne11, ne12, ne13, s01, s02, s03, s10, s11, s12, s1, s2, s3, ne00_fd,
|
| 109 |
+
ne01_fd, ne02_fd, ne11_fd, ne12_fd);
|
| 110 |
+
}
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
template <typename src_t, typename idx_t, typename dst_t>
|
| 114 |
+
static __global__ void k_set_rows(const src_t * src0_ptr,
|
| 115 |
+
const idx_t * src1_ptr,
|
| 116 |
+
dst_t * dst_ptr,
|
| 117 |
+
const int64_t ne_total,
|
| 118 |
+
const int64_t ne10,
|
| 119 |
+
const int64_t ne11,
|
| 120 |
+
const int64_t ne12,
|
| 121 |
+
const int64_t ne13,
|
| 122 |
+
const int64_t s01,
|
| 123 |
+
const int64_t s02,
|
| 124 |
+
const int64_t s03,
|
| 125 |
+
const int64_t s10,
|
| 126 |
+
const int64_t s11,
|
| 127 |
+
const int64_t s12,
|
| 128 |
+
const int64_t s1,
|
| 129 |
+
const int64_t s2,
|
| 130 |
+
const int64_t s3,
|
| 131 |
+
const uint3 ne00,
|
| 132 |
+
const uint3 ne01,
|
| 133 |
+
const uint3 ne02,
|
| 134 |
+
const uint3 ne11_fd,
|
| 135 |
+
const uint3 ne12_fd) {
|
| 136 |
+
const src_t * GGML_CUDA_RESTRICT src0 = src0_ptr;
|
| 137 |
+
const idx_t * GGML_CUDA_RESTRICT src1 = src1_ptr;
|
| 138 |
+
dst_t * GGML_CUDA_RESTRICT dst = dst_ptr;
|
| 139 |
+
const int64_t i = int64_t(blockDim.x) * blockIdx.x + threadIdx.x;
|
| 140 |
+
|
| 141 |
+
if (i >= ne_total) {
|
| 142 |
+
return;
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
uint32_t tmp = (uint32_t) i;
|
| 146 |
+
uint2 div_mod;
|
| 147 |
+
|
| 148 |
+
div_mod = fast_div_modulo(tmp, ne00);
|
| 149 |
+
const int64_t i00 = div_mod.y;
|
| 150 |
+
tmp = div_mod.x;
|
| 151 |
+
|
| 152 |
+
div_mod = fast_div_modulo(tmp, ne01);
|
| 153 |
+
const int64_t i01 = div_mod.y;
|
| 154 |
+
tmp = div_mod.x;
|
| 155 |
+
|
| 156 |
+
div_mod = fast_div_modulo(tmp, ne02);
|
| 157 |
+
const int64_t i02 = div_mod.y;
|
| 158 |
+
const int64_t i03 = div_mod.x;
|
| 159 |
+
|
| 160 |
+
const int64_t i12 = fastmodulo((uint32_t) i03, ne12_fd);
|
| 161 |
+
const int64_t i11 = fastmodulo((uint32_t) i02, ne11_fd);
|
| 162 |
+
const int64_t i10 = i01;
|
| 163 |
+
|
| 164 |
+
ggml_cuda_pdl_sync();
|
| 165 |
+
const int64_t dst_row = *(src1 + i10*s10 + i11*s11 + i12*s12);
|
| 166 |
+
ggml_cuda_pdl_lc();
|
| 167 |
+
|
| 168 |
+
const src_t * src0_row = src0 + i01*s01 + i02*s02 + i03*s03;
|
| 169 |
+
dst_t * dst_row_ptr = dst + dst_row*s1 + i02*s2 + i03*s3;
|
| 170 |
+
|
| 171 |
+
dst_row_ptr[i00] = ggml_cuda_cast<dst_t>(src0_row[i00]);
|
| 172 |
+
|
| 173 |
+
GGML_UNUSED(ne10);
|
| 174 |
+
GGML_UNUSED(ne11);
|
| 175 |
+
GGML_UNUSED(ne12);
|
| 176 |
+
GGML_UNUSED(ne13);
|
| 177 |
+
}
|
| 178 |
+
|
| 179 |
+
template<typename src_t, typename idx_t, typename dst_t>
|
| 180 |
+
static void set_rows_cuda(
|
| 181 |
+
const src_t * src0_d, const idx_t * src1_d, dst_t * dst_d,
|
| 182 |
+
const int64_t ne00, const int64_t ne01, const int64_t ne02, const int64_t ne03,
|
| 183 |
+
const int64_t ne10, const int64_t ne11, const int64_t ne12, const int64_t ne13,
|
| 184 |
+
const size_t nb01, const size_t nb02, const size_t nb03,
|
| 185 |
+
const size_t nb10, const size_t nb11, const size_t nb12,
|
| 186 |
+
const size_t nb1, const size_t nb2, const size_t nb3,
|
| 187 |
+
cudaStream_t stream) {
|
| 188 |
+
|
| 189 |
+
const int64_t ne_total = ne00 * ne01 * ne02 * ne03;
|
| 190 |
+
const int num_blocks = (ne_total + CUDA_SET_ROWS_BLOCK_SIZE - 1) / CUDA_SET_ROWS_BLOCK_SIZE;
|
| 191 |
+
const dim3 block_size(CUDA_SET_ROWS_BLOCK_SIZE);
|
| 192 |
+
const dim3 grid_size(num_blocks);
|
| 193 |
+
|
| 194 |
+
|
| 195 |
+
const int64_t s01 = nb01/sizeof(src_t);
|
| 196 |
+
const int64_t s02 = nb02/sizeof(src_t);
|
| 197 |
+
const int64_t s03 = nb03/sizeof(src_t);
|
| 198 |
+
const int64_t s10 = nb10/sizeof(idx_t);
|
| 199 |
+
const int64_t s11 = nb11/sizeof(idx_t);
|
| 200 |
+
const int64_t s12 = nb12/sizeof(idx_t);
|
| 201 |
+
const int64_t s1 = nb1/sizeof(dst_t);
|
| 202 |
+
const int64_t s2 = nb2/sizeof(dst_t);
|
| 203 |
+
const int64_t s3 = nb3/sizeof(dst_t);
|
| 204 |
+
|
| 205 |
+
if (ne_total > 0 && ne00 > 0 && ne01 > 0 && ne02 > 0 && ne11 > 0 && ne12 > 0) {
|
| 206 |
+
const uint3 ne00_fd = init_fastdiv_values((uint32_t) ne00);
|
| 207 |
+
const uint3 ne01_fd = init_fastdiv_values((uint32_t) ne01);
|
| 208 |
+
const uint3 ne02_fd = init_fastdiv_values((uint32_t) ne02);
|
| 209 |
+
const uint3 ne11_fd = init_fastdiv_values((uint32_t) ne11);
|
| 210 |
+
const uint3 ne12_fd = init_fastdiv_values((uint32_t) ne12);
|
| 211 |
+
|
| 212 |
+
const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params(grid_size, block_size, 0, stream);
|
| 213 |
+
ggml_cuda_kernel_launch(k_set_rows<src_t, idx_t, dst_t>, launch_params,
|
| 214 |
+
src0_d, src1_d, dst_d, ne_total, ne10, ne11, ne12, ne13, s01,
|
| 215 |
+
s02, s03, s10, s11, s12, s1, s2, s3, ne00_fd, ne01_fd, ne02_fd,
|
| 216 |
+
ne11_fd, ne12_fd);
|
| 217 |
+
}
|
| 218 |
+
}
|
| 219 |
+
|
| 220 |
+
template<typename src_t, typename idx_t>
|
| 221 |
+
static void set_rows_cuda(ggml_backend_cuda_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
|
| 222 |
+
const src_t * src0_d = (const src_t *)src0->data;
|
| 223 |
+
const idx_t * src1_d = (const idx_t *)src1->data;
|
| 224 |
+
|
| 225 |
+
GGML_TENSOR_BINARY_OP_LOCALS
|
| 226 |
+
|
| 227 |
+
cudaStream_t stream = ctx.stream();
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
if (dst->type == GGML_TYPE_F32) {
|
| 231 |
+
set_rows_cuda(
|
| 232 |
+
src0_d, src1_d, (float*)dst->data,
|
| 233 |
+
ne00, ne01, ne02, ne03,
|
| 234 |
+
ne10, ne11, ne12, ne13,
|
| 235 |
+
nb01, nb02, nb03,
|
| 236 |
+
nb10, nb11, nb12,
|
| 237 |
+
nb1, nb2, nb3,
|
| 238 |
+
stream
|
| 239 |
+
);
|
| 240 |
+
} else if (dst->type == GGML_TYPE_F16) {
|
| 241 |
+
set_rows_cuda(
|
| 242 |
+
src0_d, src1_d, (half*)dst->data,
|
| 243 |
+
ne00, ne01, ne02, ne03,
|
| 244 |
+
ne10, ne11, ne12, ne13,
|
| 245 |
+
nb01, nb02, nb03,
|
| 246 |
+
nb10, nb11, nb12,
|
| 247 |
+
nb1, nb2, nb3,
|
| 248 |
+
stream
|
| 249 |
+
);
|
| 250 |
+
} else if (dst->type == GGML_TYPE_BF16) {
|
| 251 |
+
set_rows_cuda(
|
| 252 |
+
src0_d, src1_d, (nv_bfloat16*)dst->data,
|
| 253 |
+
ne00, ne01, ne02, ne03,
|
| 254 |
+
ne10, ne11, ne12, ne13,
|
| 255 |
+
nb01, nb02, nb03,
|
| 256 |
+
nb10, nb11, nb12,
|
| 257 |
+
nb1, nb2, nb3,
|
| 258 |
+
stream
|
| 259 |
+
);
|
| 260 |
+
} else if (dst->type == GGML_TYPE_Q4_0) {
|
| 261 |
+
set_rows_cuda_quant<idx_t, block_q4_0, QK4_0, quantize_f32_q4_0_block>(
|
| 262 |
+
src0_d, src1_d, (block_q4_0*)dst->data,
|
| 263 |
+
ne00, ne01, ne02, ne03,
|
| 264 |
+
ne10, ne11, ne12, ne13,
|
| 265 |
+
nb01, nb02, nb03,
|
| 266 |
+
nb10, nb11, nb12,
|
| 267 |
+
nb1, nb2, nb3,
|
| 268 |
+
stream
|
| 269 |
+
);
|
| 270 |
+
} else if (dst->type == GGML_TYPE_Q4_1) {
|
| 271 |
+
set_rows_cuda_quant<idx_t, block_q4_1, QK4_1, quantize_f32_q4_1_block>(
|
| 272 |
+
src0_d, src1_d, (block_q4_1*)dst->data,
|
| 273 |
+
ne00, ne01, ne02, ne03,
|
| 274 |
+
ne10, ne11, ne12, ne13,
|
| 275 |
+
nb01, nb02, nb03,
|
| 276 |
+
nb10, nb11, nb12,
|
| 277 |
+
nb1, nb2, nb3,
|
| 278 |
+
stream
|
| 279 |
+
);
|
| 280 |
+
} else if (dst->type == GGML_TYPE_Q5_0) {
|
| 281 |
+
set_rows_cuda_quant<idx_t, block_q5_0, QK5_0, quantize_f32_q5_0_block>(
|
| 282 |
+
src0_d, src1_d, (block_q5_0*)dst->data,
|
| 283 |
+
ne00, ne01, ne02, ne03,
|
| 284 |
+
ne10, ne11, ne12, ne13,
|
| 285 |
+
nb01, nb02, nb03,
|
| 286 |
+
nb10, nb11, nb12,
|
| 287 |
+
nb1, nb2, nb3,
|
| 288 |
+
stream
|
| 289 |
+
);
|
| 290 |
+
} else if (dst->type == GGML_TYPE_Q5_1) {
|
| 291 |
+
set_rows_cuda_quant<idx_t, block_q5_1, QK5_1, quantize_f32_q5_1_block>(
|
| 292 |
+
src0_d, src1_d, (block_q5_1*)dst->data,
|
| 293 |
+
ne00, ne01, ne02, ne03,
|
| 294 |
+
ne10, ne11, ne12, ne13,
|
| 295 |
+
nb01, nb02, nb03,
|
| 296 |
+
nb10, nb11, nb12,
|
| 297 |
+
nb1, nb2, nb3,
|
| 298 |
+
stream
|
| 299 |
+
);
|
| 300 |
+
} else if (dst->type == GGML_TYPE_Q8_0) {
|
| 301 |
+
set_rows_cuda_quant<idx_t, block_q8_0, QK8_0, quantize_f32_q8_0_block>(
|
| 302 |
+
src0_d, src1_d, (block_q8_0*)dst->data,
|
| 303 |
+
ne00, ne01, ne02, ne03,
|
| 304 |
+
ne10, ne11, ne12, ne13,
|
| 305 |
+
nb01, nb02, nb03,
|
| 306 |
+
nb10, nb11, nb12,
|
| 307 |
+
nb1, nb2, nb3,
|
| 308 |
+
stream
|
| 309 |
+
);
|
| 310 |
+
} else if (dst->type == GGML_TYPE_IQ4_NL) {
|
| 311 |
+
set_rows_cuda_quant<idx_t, block_iq4_nl, QK4_NL, quantize_f32_iq4_nl_block>(
|
| 312 |
+
src0_d, src1_d, (block_iq4_nl*)dst->data,
|
| 313 |
+
ne00, ne01, ne02, ne03,
|
| 314 |
+
ne10, ne11, ne12, ne13,
|
| 315 |
+
nb01, nb02, nb03,
|
| 316 |
+
nb10, nb11, nb12,
|
| 317 |
+
nb1, nb2, nb3,
|
| 318 |
+
stream
|
| 319 |
+
);
|
| 320 |
+
} else {
|
| 321 |
+
GGML_ABORT("unsupported type %s", ggml_type_name(dst->type));
|
| 322 |
+
}
|
| 323 |
+
}
|
| 324 |
+
|
| 325 |
+
template<>
|
| 326 |
+
void set_rows_cuda<half, int32_t>(ggml_backend_cuda_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
|
| 327 |
+
const half * src0_d = (const half *)src0->data;
|
| 328 |
+
const int32_t * src1_d = (const int32_t *)src1->data;
|
| 329 |
+
|
| 330 |
+
GGML_TENSOR_BINARY_OP_LOCALS
|
| 331 |
+
|
| 332 |
+
cudaStream_t stream = ctx.stream();
|
| 333 |
+
|
| 334 |
+
|
| 335 |
+
if (dst->type == GGML_TYPE_F16) {
|
| 336 |
+
set_rows_cuda(
|
| 337 |
+
src0_d, src1_d, (half*)dst->data,
|
| 338 |
+
ne00, ne01, ne02, ne03,
|
| 339 |
+
ne10, ne11, ne12, ne13,
|
| 340 |
+
nb01, nb02, nb03,
|
| 341 |
+
nb10, nb11, nb12,
|
| 342 |
+
nb1, nb2, nb3,
|
| 343 |
+
stream
|
| 344 |
+
);
|
| 345 |
+
} else {
|
| 346 |
+
GGML_ABORT("unsupported type %s", ggml_type_name(dst->type));
|
| 347 |
+
}
|
| 348 |
+
}
|
| 349 |
+
|
| 350 |
+
template<>
|
| 351 |
+
void set_rows_cuda<half, int64_t>(ggml_backend_cuda_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
|
| 352 |
+
const half * src0_d = (const half *)src0->data;
|
| 353 |
+
const int64_t * src1_d = (const int64_t *)src1->data;
|
| 354 |
+
|
| 355 |
+
GGML_TENSOR_BINARY_OP_LOCALS
|
| 356 |
+
|
| 357 |
+
cudaStream_t stream = ctx.stream();
|
| 358 |
+
|
| 359 |
+
|
| 360 |
+
if (dst->type == GGML_TYPE_F16) {
|
| 361 |
+
set_rows_cuda(
|
| 362 |
+
src0_d, src1_d, (half*)dst->data,
|
| 363 |
+
ne00, ne01, ne02, ne03,
|
| 364 |
+
ne10, ne11, ne12, ne13,
|
| 365 |
+
nb01, nb02, nb03,
|
| 366 |
+
nb10, nb11, nb12,
|
| 367 |
+
nb1, nb2, nb3,
|
| 368 |
+
stream
|
| 369 |
+
);
|
| 370 |
+
} else {
|
| 371 |
+
GGML_ABORT("unsupported type %s", ggml_type_name(dst->type));
|
| 372 |
+
}
|
| 373 |
+
}
|
| 374 |
+
|
| 375 |
+
|
| 376 |
+
void ggml_cuda_op_set_rows(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 377 |
+
const ggml_tensor * src0 = dst->src[0];
|
| 378 |
+
const ggml_tensor * src1 = dst->src[1];
|
| 379 |
+
|
| 380 |
+
GGML_ASSERT(src0->type == GGML_TYPE_F32 || (src0->type == GGML_TYPE_F16 && dst->type == GGML_TYPE_F16));
|
| 381 |
+
GGML_ASSERT(src1->type == GGML_TYPE_I64 || src1->type == GGML_TYPE_I32);
|
| 382 |
+
|
| 383 |
+
if (src0->type == GGML_TYPE_F32) {
|
| 384 |
+
if (src1->type == GGML_TYPE_I64) {
|
| 385 |
+
set_rows_cuda<float, int64_t>(ctx, src0, src1, dst);
|
| 386 |
+
} else {
|
| 387 |
+
set_rows_cuda<float, int32_t>(ctx, src0, src1, dst);
|
| 388 |
+
}
|
| 389 |
+
} else if (src0->type == GGML_TYPE_F16) {
|
| 390 |
+
if (src1->type == GGML_TYPE_I64) {
|
| 391 |
+
set_rows_cuda<half, int64_t>(ctx, src0, src1, dst);
|
| 392 |
+
} else {
|
| 393 |
+
set_rows_cuda<half, int32_t>(ctx, src0, src1, dst);
|
| 394 |
+
}
|
| 395 |
+
} else {
|
| 396 |
+
GGML_ABORT("unsupported type %s", ggml_type_name(src0->type));
|
| 397 |
+
}
|
| 398 |
+
}
|
backend/llama.cpp/ggml/src/ggml-cuda/set-rows.cuh
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
|
| 3 |
+
#include "common.cuh"
|
| 4 |
+
|
| 5 |
+
#define CUDA_SET_ROWS_BLOCK_SIZE 256
|
| 6 |
+
|
| 7 |
+
void ggml_cuda_op_set_rows(ggml_backend_cuda_context & ctx, ggml_tensor * dst);
|
backend/llama.cpp/ggml/src/ggml-cuda/set.cu
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "set.cuh"
|
| 2 |
+
#include "cpy.cuh"
|
| 3 |
+
|
| 4 |
+
void ggml_cuda_op_set(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
| 5 |
+
const ggml_tensor * src0 = dst->src[0];
|
| 6 |
+
const ggml_tensor * src1 = dst->src[1];
|
| 7 |
+
|
| 8 |
+
GGML_ASSERT((src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_I32));
|
| 9 |
+
GGML_ASSERT(src1->type == src0->type);
|
| 10 |
+
GGML_ASSERT(dst ->type == src0->type);
|
| 11 |
+
|
| 12 |
+
GGML_ASSERT(ggml_is_contiguous(dst));
|
| 13 |
+
GGML_ASSERT(ggml_is_contiguous(src0));
|
| 14 |
+
GGML_ASSERT(ggml_is_contiguous(src1));
|
| 15 |
+
|
| 16 |
+
const size_t nb1 = ((int32_t *) dst->op_params)[0];
|
| 17 |
+
const size_t nb2 = ((int32_t *) dst->op_params)[1];
|
| 18 |
+
const size_t nb3 = ((int32_t *) dst->op_params)[2];
|
| 19 |
+
const size_t offset = ((int32_t *) dst->op_params)[3];
|
| 20 |
+
const bool inplace= (bool) ((int32_t *) dst->op_params)[4];
|
| 21 |
+
|
| 22 |
+
if (!inplace) {
|
| 23 |
+
ggml_cuda_cpy(ctx, src0, dst);
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
ggml_tensor dst_view = *dst;
|
| 27 |
+
dst_view.data = (void *)((char *)dst->data + offset);
|
| 28 |
+
dst_view.ne[0] = src1->ne[0];
|
| 29 |
+
dst_view.ne[1] = src1->ne[1];
|
| 30 |
+
dst_view.ne[2] = src1->ne[2];
|
| 31 |
+
dst_view.ne[3] = src1->ne[3];
|
| 32 |
+
|
| 33 |
+
dst_view.nb[0] = ggml_element_size(dst);
|
| 34 |
+
dst_view.nb[1] = nb1;
|
| 35 |
+
dst_view.nb[2] = nb2;
|
| 36 |
+
dst_view.nb[3] = nb3;
|
| 37 |
+
|
| 38 |
+
ggml_cuda_cpy(ctx, src1, &dst_view);
|
| 39 |
+
}
|