char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
0190529ec
char/aliceai-t5-moe
1#include "unary.cuh" 2#include "convert.cuh" 3 4static __device__ __forceinline__ float op_abs(float x) { 5 return fabsf(x); 6} 7 8static __device__ __forceinline__ float op_sgn(float x) { 9 return (x > 0.f ? 1.f : ((x < 0.f ? -1.f : 0.f))); 10} 11 12static __device__ __forceinline__ float op_neg(float x) { 13 return -x; 14} 15 16static __device__ __forceinline__ float op_step(float x) { 17 return x > 0.0f; 18} 19 20static __device__ __forceinline__ float op_gelu(float x) { 21 return ggml_cuda_op_gelu_single(x); 22} 23 24static __device__ __forceinline__ float op_gelu_erf(float x) { 25 const float SQRT_2_INV = 0.70710678118654752440084436210484f; 26 27 return 0.5f*x*(1.0f + erff(x*SQRT_2_INV)); 28} 29 30static __device__ __forceinline__ float op_gelu_quick(float x) { 31 const float GELU_QUICK_COEF = -1.702f; 32 33 return x * (1.0f / (1.0f + expf(GELU_QUICK_COEF * x))); 34} 35 36static __device__ __forceinline__ float op_silu(float x) { 37 return ggml_cuda_op_silu_single(x); 38} 39 40static __device__ __forceinline__ float op_tanh(float x) { 41 return tanhf(x); 42} 43 44static __device__ __forceinline__ float op_relu(float x) { 45 return fmaxf(x, 0); 46} 47 48static __device__ __forceinline__ float op_sigmoid(float x) { 49 return 1.0f / (1.0f + expf(-x)); 50} 51 52static __device__ __forceinline__ float op_hardsigmoid(float x) { 53 return fminf(1.0f, fmaxf(0.0f, (x + 3.0f) / 6.0f)); 54} 55 56static __device__ __forceinline__ float op_hardswish(float x) { 57 return x * fminf(1.0f, fmaxf(0.0f, (x + 3.0f) / 6.0f)); 58} 59 60static __device__ __forceinline__ float op_exp(float x) { 61 return expf(x); 62} 63 64static __device__ __forceinline__ float op_sqr(float x) { 65 return x * x; 66} 67 68static __device__ __forceinline__ float op_relu_sqr(float x) { 69 const float r = fmaxf(x, 0.0f); 70 return r * r; 71} 72 73static __device__ __forceinline__ float op_sqrt(float x) { 74 return sqrtf(x); 75} 76 77static __device__ __forceinline__ float op_sin(float x) { 78 return sinf(x); 79} 80 81static __device__ __forceinline__ float op_cos(float x) { 82 return cosf(x); 83} 84 85static __device__ __forceinline__ float op_log(float x) { 86 return logf(x); 87} 88 89static __device__ __forceinline__ float op_expm1(float x) { 90 return expm1f(x); 91} 92 93static __device__ __forceinline__ float op_softplus(float x) { 94 return (x > 20.0f) ? x : logf(1.0f + expf(x)); 95} 96 97static __device__ __forceinline__ float op_elu(float x) { 98 return (x > 0.f) ? x : expm1f(x); 99} 100 101static __device__ __forceinline__ float op_floor(float x) { 102 return floorf(x); 103} 104 105static __device__ __forceinline__ float op_ceil(float x) { 106 return ceilf(x); 107} 108 109static __device__ __forceinline__ float op_round(float x) { 110 return round(x); 111} 112 113static __device__ __forceinline__ float op_trunc(float x) { 114 return trunc(x); 115} 116 117template <float (*op)(float), typename T> 118static __global__ void unary_op_kernel(const T * x, T * dst, const int k) { 119 ggml_cuda_pdl_lc(); 120 const int i = blockDim.x*blockIdx.x + threadIdx.x; 121 122 if (i >= k) { 123 return; 124 } 125 126 ggml_cuda_pdl_sync(); 127 dst[i] = (T)op((float)x[i]); 128} 129 130template <float (*op)(float), typename T> 131static void unary_cuda(const T * x, T * dst, const int k, cudaStream_t stream) { 132 const int num_blocks = (k + CUDA_NEG_BLOCK_SIZE - 1) / CUDA_NEG_BLOCK_SIZE; 133 const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params((dim3)num_blocks, CUDA_NEG_BLOCK_SIZE, 0, stream); 134 ggml_cuda_kernel_launch(unary_op_kernel<op, T>, launch_params, x, dst, k); 135} 136 137template <float (*op)(float)> 138void ggml_cuda_op_unary(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 139 const ggml_tensor * src0 = dst->src[0]; 140 const void * src0_d = src0->data; 141 void * dst_d = dst->data; 142 cudaStream_t stream = ctx.stream(); 143 144 GGML_ASSERT(ggml_is_contiguous(src0)); 145 146 GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); 147 GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); 148 GGML_ASSERT(src0->type == dst->type); 149 150 if (src0->type == GGML_TYPE_F16) { 151 unary_cuda<op>((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), stream); 152 } else { 153 unary_cuda<op>((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), stream); 154 } 155} 156 157void ggml_cuda_op_abs(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 158 ggml_cuda_op_unary<op_abs>(ctx, dst); 159} 160 161void ggml_cuda_op_sgn(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 162 ggml_cuda_op_unary<op_sgn>(ctx, dst); 163} 164 165void ggml_cuda_op_neg(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 166 ggml_cuda_op_unary<op_neg>(ctx, dst); 167} 168 169void ggml_cuda_op_step(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 170 ggml_cuda_op_unary<op_step>(ctx, dst); 171} 172 173void ggml_cuda_op_gelu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 174 ggml_cuda_op_unary<op_gelu>(ctx, dst); 175} 176 177void ggml_cuda_op_gelu_erf(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 178 ggml_cuda_op_unary<op_gelu_erf>(ctx, dst); 179} 180 181void ggml_cuda_op_gelu_quick(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 182 ggml_cuda_op_unary<op_gelu_quick>(ctx, dst); 183} 184 185void ggml_cuda_op_silu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 186 ggml_cuda_op_unary<op_silu>(ctx, dst); 187} 188 189void ggml_cuda_op_tanh(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 190 ggml_cuda_op_unary<op_tanh>(ctx, dst); 191} 192 193void ggml_cuda_op_relu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 194 ggml_cuda_op_unary<op_relu>(ctx, dst); 195} 196 197void ggml_cuda_op_sigmoid(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 198 ggml_cuda_op_unary<op_sigmoid>(ctx, dst); 199} 200 201void ggml_cuda_op_hardsigmoid(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 202 ggml_cuda_op_unary<op_hardsigmoid>(ctx, dst); 203} 204 205void ggml_cuda_op_hardswish(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 206 ggml_cuda_op_unary<op_hardswish>(ctx, dst); 207} 208 209void ggml_cuda_op_exp(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 210 ggml_cuda_op_unary<op_exp>(ctx, dst); 211} 212 213void ggml_cuda_op_sqr(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 214 ggml_cuda_op_unary<op_sqr>(ctx, dst); 215} 216 217void ggml_cuda_op_sqrt(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 218 ggml_cuda_op_unary<op_sqrt>(ctx, dst); 219} 220 221void ggml_cuda_op_sin(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 222 ggml_cuda_op_unary<op_sin>(ctx, dst); 223} 224 225void ggml_cuda_op_cos(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 226 ggml_cuda_op_unary<op_cos>(ctx, dst); 227} 228 229void ggml_cuda_op_log(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 230 ggml_cuda_op_unary<op_log>(ctx, dst); 231} 232 233void ggml_cuda_op_elu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 234 ggml_cuda_op_unary<op_elu>(ctx, dst); 235} 236 237void ggml_cuda_op_floor(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 238 ggml_cuda_op_unary<op_floor>(ctx, dst); 239} 240 241void ggml_cuda_op_ceil(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 242 ggml_cuda_op_unary<op_ceil>(ctx, dst); 243} 244 245void ggml_cuda_op_round(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 246 ggml_cuda_op_unary<op_round>(ctx, dst); 247} 248 249void ggml_cuda_op_trunc(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 250 ggml_cuda_op_unary<op_trunc>(ctx, dst); 251} 252 253void ggml_cuda_op_expm1(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 254 ggml_cuda_op_unary<op_expm1>(ctx, dst); 255} 256 257void ggml_cuda_op_softplus(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 258 ggml_cuda_op_unary<op_softplus>(ctx, dst); 259} 260/* gated ops */ 261 262template <float (*op)(float), typename T> 263static __global__ void unary_gated_op_kernel(const T * x, const T * g, T * dst, const int64_t k, const int64_t n, const int64_t o0, const int64_t o1) { 264 ggml_cuda_pdl_lc(); 265 const int64_t i = int64_t(blockDim.x)*blockIdx.x + threadIdx.x; 266 267 if (i >= k) { 268 return; 269 } 270 271 // perform base op and multiply with gate (either offset in same tensor or a separate one) 272 const int64_t j0 = (i / n) * o0 + (i % n); 273 const int64_t j1 = o0 == o1 ? j0 : (i / n) * o1 + (i % n); 274 275 ggml_cuda_pdl_sync(); 276 dst[i] = (T)(op((float)x[j0]) * (float)g[j1]); 277} 278 279template <float (*op)(float), typename T> 280static void unary_gated_cuda(const T * x, const T * g, T * dst, const int64_t k, const int64_t n, const int64_t o0, const int64_t o1, cudaStream_t stream) { 281 const int64_t num_blocks = (k + CUDA_GLU_BLOCK_SIZE - 1) / CUDA_GLU_BLOCK_SIZE; 282 const ggml_cuda_kernel_launch_params launch_params = ggml_cuda_kernel_launch_params((dim3)num_blocks, CUDA_GLU_BLOCK_SIZE, 0, stream); 283 ggml_cuda_kernel_launch(unary_gated_op_kernel<op, T>, launch_params, x, g, dst, k, n, o0, o1); 284} 285 286template <float (*op)(float)> 287void ggml_cuda_op_unary_gated(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 288 const ggml_tensor * src0 = dst->src[0]; 289 const ggml_tensor * src1 = dst->src[1]; 290 void * src0_d = src0->data; 291 void * src1_d = src1 ? src1->data : src0->data; 292 const int64_t src0_o = src0->nb[1]; 293 const int64_t src1_o = src1 ? src1->nb[1] : src0->nb[1]; 294 void * dst_d = dst->data; 295 const int64_t nc = src1 ? src0->ne[0] : src0->ne[0] / 2; 296 cudaStream_t stream = ctx.stream(); 297 298 GGML_ASSERT(ggml_is_contiguous_1(src0)); 299 GGML_ASSERT(src0->nb[0] == ggml_element_size(src0)); 300 GGML_ASSERT(ggml_is_contiguous(dst)); 301 302 GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); 303 GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); 304 GGML_ASSERT(src0->type == dst->type); 305 GGML_ASSERT(dst->ne[0] == nc); 306 GGML_ASSERT(ggml_nrows(dst) == ggml_nrows(src0)); 307 308 if (src1) { 309 GGML_ASSERT(ggml_is_contiguous_1(src1)); 310 GGML_ASSERT(src1->nb[0] == ggml_element_size(src1)); 311 GGML_ASSERT(src1->ne[0] == nc); 312 GGML_ASSERT(src0->type == src1->type); 313 } 314 315 const int32_t swapped = ((const int32_t *) dst->op_params)[1]; 316 317 if (src0->type == GGML_TYPE_F16) { 318 half * src0_p = (half *) src0_d; 319 half * src1_p = (half *) src1_d; 320 321 if (!src1) { 322 src0_p += swapped ? nc : 0; 323 src1_p += swapped ? 0 : nc; 324 } 325 326 unary_gated_cuda<op>(src0_p, src1_p, (half *)dst_d, ggml_nelements(dst), nc, src0_o / sizeof(half), src1_o / sizeof(half), stream); 327 } else { 328 float * src0_p = (float *) src0_d; 329 float * src1_p = (float *) src1_d; 330 331 if (!src1) { 332 src0_p += swapped ? nc : 0; 333 src1_p += swapped ? 0 : nc; 334 } 335 336 unary_gated_cuda<op>(src0_p, src1_p, (float *)dst_d, ggml_nelements(dst), nc, src0_o / sizeof(float), src1_o / sizeof(float), stream); 337 } 338} 339 340void ggml_cuda_op_reglu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 341 ggml_cuda_op_unary_gated<op_relu>(ctx, dst); 342} 343 344void ggml_cuda_op_geglu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 345 ggml_cuda_op_unary_gated<op_gelu>(ctx, dst); 346} 347 348void ggml_cuda_op_swiglu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 349 ggml_cuda_op_unary_gated<op_silu>(ctx, dst); 350} 351 352void ggml_cuda_op_geglu_erf(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 353 ggml_cuda_op_unary_gated<op_gelu_erf>(ctx, dst); 354} 355 356void ggml_cuda_op_geglu_quick(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 357 ggml_cuda_op_unary_gated<op_gelu_quick>(ctx, dst); 358} 359 360// swiglu_oai 361 362template <typename T> 363static __global__ void swiglu_oai_kernel(const T * x, const T * g, T * dst, const int64_t k, const int64_t n, const int64_t o0, const int64_t o1, float alpha, float limit) { 364 const int64_t i = int64_t(blockDim.x)*blockIdx.x + threadIdx.x; 365 366 if (i >= k) { 367 return; 368 } 369 370 // perform base op and multiply with gate (either offset in same tensor or a separate one) 371 const int64_t j0 = (i / n) * o0 + (i % n); 372 const int64_t j1 = o0 == o1 ? j0 : (i / n) * o1 + (i % n); 373 374 float xi = x[j0]; 375 float gi = g[j1]; 376 377 dst[i] = ggml_cuda_op_swiglu_oai_single(xi, gi, alpha, limit); 378} 379 380template <typename T> 381static void swiglu_oai_cuda(const T * x, const T * g, T * dst, const int64_t k, const int64_t n, const int64_t o0, const int64_t o1, const float alpha, const float limit, cudaStream_t stream) { 382 const int64_t num_blocks = (k + CUDA_GLU_BLOCK_SIZE - 1) / CUDA_GLU_BLOCK_SIZE; 383 swiglu_oai_kernel<<<num_blocks, CUDA_GLU_BLOCK_SIZE, 0, stream>>>(x, g, dst, k, n, o0, o1, alpha, limit); 384} 385 386void ggml_cuda_op_swiglu_oai(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 387 const ggml_tensor * src0 = dst->src[0]; 388 const ggml_tensor * src1 = dst->src[1]; 389 void * src0_d = src0->data; 390 void * src1_d = src1 ? src1->data : src0->data; 391 const int64_t src0_o = src0->nb[1]; 392 const int64_t src1_o = src1 ? src1->nb[1] : src0->nb[1]; 393 void * dst_d = dst->data; 394 const int64_t nc = src1 ? src0->ne[0] : src0->ne[0] / 2; 395 cudaStream_t stream = ctx.stream(); 396 397 GGML_ASSERT(ggml_is_contiguous_1(src0)); 398 GGML_ASSERT(src0->nb[0] == ggml_element_size(src0)); 399 GGML_ASSERT(ggml_is_contiguous(dst)); 400 401 GGML_ASSERT(src0->type == GGML_TYPE_F32); 402 GGML_ASSERT( dst->type == GGML_TYPE_F32); 403 GGML_ASSERT(src0->type == dst->type); 404 GGML_ASSERT(dst->ne[0] == nc); 405 GGML_ASSERT(ggml_nrows(dst) == ggml_nrows(src0)); 406 407 if (src1) { 408 GGML_ASSERT(ggml_is_contiguous_1(src1)); 409 GGML_ASSERT(src1->nb[0] == ggml_element_size(src1)); 410 GGML_ASSERT(src1->ne[0] == nc); 411 GGML_ASSERT(src0->type == src1->type); 412 } 413 414 //const int32_t swapped = ((const int32_t *) dst->op_params)[1]; 415 const int32_t swapped = ggml_get_op_params_i32(dst, 1); 416 const float alpha = ggml_get_op_params_f32(dst, 2); 417 const float limit = ggml_get_op_params_f32(dst, 3); 418 419 float * src0_p = (float *) src0_d; 420 float * src1_p = (float *) src1_d; 421 422 if (!src1) { 423 src0_p += swapped ? nc : 0; 424 src1_p += swapped ? 0 : nc; 425 } 426 427 swiglu_oai_cuda(src0_p, src1_p, (float *)dst_d, ggml_nelements(dst), nc, src0_o / sizeof(float), src1_o / sizeof(float), alpha, limit, stream); 428} 429 430// swiglu_clamp 431 432template <typename T> 433static __global__ void swiglu_clamp_kernel(const T * gate, const T * up, T * dst, const int64_t k, const int64_t n, const int64_t o0, const int64_t o1, float limit) { 434 const int64_t i = int64_t(blockDim.x)*blockIdx.x + threadIdx.x; 435 436 if (i >= k) { 437 return; 438 } 439 440 const int64_t j0 = (i / n) * o0 + (i % n); 441 const int64_t j1 = o0 == o1 ? j0 : (i / n) * o1 + (i % n); 442 443 dst[i] = (T) ggml_cuda_op_swiglu_clamp_single((float) gate[j0], (float) up[j1], limit); 444} 445 446template <typename T> 447static void swiglu_clamp_cuda(const T * gate, const T * up, T * dst, const int64_t k, const int64_t n, const int64_t o0, const int64_t o1, const float limit, cudaStream_t stream) { 448 const int64_t num_blocks = (k + CUDA_GLU_BLOCK_SIZE - 1) / CUDA_GLU_BLOCK_SIZE; 449 swiglu_clamp_kernel<<<num_blocks, CUDA_GLU_BLOCK_SIZE, 0, stream>>>(gate, up, dst, k, n, o0, o1, limit); 450} 451 452void ggml_cuda_op_swiglu_clamp(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 453 const ggml_tensor * src0 = dst->src[0]; 454 const ggml_tensor * src1 = dst->src[1]; 455 void * src0_d = src0->data; 456 void * src1_d = src1 ? src1->data : src0->data; 457 const int64_t src0_o = src0->nb[1]; 458 const int64_t src1_o = src1 ? src1->nb[1] : src0->nb[1]; 459 void * dst_d = dst->data; 460 const int64_t nc = src1 ? src0->ne[0] : src0->ne[0] / 2; 461 cudaStream_t stream = ctx.stream(); 462 463 GGML_ASSERT(ggml_is_contiguous_1(src0)); 464 GGML_ASSERT(src0->nb[0] == ggml_element_size(src0)); 465 GGML_ASSERT(ggml_is_contiguous(dst)); 466 467 GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); 468 GGML_ASSERT(src0->type == dst->type); 469 GGML_ASSERT(dst->ne[0] == nc); 470 GGML_ASSERT(ggml_nrows(dst) == ggml_nrows(src0)); 471 472 if (src1) { 473 GGML_ASSERT(ggml_is_contiguous_1(src1)); 474 GGML_ASSERT(src1->nb[0] == ggml_element_size(src1)); 475 GGML_ASSERT(src1->ne[0] == nc); 476 GGML_ASSERT(src0->type == src1->type); 477 } 478 479 const int32_t swapped = ggml_get_op_params_i32(dst, 1); 480 const float limit = ggml_get_op_params_f32(dst, 3); 481 482 if (src0->type == GGML_TYPE_F16) { 483 half * src0_p = (half *) src0_d; 484 half * src1_p = (half *) src1_d; 485 486 if (!src1) { 487 src0_p += swapped ? nc : 0; 488 src1_p += swapped ? 0 : nc; 489 } 490 491 swiglu_clamp_cuda(src0_p, src1_p, (half *) dst_d, ggml_nelements(dst), nc, src0_o / sizeof(half), src1_o / sizeof(half), limit, stream); 492 } else { 493 float * src0_p = (float *) src0_d; 494 float * src1_p = (float *) src1_d; 495 496 if (!src1) { 497 src0_p += swapped ? nc : 0; 498 src1_p += swapped ? 0 : nc; 499 } 500 501 swiglu_clamp_cuda(src0_p, src1_p, (float *) dst_d, ggml_nelements(dst), nc, src0_o / sizeof(float), src1_o / sizeof(float), limit, stream); 502 } 503} 504 505/* CUDA kernel + launcher for xIELU */ 506 507template <typename T> 508static __global__ void xielu_kernel(const T * x, T * dst, const int k, float alpha_n, float alpha_p, float beta, float eps) { 509 const int i = blockDim.x*blockIdx.x + threadIdx.x; 510 511 if (i >= k) { 512 return; 513 } 514 515 const float xi = ggml_cuda_cast<float>(x[i]); 516 517 const float gate_pos = (xi > 0.0f); 518 const float y_pos = alpha_p * xi * xi + beta * xi; 519 const float min_v_eps = fminf(xi, eps); 520 const float y_neg = (expm1f(min_v_eps) - xi) * alpha_n + beta * xi; 521 const float out = gate_pos * y_pos + (1.0f - gate_pos) * y_neg; 522 523 dst[i] = ggml_cuda_cast<T>(out); 524} 525 526template <typename T> 527static void xielu_cuda(const T * x, T * dst, const int k, float alpha_n, float alpha_p, float beta, float eps, cudaStream_t stream) { 528 const int num_blocks = (k + CUDA_XIELU_BLOCK_SIZE) / CUDA_XIELU_BLOCK_SIZE; 529 xielu_kernel<<<num_blocks, CUDA_XIELU_BLOCK_SIZE, 0, stream>>>(x, dst, k, alpha_n, alpha_p, beta, eps); 530} 531 532void ggml_cuda_op_xielu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 533 const ggml_tensor * src0 = dst->src[0]; 534 const void * src0_d = src0->data; 535 void * dst_d = dst->data; 536 cudaStream_t stream = ctx.stream(); 537 538 GGML_ASSERT(ggml_is_contiguous(src0)); 539 540 GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); 541 GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); 542 GGML_ASSERT(src0->type == dst->type); 543 544 const float alpha_n = ggml_get_op_params_f32(dst, 1); 545 const float alpha_p = ggml_get_op_params_f32(dst, 2); 546 const float beta = ggml_get_op_params_f32(dst, 3); 547 const float eps = ggml_get_op_params_f32(dst, 4); 548 549 if (src0->type == GGML_TYPE_F16) { 550 xielu_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), alpha_n, alpha_p, beta, eps, stream); 551 } else { 552 xielu_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), alpha_n, alpha_p, beta, eps, stream); 553 } 554} 555 556 557 558/* silu_back */ 559 560static __device__ __forceinline__ float op_silu_back(float grad, float x) { 561 const float s = 1.0f / (1.0f + expf(-x)); 562 return grad * s * (1.0f + x * (1.0f - s)); 563} 564 565template <class T> 566static __global__ void silu_back_kernel(const T * grad, const T * xf, T * dst, const int k) { 567 const int i = blockDim.x*blockIdx.x + threadIdx.x; 568 569 if (i >= k) { 570 return; 571 } 572 573 dst[i] = (T)op_silu_back((float)grad[i], (float)xf[i]); 574} 575 576template <class T> 577static void silu_back_cuda(const T * grad, const T * x, T * dst, const int k, cudaStream_t stream) { 578 const int num_blocks = (k + CUDA_SILU_BACK_BLOCK_SIZE - 1) / CUDA_SILU_BLOCK_SIZE; 579 silu_back_kernel<<<num_blocks, CUDA_SILU_BACK_BLOCK_SIZE, 0, stream>>>(grad, x, dst, k); 580} 581 582void ggml_cuda_op_silu_back(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 583 const ggml_tensor * src0 = dst->src[0]; // input from forward pass 584 const ggml_tensor * src1 = dst->src[1]; // grads of forward pass output 585 586 const float * src0_d = (const float *) src0->data; 587 const float * src1_d = (const float *) src1->data; 588 float * dst_d = (float *) dst->data; 589 590 cudaStream_t stream = ctx.stream(); 591 592 GGML_ASSERT(ggml_is_contiguous(src0)); 593 594 GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); 595 GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); 596 GGML_ASSERT(src0->type == dst->type); 597 598 if (src0->type == GGML_TYPE_F16) { 599 silu_back_cuda((const half *)src0_d, (const half *)src1_d, (half *)dst_d, ggml_nelements(src0), stream); 600 } else { 601 silu_back_cuda((const float*)src0_d, (const float*)src1_d, (float *)dst_d, ggml_nelements(src0), stream); 602 } 603} 604 605/* leaky relu */ 606 607static __device__ __forceinline__ float op_leaky_relu(float x, const float negative_slope) { 608 return fmaxf(x, 0) + fminf(x, 0.0f) * negative_slope; 609} 610 611template <class T> 612static __global__ void leaky_relu_kernel(const T * x, T * dst, const int k, const float negative_slope) { 613 const int i = blockDim.x*blockIdx.x + threadIdx.x; 614 615 if (i >= k) { 616 return; 617 } 618 619 dst[i] = (T)op_leaky_relu((float)x[i], negative_slope); 620} 621 622template <class T> 623static void leaky_relu_cuda(const T * x, T * dst, const int k, const float negative_slope, cudaStream_t stream) { 624 const int num_blocks = (k + CUDA_RELU_BLOCK_SIZE - 1) / CUDA_RELU_BLOCK_SIZE; 625 leaky_relu_kernel<<<num_blocks, CUDA_RELU_BLOCK_SIZE, 0, stream>>>(x, dst, k, negative_slope); 626} 627 628void ggml_cuda_op_leaky_relu(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 629 const ggml_tensor * src0 = dst->src[0]; 630 const void * src0_d = src0->data; 631 void * dst_d = dst->data; 632 cudaStream_t stream = ctx.stream(); 633 634 GGML_ASSERT(ggml_is_contiguous(src0)); 635 636 GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16); 637 GGML_ASSERT( dst->type == GGML_TYPE_F32 || dst->type == GGML_TYPE_F16); 638 GGML_ASSERT(src0->type == dst->type); 639 640 float negative_slope; 641 memcpy(&negative_slope, dst->op_params, sizeof(float)); 642 643 if (src0->type == GGML_TYPE_F16) { 644 leaky_relu_cuda((const half *)src0_d, (half *)dst_d, ggml_nelements(src0), negative_slope, stream); 645 } else { 646 leaky_relu_cuda((const float *)src0_d, (float *)dst_d, ggml_nelements(src0), negative_slope, stream); 647 } 648} 649 650/* fused unary + mul */ 651 652template <float (*op)(float)> 653static void ggml_cuda_op_unary_mul_impl(ggml_backend_cuda_context & ctx, ggml_tensor * unary_node, ggml_tensor * mul_node) { 654 // unary_node: UNARY op applied to unary_node->src[0] 655 // mul_node: MUL(a, b) where one of a/b is unary_node 656 // Output goes to mul_node->data 657 658 const ggml_tensor * unary_src = unary_node->src[0]; // input to the unary op 659 const ggml_tensor * other_src = (mul_node->src[0] == unary_node) ? mul_node->src[1] : mul_node->src[0]; 660 661 GGML_ASSERT(ggml_is_contiguous_1(unary_src)); 662 GGML_ASSERT(unary_src->nb[0] == ggml_element_size(unary_src)); 663 GGML_ASSERT(ggml_is_contiguous_1(other_src)); 664 GGML_ASSERT(other_src->nb[0] == ggml_element_size(other_src)); 665 GGML_ASSERT(ggml_are_same_shape(unary_src, other_src)); 666 667 GGML_ASSERT(unary_src->type == GGML_TYPE_F32 || unary_src->type == GGML_TYPE_F16); 668 GGML_ASSERT(unary_src->type == other_src->type); 669 GGML_ASSERT(unary_src->type == mul_node->type); 670 671 cudaStream_t stream = ctx.stream(); 672 673 const int64_t k = ggml_nelements(mul_node); 674 const int64_t nc = unary_src->ne[0]; 675 const int64_t unary_stride = unary_src->nb[1]; 676 const int64_t other_stride = other_src->nb[1]; 677 678 if (unary_src->type == GGML_TYPE_F16) { 679 unary_gated_cuda<op>((const half *) unary_src->data, (const half *) other_src->data, 680 (half *) mul_node->data, k, nc, 681 unary_stride / sizeof(half), other_stride / sizeof(half), stream); 682 } else { 683 unary_gated_cuda<op>((const float *) unary_src->data, (const float *) other_src->data, 684 (float *) mul_node->data, k, nc, 685 unary_stride / sizeof(float), other_stride / sizeof(float), stream); 686 } 687} 688 689void ggml_cuda_op_unary_mul(ggml_backend_cuda_context & ctx, ggml_tensor * unary_node, ggml_tensor * mul_node) { 690 switch (ggml_get_unary_op(unary_node)) { 691 case GGML_UNARY_OP_SILU: 692 ggml_cuda_op_unary_mul_impl<op_silu>(ctx, unary_node, mul_node); 693 break; 694 case GGML_UNARY_OP_SIGMOID: 695 ggml_cuda_op_unary_mul_impl<op_sigmoid>(ctx, unary_node, mul_node); 696 break; 697 case GGML_UNARY_OP_SOFTPLUS: 698 ggml_cuda_op_unary_mul_impl<op_softplus>(ctx, unary_node, mul_node); 699 break; 700 default: 701 GGML_ABORT("Unsupported unary op for fused unary+mul"); 702 } 703} 704 705/* fused relu + sqr */ 706 707void ggml_cuda_op_relu_sqr(ggml_backend_cuda_context & ctx, ggml_tensor * relu_node, ggml_tensor * sqr_node) { 708 const ggml_tensor * src = relu_node->src[0]; 709 cudaStream_t stream = ctx.stream(); 710 711 GGML_ASSERT(ggml_is_contiguous(src)); 712 GGML_ASSERT(src->type == GGML_TYPE_F32 || src->type == GGML_TYPE_F16); 713 GGML_ASSERT(src->type == sqr_node->type); 714 715 const int k = ggml_nelements(src); 716 if (src->type == GGML_TYPE_F16) { 717 unary_cuda<op_relu_sqr>((const half *)src->data, (half *)sqr_node->data, k, stream); 718 } else { 719 unary_cuda<op_relu_sqr>((const float *)src->data, (float *)sqr_node->data, k, stream); 720 } 721}