char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
0190529ec
char/aliceai-t5-moe
1#include "ggml.h" 2#include "common.cuh" 3#include "unary.cuh" 4#include "mmvf.cuh" 5#include "convert.cuh" 6 7template <typename T, typename type_acc, int ncols_dst, int block_size, bool has_fusion = false, bool is_multi_token_id = false> 8static __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 float glu_limit = 0.0f; 60 const T * gate_x = nullptr; 61 const float * x_bias = nullptr; 62 const float * gate_bias = nullptr; 63 64 if constexpr (has_fusion) { 65 use_gate = fusion.gate != nullptr; 66 use_bias = fusion.x_bias != nullptr; 67 use_gate_bias = fusion.gate_bias != nullptr; 68 glu_op = fusion.glu_op; 69 glu_limit = fusion.glu_limit; 70 71 if (use_gate) { 72 gate_x = static_cast<const T *>(fusion.gate); 73 } 74 if (use_bias) { 75 x_bias = static_cast<const float *>(fusion.x_bias); 76 } 77 if (use_gate_bias) { 78 gate_bias = static_cast<const float *>(fusion.gate_bias); 79 use_gate_bias = use_gate; 80 } else { 81 use_gate_bias = false; 82 } 83 } 84 85 if (use_gate) { 86 gate_x += int64_t(sample_x) *stride_sample_x + channel_x *stride_channel_x + row*stride_row; 87 } 88 89 if constexpr (has_fusion) { 90 const int channel_bias = ids ? channel_x : channel_dst; 91 if (use_bias) { 92 x_bias += int64_t(sample_dst)*stride_sample_dst + channel_bias*stride_channel_dst; 93 } 94 if (use_gate_bias) { 95 gate_bias += int64_t(sample_dst)*stride_sample_dst + channel_bias*stride_channel_dst; 96 } 97 } 98 99 const float2 * y2 = (const float2 *) y; 100 101 extern __shared__ char data_mmv[]; 102 float * buf_iw = (float *) data_mmv; 103 [[maybe_unused]] float * buf_iw_gate = nullptr; 104 if constexpr (has_fusion) { 105 buf_iw_gate = (float *) (data_mmv + warp_size*sizeof(float)); 106 } 107 108 if (block_size > warp_size) { 109 if (tid < warp_size) { 110 buf_iw[tid] = 0.0f; 111 if constexpr (has_fusion) { 112 if (use_gate) { 113 buf_iw_gate[tid] = 0.0f; 114 } 115 } 116 } 117 __syncthreads(); 118 } 119 120 float sumf[ncols_dst] = {0.0f}; 121 float sumf_gate[ncols_dst]; 122 if constexpr (has_fusion) { 123#pragma unroll 124 for (int j = 0; j < ncols_dst; ++j) { 125 sumf_gate[j] = 0.0f; 126 } 127 } 128 129 if constexpr (std::is_same_v<T, float>) { 130 const float2 * x2 = (const float2 *) x; 131 [[maybe_unused]] const float2 * gate_x2 = nullptr; 132 if constexpr (has_fusion) { 133 if (use_gate) { 134 gate_x2 = (const float2 *) gate_x; 135 } 136 } 137 138 for (int col2 = tid; col2 < ncols2; col2 += block_size) { 139 const float2 tmpx = x2[col2]; 140 float2 tmpx_gate = make_float2(0.0f, 0.0f); 141 if constexpr (has_fusion) { 142 if (use_gate) { 143 tmpx_gate = gate_x2[col2]; 144 } 145 } 146 147#pragma unroll 148 for (int j = 0; j < ncols_dst; ++j) { 149 const float2 tmpy = y2[j*stride_col_y2 + col2]; 150 ggml_cuda_mad(sumf[j], tmpx.x, tmpy.x); 151 ggml_cuda_mad(sumf[j], tmpx.y, tmpy.y); 152 153 if constexpr (has_fusion) { 154 if (use_gate) { 155 ggml_cuda_mad(sumf_gate[j], tmpx_gate.x, tmpy.x); 156 ggml_cuda_mad(sumf_gate[j], tmpx_gate.y, tmpy.y); 157 } 158 } 159 } 160 } 161 } else if constexpr (std::is_same_v<T, half>) { 162 const half2 * x2 = (const half2 *) x; 163 [[maybe_unused]] const half2 * gate_x2 = nullptr; 164 if constexpr (has_fusion) { 165 if (use_gate) { 166 gate_x2 = (const half2 *) gate_x; 167 } 168 } 169 170 if (std::is_same_v<type_acc, float>) { 171 for (int col2 = tid; col2 < ncols2; col2 += block_size) { 172 const float2 tmpx = __half22float2(x2[col2]); 173 float2 tmpx_gate = make_float2(0.0f, 0.0f); 174 if constexpr (has_fusion) { 175 if (use_gate) { 176 tmpx_gate = __half22float2(gate_x2[col2]); 177 } 178 } 179#pragma unroll 180 for (int j = 0; j < ncols_dst; ++j) { 181 const float2 tmpy = y2[j*stride_col_y2 + col2]; 182 ggml_cuda_mad(sumf[j], tmpx.x, tmpy.x); 183 ggml_cuda_mad(sumf[j], tmpx.y, tmpy.y); 184 185 if constexpr (has_fusion) { 186 if (use_gate) { 187 ggml_cuda_mad(sumf_gate[j], tmpx_gate.x, tmpy.x); 188 ggml_cuda_mad(sumf_gate[j], tmpx_gate.y, tmpy.y); 189 } 190 } 191 } 192 } 193 } else { 194#ifdef FP16_AVAILABLE 195 half2 sumh2[ncols_dst] = {{0.0f, 0.0f}}; 196 half2 sumh2_gate[ncols_dst] = {{0.0f, 0.0f}}; 197 198 for (int col2 = tid; col2 < ncols2; col2 += block_size) { 199 const half2 tmpx = x2[col2]; 200 half2 tmpx_gate = make_half2(0.0f, 0.0f); 201 if constexpr (has_fusion) { 202 if (use_gate) { 203 tmpx_gate = gate_x2[col2]; 204 } 205 } 206#pragma unroll 207 for (int j = 0; j < ncols_dst; ++j) { 208 const float2 tmpy = y2[j*stride_col_y2 + col2]; 209 sumh2[j] += tmpx * make_half2(tmpy.x, tmpy.y); 210 211 if constexpr (has_fusion) { 212 if (use_gate) { 213 sumh2_gate[j] += tmpx_gate * make_half2(tmpy.x, tmpy.y); 214 } 215 } 216 } 217 } 218 219#pragma unroll 220 for (int j = 0; j < ncols_dst; ++j) { 221 sumf[j] = __low2float(sumh2[j]) + __high2float(sumh2[j]); 222 } 223 224 if constexpr (has_fusion) { 225 if (use_gate) { 226#pragma unroll 227 for (int j = 0; j < ncols_dst; ++j) { 228 sumf_gate[j] = __low2float(sumh2_gate[j]) + __high2float(sumh2_gate[j]); 229 } 230 } 231 } 232#else 233 NO_DEVICE_CODE; 234#endif // FP16_AVAILABLE 235 } 236 } else if constexpr (std::is_same_v<T, nv_bfloat16>) { 237//TODO: add support for ggml_cuda_mad for hip_bfloat162 238#if defined(GGML_USE_HIP) 239 const int * x2 = (const int *) x; 240 const int * gate_x2 = nullptr; 241 if constexpr (has_fusion) { 242 if (use_gate) { 243 gate_x2 = (const int *) gate_x; 244 } 245 } 246 for (int col2 = tid; col2 < ncols2; col2 += block_size) { 247 const int tmpx = x2[col2]; 248 int tmpx_gate = 0; 249 if constexpr (has_fusion) { 250 if (use_gate) { 251 tmpx_gate = gate_x2[col2]; 252 } 253 } 254#pragma unroll 255 for (int j = 0; j < ncols_dst; ++j) { 256 const float2 tmpy = y2[j*stride_col_y2 + col2]; 257 const float tmpx0 = ggml_cuda_cast<float>(reinterpret_cast<const nv_bfloat16 *>(&tmpx)[0]); 258 const float tmpx1 = ggml_cuda_cast<float>(reinterpret_cast<const nv_bfloat16 *>(&tmpx)[1]); 259 ggml_cuda_mad(sumf[j], tmpx0, tmpy.x); 260 ggml_cuda_mad(sumf[j], tmpx1, tmpy.y); 261 262 if constexpr (has_fusion) { 263 if (use_gate) { 264 const float tmpx0_gate = ggml_cuda_cast<float>(reinterpret_cast<const nv_bfloat16 *>(&tmpx_gate)[0]); 265 const float tmpx1_gate = ggml_cuda_cast<float>(reinterpret_cast<const nv_bfloat16 *>(&tmpx_gate)[1]); 266 ggml_cuda_mad(sumf_gate[j], tmpx0_gate, tmpy.x); 267 ggml_cuda_mad(sumf_gate[j], tmpx1_gate, tmpy.y); 268 } 269 } 270 } 271 } 272#else 273 const nv_bfloat162 * x2 = (const nv_bfloat162 *) x; 274 [[maybe_unused]] const nv_bfloat162 * gate_x2 = nullptr; 275 if constexpr (has_fusion) { 276 if (use_gate) { 277 gate_x2 = (const nv_bfloat162 *) gate_x; 278 } 279 } 280 for (int col2 = tid; col2 < ncols2; col2 += block_size) { 281 const nv_bfloat162 tmpx = x2[col2]; 282 [[maybe_unused]] nv_bfloat162 tmpx_gate; 283 if constexpr (has_fusion) { 284 if (use_gate) { 285 tmpx_gate = gate_x2[col2]; 286 } 287 } 288#pragma unroll 289 for (int j = 0; j < ncols_dst; ++j) { 290 const float2 tmpy = y2[j*stride_col_y2 + col2]; 291 ggml_cuda_mad(sumf[j], tmpx.x, tmpy.x); 292 ggml_cuda_mad(sumf[j], tmpx.y, tmpy.y); 293 294 if constexpr (has_fusion) { 295 if (use_gate) { 296 ggml_cuda_mad(sumf_gate[j], tmpx_gate.x, tmpy.x); 297 ggml_cuda_mad(sumf_gate[j], tmpx_gate.y, tmpy.y); 298 } 299 } 300 } 301 } 302#endif 303 } else { 304 static_assert(std::is_same_v<T, void>, "unsupported type"); 305 } 306 307 ggml_cuda_pdl_lc(); 308#pragma unroll 309 for (int j = 0; j < ncols_dst; ++j) { 310 sumf[j] = warp_reduce_sum<warp_size>(sumf[j]); 311 312 if constexpr (has_fusion) { 313 if (use_gate) { 314 sumf_gate[j] = warp_reduce_sum<warp_size>(sumf_gate[j]); 315 } 316 } 317 318 if (block_size > warp_size) { 319 buf_iw[tid/warp_size] = sumf[j]; 320 if constexpr (has_fusion) { 321 if (use_gate) { 322 buf_iw_gate[tid/warp_size] = sumf_gate[j]; 323 } 324 } 325 __syncthreads(); 326 if (tid < warp_size) { 327 sumf[j] = buf_iw[tid]; 328 sumf[j] = warp_reduce_sum<warp_size>(sumf[j]); 329 if constexpr (has_fusion) { 330 if (use_gate) { 331 sumf_gate[j] = buf_iw_gate[tid]; 332 sumf_gate[j] = warp_reduce_sum<warp_size>(sumf_gate[j]); 333 } 334 } 335 } 336 337 if (j < ncols_dst) { 338 __syncthreads(); 339 } 340 } 341 } 342 343 if (tid >= ncols_dst) { 344 return; 345 } 346 347 float value = sumf[tid]; 348 349 if constexpr (has_fusion) { 350 if (use_bias) { 351 value += x_bias[tid*stride_col_dst + row]; 352 } 353 354 if (use_gate) { 355 float gate_value = sumf_gate[tid]; 356 if (use_gate_bias) { 357 gate_value += gate_bias[tid*stride_col_dst + row]; 358 } 359 switch (glu_op) { 360 case GGML_GLU_OP_SWIGLU: 361 value *= ggml_cuda_op_silu_single(gate_value); 362 break; 363 case GGML_GLU_OP_GEGLU: 364 value *= ggml_cuda_op_gelu_single(gate_value); 365 break; 366 case GGML_GLU_OP_SWIGLU_OAI: { 367 value = ggml_cuda_op_swiglu_oai_single(gate_value, value); 368 break; 369 } 370 case GGML_GLU_OP_SWIGLU_CLAMP: 371 value = ggml_cuda_op_swiglu_clamp_single(gate_value, value, glu_limit); 372 break; 373 default: 374 break; 375 } 376 } 377 } 378 379 dst[tid*stride_col_dst + row] = value; 380 381 if constexpr (!has_fusion) { 382 GGML_UNUSED_VARS(use_gate, use_bias, use_gate_bias, glu_op, glu_limit, gate_x, x_bias, gate_bias, sumf_gate); 383 } 384} 385 386template<typename T, typename type_acc, int ncols_dst, int block_size, bool is_multi_token_id = false> 387static void mul_mat_vec_f_switch_fusion( 388 const T * x, const float * y, const int32_t * ids, const ggml_cuda_mm_fusion_args_device fusion, float * dst, 389 const int64_t ncols, const uint3 nchannels_y, 390 const int64_t stride_row, const int64_t stride_col_y, const int64_t stride_col_dst, 391 const uint3 channel_ratio, const int stride_channel_x, const int stride_channel_y, const int stride_channel_dst, 392 const uint3 sample_ratio, const int stride_sample_x, const int stride_sample_y, const int stride_sample_dst, 393 const dim3 & block_dims, const dim3 & block_nums, const int nbytes_shared, const int ids_stride, const cudaStream_t stream) { 394 395 const ggml_cuda_kernel_launch_params launch_params = {block_nums, block_dims, nbytes_shared, stream}; 396 397 const bool has_fusion = fusion.gate != nullptr || fusion.x_bias != nullptr || fusion.gate_bias != nullptr; 398 if constexpr (ncols_dst == 1) { 399 if (has_fusion) { 400 ggml_cuda_kernel_launch(mul_mat_vec_f<T, type_acc, ncols_dst, block_size, true, is_multi_token_id>, launch_params, 401 x, y, ids, fusion, dst, ncols, nchannels_y, stride_row, stride_col_y, stride_col_dst, 402 channel_ratio, stride_channel_x, stride_channel_y, stride_channel_dst, 403 sample_ratio, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride); 404 return; 405 } 406 } 407 408 GGML_ASSERT(!has_fusion && "fusion only supported for ncols_dst=1"); 409 410 ggml_cuda_kernel_launch(mul_mat_vec_f<T, type_acc, ncols_dst, block_size, false, is_multi_token_id>, launch_params, 411 x, y, ids, fusion, dst, ncols, nchannels_y, stride_row, stride_col_y, stride_col_dst, 412 channel_ratio, stride_channel_x, stride_channel_y, stride_channel_dst, 413 sample_ratio, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride); 414 415} 416 417template <typename T, typename type_acc, int ncols_dst, bool is_multi_token_id = false> 418void launch_mul_mat_vec_f_cuda( 419 const T * x, const float * y, const int32_t * ids, const ggml_cuda_mm_fusion_args_device fusion, float * dst, 420 const int64_t ncols, const int64_t nrows, 421 const int64_t stride_row, const int64_t stride_col_y, const int64_t stride_col_dst, 422 const int64_t nchannels_x, const int64_t nchannels_y, const int64_t nchannels_dst, 423 const int64_t stride_channel_x, const int64_t stride_channel_y, const int64_t stride_channel_dst, const int64_t nsamples_x, 424 const int64_t nsamples_dst, const int64_t stride_sample_x, const int64_t stride_sample_y, const int64_t stride_sample_dst, 425 const int64_t nsamples_or_ntokens, const int64_t ids_stride, cudaStream_t stream) { 426 GGML_ASSERT(ncols % 2 == 0); 427 GGML_ASSERT(stride_row % 2 == 0); 428 GGML_ASSERT(stride_col_y % 2 == 0); 429 GGML_ASSERT(ids || nchannels_dst % nchannels_x == 0); 430 GGML_ASSERT( nsamples_dst % nsamples_x == 0); 431 const uint3 nchannels_y_fd = ids ? init_fastdiv_values(nchannels_y) : make_uint3(0, 0, 0); 432 const uint3 channel_ratio_fd = ids ? make_uint3(0, 0, 0) : init_fastdiv_values(nchannels_dst / nchannels_x); 433 const uint3 sample_ratio_fd = init_fastdiv_values(nsamples_dst / nsamples_x); 434 435 const int device = ggml_cuda_get_device(); 436 const int warp_size = ggml_cuda_info().devices[device].warp_size; 437 438 int64_t block_size_best = warp_size; 439 int64_t niter_best = (ncols + 2*warp_size - 1) / (2*warp_size); 440 int64_t max_block_size = 256; 441 if(ggml_cuda_info().devices[device].cc > GGML_CUDA_CC_OFFSET_AMD && ggml_cuda_info().devices[device].cc < GGML_CUDA_CC_RDNA1) { 442 max_block_size = 128; 443 } 444 for (int64_t block_size = 2*warp_size; block_size <= max_block_size; block_size += warp_size) { 445 const int64_t niter = (ncols + 2*block_size - 1) / (2*block_size); 446 if (niter < niter_best) { 447 niter_best = niter; 448 block_size_best = block_size; 449 } 450 } 451 452 const bool has_fusion = fusion.gate != nullptr || fusion.x_bias != nullptr || fusion.gate_bias != nullptr; 453 454 const int nbytes_shared = warp_size*sizeof(float) + (has_fusion ? warp_size*sizeof(float) : 0); 455 const dim3 block_nums(nrows, nchannels_dst, nsamples_or_ntokens); 456 const dim3 block_dims(block_size_best, 1, 1); 457 switch (block_size_best) { 458 case 32: { 459 mul_mat_vec_f_switch_fusion<T, type_acc, ncols_dst, 32, is_multi_token_id> 460 (x, y, ids, fusion, dst, ncols/2, nchannels_y_fd, stride_row, stride_col_y/2, stride_col_dst, 461 channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst, 462 sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst, block_dims, block_nums, nbytes_shared, ids_stride, stream); 463 } break; 464 case 64: { 465 mul_mat_vec_f_switch_fusion<T, type_acc, ncols_dst, 64, is_multi_token_id> 466 (x, y, ids, fusion, dst, ncols/2, nchannels_y_fd, stride_row, stride_col_y/2, stride_col_dst, 467 channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst, 468 sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst, block_dims, block_nums, nbytes_shared, ids_stride, stream); 469 } break; 470 case 96: { 471 mul_mat_vec_f_switch_fusion<T, type_acc, ncols_dst, 96, is_multi_token_id> 472 (x, y, ids, fusion, dst, ncols/2, nchannels_y_fd, stride_row, stride_col_y/2, stride_col_dst, 473 channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst, 474 sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst, block_dims, block_nums, nbytes_shared, ids_stride, stream); 475 } break; 476 case 128: { 477 mul_mat_vec_f_switch_fusion<T, type_acc, ncols_dst, 128, is_multi_token_id> 478 (x, y, ids, fusion, dst, ncols/2, nchannels_y_fd, stride_row, stride_col_y/2, stride_col_dst, 479 channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst, 480 sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst, block_dims, block_nums, nbytes_shared, ids_stride, stream); 481 } break; 482 case 160: { 483 mul_mat_vec_f_switch_fusion<T, type_acc, ncols_dst, 160, is_multi_token_id> 484 (x, y, ids, fusion, dst, ncols/2, nchannels_y_fd, stride_row, stride_col_y/2, stride_col_dst, 485 channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst, 486 sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst, block_dims, block_nums, nbytes_shared, ids_stride, stream); 487 } break; 488 case 192: { 489 mul_mat_vec_f_switch_fusion<T, type_acc, ncols_dst, 192, is_multi_token_id> 490 (x, y, ids, fusion, dst, ncols/2, nchannels_y_fd, stride_row, stride_col_y/2, stride_col_dst, 491 channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst, 492 sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst, block_dims, block_nums, nbytes_shared, ids_stride, stream); 493 } break; 494 case 224: { 495 mul_mat_vec_f_switch_fusion<T, type_acc, ncols_dst, 224, is_multi_token_id> 496 (x, y, ids, fusion, dst, ncols/2, nchannels_y_fd, stride_row, stride_col_y/2, stride_col_dst, 497 channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst, 498 sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst, block_dims, block_nums, nbytes_shared, ids_stride, stream); 499 } break; 500 case 256: { 501 mul_mat_vec_f_switch_fusion<T, type_acc, ncols_dst, 256, is_multi_token_id> 502 (x, y, ids, fusion, dst, ncols/2, nchannels_y_fd, stride_row, stride_col_y/2, stride_col_dst, 503 channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst, 504 sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst, block_dims, block_nums, nbytes_shared, ids_stride, stream); 505 } break; 506 default: { 507 GGML_ABORT("fatal error"); 508 } break; 509 } 510} 511 512template <typename T, typename type_acc> 513static void mul_mat_vec_f_cuda_switch_ncols_dst( 514 const T * x, const float * y, const int32_t * ids, const ggml_cuda_mm_fusion_args_device fusion, float * dst, 515 const int64_t ncols, const int64_t nrows, const int64_t ncols_dst, 516 const int64_t stride_row, const int64_t stride_col_y, const int64_t stride_col_dst, 517 const int64_t nchannels_x, const int64_t nchannels_y, const int64_t nchannels_dst, 518 const int64_t stride_channel_x, const int64_t stride_channel_y, const int64_t stride_channel_dst, const int64_t nsamples_x, 519 const int64_t nsamples_dst, const int64_t stride_sample_x, const int64_t stride_sample_y, const int64_t stride_sample_dst, 520 const int64_t ids_stride, cudaStream_t stream) { 521 522 const bool has_ids = ids != nullptr; 523 524 if (has_ids && ncols_dst > 1) { 525 // Multi-token MUL_MAT_ID path only - single-token goes through regular path below 526 constexpr int c_ncols_dst = 1; 527 launch_mul_mat_vec_f_cuda<T, type_acc, c_ncols_dst, true> 528 (x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst, 529 nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, 530 stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, 531 ncols_dst, ids_stride, stream); 532 return; 533 } 534 535 if (has_ids) { 536 // Single-token MUL_MAT_ID path 537 constexpr int c_ncols_dst = 1; 538 launch_mul_mat_vec_f_cuda<T, type_acc, c_ncols_dst> 539 (x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst, 540 nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, 541 stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, 542 ncols_dst, ids_stride, stream); 543 return; 544 } 545 546 switch (ncols_dst) { 547 case 1: 548 launch_mul_mat_vec_f_cuda<T, type_acc, 1> 549 (x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst, 550 nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, 551 stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, 552 nsamples_dst, ids_stride, stream); 553 break; 554 case 2: 555 launch_mul_mat_vec_f_cuda<T, type_acc, 2> 556 (x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst, 557 nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, 558 stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, 559 nsamples_dst, ids_stride, stream); 560 break; 561 case 3: 562 launch_mul_mat_vec_f_cuda<T, type_acc, 3> 563 (x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst, 564 nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, 565 stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, 566 nsamples_dst, ids_stride, stream); 567 break; 568 case 4: 569 launch_mul_mat_vec_f_cuda<T, type_acc, 4> 570 (x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst, 571 nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, 572 stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, 573 nsamples_dst, ids_stride, stream); 574 break; 575 case 5: 576 launch_mul_mat_vec_f_cuda<T, type_acc, 5> 577 (x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst, 578 nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, 579 stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, 580 nsamples_dst, ids_stride, stream); 581 break; 582 case 6: 583 launch_mul_mat_vec_f_cuda<T, type_acc, 6> 584 (x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst, 585 nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, 586 stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, 587 nsamples_dst, ids_stride, stream); 588 break; 589 case 7: 590 launch_mul_mat_vec_f_cuda<T, type_acc, 7> 591 (x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst, 592 nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, 593 stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, 594 nsamples_dst, ids_stride, stream); 595 break; 596 case 8: 597 launch_mul_mat_vec_f_cuda<T, type_acc, 8> 598 (x, y, ids, fusion, dst, ncols, nrows, stride_row, stride_col_y, stride_col_dst, 599 nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, 600 stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, 601 nsamples_dst, ids_stride, stream); 602 break; 603 default: 604 GGML_ABORT("fatal error"); 605 break; 606 } 607} 608 609template<typename T> 610static void mul_mat_vec_f_cuda( 611 const T * x, const float * y, const int32_t * ids, const ggml_cuda_mm_fusion_args_device fusion, float * dst, 612 const int64_t ncols, const int64_t nrows, const int64_t ncols_dst, 613 const int64_t stride_row, const int64_t stride_col_y, const int stride_col_dst, 614 const int64_t nchannels_x, const int64_t nchannels_y, const int64_t nchannels_dst, 615 const int64_t stride_channel_x, const int64_t stride_channel_y, const int64_t stride_channel_dst, const int64_t nsamples_x, 616 const int64_t nsamples_dst, const int64_t stride_sample_x, const int64_t stride_sample_y, const int64_t stride_sample_dst, 617 const int64_t ids_stride, enum ggml_prec prec, cudaStream_t stream) { 618 619 if constexpr(std::is_same_v<T, half>) { 620 if (prec == GGML_PREC_DEFAULT) { 621 mul_mat_vec_f_cuda_switch_ncols_dst<T, half> 622 (x, y, ids, fusion, dst, ncols, nrows, ncols_dst, stride_row, stride_col_y, stride_col_dst, 623 nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, 624 stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream); 625 return; 626 } 627 } 628 mul_mat_vec_f_cuda_switch_ncols_dst<T, float> 629 (x, y, ids, fusion, dst, ncols, nrows, ncols_dst, stride_row, stride_col_y, stride_col_dst, 630 nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, 631 stride_channel_dst, nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, ids_stride, stream); 632} 633 634void 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, 635 const ggml_cuda_mm_fusion_args_host * fusion) { 636 GGML_ASSERT( src1->type == GGML_TYPE_F32); 637 GGML_ASSERT(!ids || ids->type == GGML_TYPE_I32); 638 GGML_ASSERT( dst->type == GGML_TYPE_F32); 639 640 GGML_TENSOR_BINARY_OP_LOCALS; 641 642 const size_t ts_src0 = ggml_type_size(src0->type); 643 const size_t ts_src1 = ggml_type_size(src1->type); 644 const size_t ts_dst = ggml_type_size(dst->type); 645 646 GGML_ASSERT(!ids || ne12 <= MMVF_MAX_BATCH_SIZE); 647 GGML_ASSERT(ne13 == ne3); 648 649 GGML_ASSERT( nb00 == ts_src0); 650 GGML_ASSERT( nb10 == ts_src1); 651 GGML_ASSERT(!ids || ids->nb[0] == ggml_type_size(ids->type)); 652 GGML_ASSERT( nb0 == ts_dst); 653 654 const int cc = ggml_cuda_info().devices[ggml_cuda_get_device()].cc; 655 const enum ggml_prec prec = fast_fp16_available(cc) ? ggml_prec(dst->op_params[0]) : GGML_PREC_F32; 656 657 const float * src1_d = (const float *) src1->data; 658 const int32_t * ids_d = ids ? (const int32_t *) ids->data : nullptr; 659 float * dst_d = (float *) dst->data; 660 661 ggml_cuda_mm_fusion_args_device fusion_local{}; 662 663 if (fusion) { 664 GGML_ASSERT( !ids || dst->ne[2] == 1); 665 GGML_ASSERT( ids || dst->ne[1] == 1); 666 if (fusion->x_bias) { 667 GGML_ASSERT(fusion->x_bias->type == GGML_TYPE_F32); 668 GGML_ASSERT(fusion->x_bias->ne[0] == dst->ne[0]); 669 GGML_ASSERT(!ids || fusion->x_bias->ne[1] == src0->ne[2]); 670 fusion_local.x_bias = fusion->x_bias->data; 671 } 672 if (fusion->gate) { 673 GGML_ASSERT(fusion->gate->type == src0->type && ggml_are_same_stride(fusion->gate, src0)); 674 fusion_local.gate = fusion->gate->data; 675 } 676 if (fusion->gate_bias) { 677 GGML_ASSERT(fusion->gate_bias->type == GGML_TYPE_F32); 678 GGML_ASSERT(fusion->gate_bias->ne[0] == dst->ne[0]); 679 GGML_ASSERT(!ids || fusion->gate_bias->ne[1] == src0->ne[2]); 680 fusion_local.gate_bias = fusion->gate_bias->data; 681 } 682 fusion_local.glu_op = fusion->glu_op; 683 fusion_local.glu_limit = fusion->glu_limit; 684 } 685 686 const int64_t s01 = src0->nb[1] / ts_src0; 687 const int64_t s11 = src1->nb[1] / ts_src1; 688 const int64_t s1 = dst->nb[1] / ts_dst; 689 const int64_t s02 = src0->nb[2] / ts_src0; 690 const int64_t s12 = src1->nb[2] / ts_src1; 691 const int64_t s2 = dst->nb[2] / ts_dst; 692 const int64_t s03 = src0->nb[3] / ts_src0; 693 const int64_t s13 = src1->nb[3] / ts_src1; 694 const int64_t s3 = dst->nb[3] / ts_dst; 695 696 // For MUL_MAT_ID the memory layout is different than for MUL_MAT: 697 const int64_t ncols_dst = ids ? ne2 : ne1; 698 const int64_t nchannels_y = ids ? ne11 : ne12; 699 const int64_t nchannels_dst = ids ? ne1 : ne2; 700 const int64_t stride_col_dst = ids ? s2 : s1; 701 const int64_t stride_col_y = ids ? s12 : s11; 702 const int64_t stride_channel_dst = ids ? s1 : s2; 703 const int64_t stride_channel_y = ids ? s11 : s12; 704 705 const int64_t ids_stride = ids ? ids->nb[1] / ggml_type_size(ids->type) : 0; 706 707 switch (src0->type) { 708 case GGML_TYPE_F32: { 709 const float * src0_d = (const float *) 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_F16: { 715 const half * src0_d = (const half *) 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 case GGML_TYPE_BF16: { 721 const nv_bfloat16 * src0_d = (const nv_bfloat16 *) src0->data; 722 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, 723 ne02, nchannels_y, nchannels_dst, s02, stride_channel_y, stride_channel_dst, 724 ne03, ne3, s03, s13, s3, ids_stride, prec, ctx.stream()); 725 } break; 726 default: 727 GGML_ABORT("unsupported type: %s", ggml_type_name(src0->type)); 728 } 729} 730 731void ggml_cuda_op_mul_mat_vec_f( 732 ggml_backend_cuda_context & ctx, 733 const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, const char * src0_dd_i, const float * src1_ddf_i, 734 const char * src1_ddq_i, float * dst_dd_i, const int64_t row_low, const int64_t row_high, const int64_t src1_ncols, 735 const int64_t src1_padded_row_size, cudaStream_t stream) { 736 737 GGML_ASSERT(src1->type == GGML_TYPE_F32); 738 GGML_ASSERT(dst->type == GGML_TYPE_F32); 739 740 const int64_t ne00 = src0->ne[0]; 741 const int64_t ne10 = src1->ne[0]; 742 const int64_t ne0 = dst->ne[0]; 743 const int64_t row_diff = row_high - row_low; 744 745 const int id = ggml_cuda_get_device(); 746 const int cc = ggml_cuda_info().devices[id].cc; 747 const enum ggml_prec prec = fast_fp16_available(cc) ? ggml_prec(dst->op_params[0]) : GGML_PREC_F32; 748 749 // ggml_cuda_op provides single, contiguous matrices 750 const int64_t stride_row = ne00; 751 const int64_t stride_col_y = ne10; 752 const int64_t stride_col_dst = id == ctx.device ? ne0 : row_diff; // main device has larger memory buffer 753 const int64_t nchannels_x = 1; 754 const int64_t nchannels_y = 1; 755 const int64_t nchannels_dst = 1; 756 const int64_t stride_channel_x = 0; 757 const int64_t stride_channel_y = 0; 758 const int64_t stride_channel_dst = 0; 759 const int64_t nsamples_x = 1; 760 const int64_t nsamples_dst = 1; 761 const int64_t stride_sample_x = 0; 762 const int64_t stride_sample_y = 0; 763 const int64_t stride_sample_dst = 0; 764 765 ggml_cuda_mm_fusion_args_device empty{}; 766 switch (src0->type) { 767 case GGML_TYPE_F32: { 768 const float * src0_d = (const float *) 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_F16: { 774 const half * src0_d = (const half *) 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 case GGML_TYPE_BF16: { 780 const nv_bfloat16 * src0_d = (const nv_bfloat16 *) src0_dd_i; 781 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, 782 nchannels_x, nchannels_y, nchannels_dst, stride_channel_x, stride_channel_y, stride_channel_dst, 783 nsamples_x, nsamples_dst, stride_sample_x, stride_sample_y, stride_sample_dst, 0, prec, stream); 784 } break; 785 default: 786 GGML_ABORT("unsupported type: %s", ggml_type_name(src0->type)); 787 } 788 789 GGML_UNUSED_VARS(ctx, src1, dst, src1_ddq_i, src1_ncols, src1_padded_row_size); 790} 791 792bool ggml_cuda_should_use_mmvf(enum ggml_type type, int cc, const int64_t * src0_ne, const size_t * src0_nb, int64_t ne11) { 793 if (src0_ne[0] % 2 != 0) { 794 return false; 795 } 796 797 const size_t ts = ggml_type_size(type); 798 if (src0_nb[0] != ts) { 799 return false; 800 } 801 802 // Pointers not aligned to the size of half2/nv_bfloat162/float2 would result in a crash: 803 for (size_t i = 1; i < GGML_MAX_DIMS; ++i) { 804 if (src0_nb[i] % (2*ts) != 0) { 805 return false; 806 } 807 } 808 809 switch (type) { 810 case GGML_TYPE_F32: 811 if (GGML_CUDA_CC_IS_NVIDIA(cc)) { 812 if (ampere_mma_available(cc)) { 813 return ne11 <= 3; 814 } 815 if (cc >= GGML_CUDA_CC_TURING) { 816 return ne11 <= 4; 817 } 818 return ne11 <= 3; 819 } else if (GGML_CUDA_CC_IS_AMD(cc)) { 820 if (fp32_mma_hardware_available(cc)) { 821 return ne11 <= 3; 822 } 823 return ne11 <= 8; 824 } 825 return ne11 <= 8; 826 case GGML_TYPE_F16: 827 if (GGML_CUDA_CC_IS_NVIDIA(cc)) { 828 const bool src0_small = (src0_ne[1] <= 512 || src0_ne[2]*src0_ne[3] == 1); 829 if (ampere_mma_available(cc)) { 830 return src0_small && ne11 == 1; 831 } 832 if (cc >= GGML_CUDA_CC_ADA_LOVELACE) { 833 return src0_small && ne11 <= 4; 834 } 835 if (fp16_mma_hardware_available(cc)) { 836 return src0_small && ne11 <= 3; 837 } 838 return ne11 <= 8; 839 } else if (GGML_CUDA_CC_IS_AMD(cc)) { 840 if (fp16_mma_hardware_available(cc)) { 841 if (GGML_CUDA_CC_IS_RDNA3(cc)) { 842 return ne11 <= 3; 843 } 844 if (GGML_CUDA_CC_IS_RDNA4(cc)) { 845 return ne11 <= 5; 846 } 847 return ne11 <= 2; 848 } 849 return ne11 <= 8; 850 } 851 return ne11 <= 8; 852 case GGML_TYPE_BF16: 853 if (GGML_CUDA_CC_IS_NVIDIA(cc)) { 854 const bool src0_small = (src0_ne[1] <= 512 || src0_ne[2]*src0_ne[3] == 1); 855 if (ampere_mma_available(cc)) { 856 return src0_small && ne11 == 1; 857 } 858 if (cc >= GGML_CUDA_CC_ADA_LOVELACE) { 859 return src0_small && ne11 <= 4; 860 } 861 if (bf16_mma_hardware_available(cc)) { 862 return src0_small && ne11 <= 3; 863 } 864 return ne11 <= 8; 865 } else if (GGML_CUDA_CC_IS_AMD(cc)) { 866 if (bf16_mma_hardware_available(cc)) { 867 return ne11 <= 3; 868 } 869 return ne11 <= 8; 870 } 871 return ne11 <= 8; 872 default: 873 return false; 874 } 875}