char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
d9b6be07d
char/aliceai-t5-moe
1#include "common.cuh" 2#include "ggml.h" 3#include "solve_tri.cuh" 4 5#define MAX_N_FAST 64 6#define MAX_K_FAST 32 7 8static __global__ void get_batch_pointers(const float * A, 9 float * X, 10 const float ** A_ptrs, 11 float ** X_ptrs, 12 int64_t ne02, 13 int64_t total_batches, 14 size_t s02, 15 size_t s03, 16 size_t s2, 17 size_t s3) { 18 const int idx = blockIdx.x * blockDim.x + threadIdx.x; 19 if (idx >= total_batches) { 20 return; 21 } 22 23 const int64_t i3 = idx / ne02; 24 const int64_t i2 = idx % ne02; 25 26 A_ptrs[idx] = A + i3 * s03 + i2 * s02; 27 X_ptrs[idx] = X + i3 * s3 + i2 * s2; 28} 29 30static void solve_tri_f32_cublas(ggml_backend_cuda_context & ctx, 31 const float * A, 32 const float * B, 33 float * X, 34 int n, 35 int k, 36 int64_t ne02, 37 int64_t ne03, 38 size_t s02, 39 size_t s03, 40 size_t s12, 41 size_t s13, 42 size_t s2, 43 size_t s3, 44 cudaStream_t stream) { 45 const float alpha = 1.0f; 46 const int64_t total_batches = ne02 * ne03; 47 if (total_batches == 0) { 48 return; 49 } 50 51 // Bulk copy B -> X (contiguous tensors) 52 if (X != B) { 53 const int64_t total_elements_BX = n * k * total_batches; 54 CUDA_CHECK(cudaMemcpyAsync(X, B, total_elements_BX * sizeof(float), cudaMemcpyDeviceToDevice, stream)); 55 } 56 57 const int id = ggml_cuda_get_device(); 58 59 ggml_cuda_pool_alloc<const float *> A_ptrs_alloc(ctx.pool(id), total_batches); 60 ggml_cuda_pool_alloc<float *> X_ptrs_alloc(ctx.pool(id), total_batches); 61 62 const float ** A_ptrs_dev = A_ptrs_alloc.get(); 63 float ** X_ptrs_dev = X_ptrs_alloc.get(); 64 65 get_batch_pointers<<<(total_batches + 255) / 256, 256, 0, stream>>>(A, X, A_ptrs_dev, X_ptrs_dev, ne02, 66 total_batches, s02, s03, s2, s3); 67 68 // Yes, this is necessary, without this we get RMSE errors 69 CUBLAS_CHECK(cublasSetMathMode(ctx.cublas_handle(), CUBLAS_DEFAULT_MATH)); 70 CUBLAS_CHECK(cublasStrsmBatched(ctx.cublas_handle(), CUBLAS_SIDE_RIGHT, CUBLAS_FILL_MODE_UPPER, CUBLAS_OP_N, 71 CUBLAS_DIAG_NON_UNIT, k, n, &alpha, A_ptrs_dev, n, X_ptrs_dev, k, total_batches)); 72 73 // revert to standard mode from common.cuh 74 CUBLAS_CHECK(cublasSetMathMode(ctx.cublas_handle(), CUBLAS_TF32_TENSOR_OP_MATH)); 75 76 GGML_UNUSED_VARS(s12, s13); 77} 78 79// ====================== 80// Fast Kernel (n <= 64, k <= 32) - Warp-based parallel reduction 81// ====================== 82// When ncols_template == 0 the bounds for the loops in this function are not 83// known and can't be unrolled. As we want to keep pragma unroll for all other 84// cases we suppress the clang transformation warning here. 85#ifdef __clang__ 86# pragma clang diagnostic push 87# pragma clang diagnostic ignored "-Wpass-failed" 88#endif // __clang__ 89template <int n_template, int k_template> 90static __global__ void solve_tri_f32_fast(const float * __restrict__ A, 91 const float * __restrict__ B, 92 float * __restrict__ X, 93 const uint3 ne02, 94 const size_t nb02, 95 const size_t nb03, 96 const size_t nb12, 97 const size_t nb13, 98 const size_t nb2, 99 const size_t nb3, 100 const int n_arg, 101 const int k_arg) { 102 const int n = n_template == 0 ? n_arg : n_template; 103 const int k = k_template == 0 ? k_arg : k_template; 104 105 const int batch_idx = blockIdx.x; 106 const int lane = threadIdx.x; 107 const int col_idx = threadIdx.y; 108 109 if (col_idx >= k) { 110 return; 111 } 112 113 const uint2 i02_i03 = fast_div_modulo(batch_idx, ne02); 114 const int64_t i02 = i02_i03.y; 115 const int64_t i03 = i02_i03.x; 116 117 const float * const A_batch = (const float *) (A + i02 * nb02 + i03 * nb03); 118 const float * const B_batch = (const float *) (B + i02 * nb12 + i03 * nb13); 119 float * X_batch = (float *) (X + i02 * nb2 + i03 * nb3); 120 121 __shared__ float sA[MAX_N_FAST * MAX_N_FAST]; 122 123 const int offset = threadIdx.x + threadIdx.y * blockDim.x; 124 125#pragma unroll 126 for (int i = 0; i < n * n; i += k * WARP_SIZE) { 127 const int i0 = i + offset; 128 if (i0 < n * n) { 129 sA[i0] = A_batch[i0]; 130 } 131 } 132 133 __syncthreads(); 134 135 float x_low = (lane < n) ? B_batch[lane * k + col_idx] : 0.0f; 136 float x_high = (WARP_SIZE + lane < n) ? B_batch[(WARP_SIZE + lane) * k + col_idx] : 0.0f; 137 138 const int half = WARP_SIZE; 139 const int nrows_low = (n < half) ? n : half; 140 141#pragma unroll 142 for (int row = 0; row < nrows_low; ++row) { 143 float sum = 0.0f; 144 if (lane < row) { 145 sum += sA[row * n + lane] * x_low; 146 } 147 sum = warp_reduce_sum(sum); 148 149 if (lane == row) { 150 x_low = (x_low - sum) / sA[row * n + row]; 151 } 152 } 153 154#pragma unroll 155 for (int row = half; row < n; ++row) { 156 float sum = sA[row * n + lane] * x_low; 157 const int j = half + lane; 158 if (j < row) { 159 sum += sA[row * n + j] * x_high; 160 } 161 sum = warp_reduce_sum(sum); 162 163 if (lane == row - half) { 164 x_high = (x_high - sum) / sA[row * n + row]; 165 } 166 } 167 168#pragma unroll 169 for (int rr = 0; rr < 2; ++rr) { 170 const int row = rr * WARP_SIZE + lane; 171 if (row < n) { 172 const float val = (row < half) ? x_low : x_high; 173 X_batch[row * k + col_idx] = val; 174 } 175 } 176} 177#ifdef __clang__ 178# pragma clang diagnostic pop 179#endif // __clang__ 180 181static void solve_tri_f32_cuda(const float * A, 182 const float * B, 183 float * X, 184 int n, 185 int k, 186 int64_t ne02, 187 int64_t ne03, 188 size_t nb02, 189 size_t nb03, 190 size_t nb12, 191 size_t nb13, 192 size_t nb2, 193 size_t nb3, 194 cudaStream_t stream) { 195 const uint3 ne02_fd = init_fastdiv_values((uint32_t) ne02); 196 dim3 threads(WARP_SIZE, k); 197 dim3 grid(ne02 * ne03); 198 if (n == 64) { 199 switch (k) { 200 case 32: 201 solve_tri_f32_fast<64, 32> 202 <<<grid, threads, 0, stream>>>(A, B, X, ne02_fd, nb02, nb03, nb12, nb13, nb2, nb3, 0, 0); 203 break; 204 case 16: 205 solve_tri_f32_fast<64, 16> 206 <<<grid, threads, 0, stream>>>(A, B, X, ne02_fd, nb02, nb03, nb12, nb13, nb2, nb3, 0, 0); 207 break; 208 case 14: 209 solve_tri_f32_fast<64, 14> 210 <<<grid, threads, 0, stream>>>(A, B, X, ne02_fd, nb02, nb03, nb12, nb13, nb2, nb3, 0, 0); 211 break; 212 case 12: 213 solve_tri_f32_fast<64, 12> 214 <<<grid, threads, 0, stream>>>(A, B, X, ne02_fd, nb02, nb03, nb12, nb13, nb2, nb3, 0, 0); 215 break; 216 case 10: 217 solve_tri_f32_fast<64, 10> 218 <<<grid, threads, 0, stream>>>(A, B, X, ne02_fd, nb02, nb03, nb12, nb13, nb2, nb3, 0, 0); 219 break; 220 case 8: 221 solve_tri_f32_fast<64, 8> 222 <<<grid, threads, 0, stream>>>(A, B, X, ne02_fd, nb02, nb03, nb12, nb13, nb2, nb3, 0, 0); 223 break; 224 case 6: 225 solve_tri_f32_fast<64, 6> 226 <<<grid, threads, 0, stream>>>(A, B, X, ne02_fd, nb02, nb03, nb12, nb13, nb2, nb3, 0, 0); 227 break; 228 case 4: 229 solve_tri_f32_fast<64, 4> 230 <<<grid, threads, 0, stream>>>(A, B, X, ne02_fd, nb02, nb03, nb12, nb13, nb2, nb3, 0, 0); 231 break; 232 case 2: 233 solve_tri_f32_fast<64, 2> 234 <<<grid, threads, 0, stream>>>(A, B, X, ne02_fd, nb02, nb03, nb12, nb13, nb2, nb3, 0, 0); 235 break; 236 case 1: 237 solve_tri_f32_fast<64, 1> 238 <<<grid, threads, 0, stream>>>(A, B, X, ne02_fd, nb02, nb03, nb12, nb13, nb2, nb3, 0, 0); 239 break; 240 default: 241 solve_tri_f32_fast<0, 0> 242 <<<grid, threads, 0, stream>>>(A, B, X, ne02_fd, nb02, nb03, nb12, nb13, nb2, nb3, n, k); 243 } 244 } else { // run general case 245 solve_tri_f32_fast<0, 0> 246 <<<grid, threads, 0, stream>>>(A, B, X, ne02_fd, nb02, nb03, nb12, nb13, nb2, nb3, n, k); 247 } 248} 249 250void ggml_cuda_op_solve_tri(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { 251 const ggml_tensor * src0 = dst->src[0]; // A (n×n, lower triangular) 252 const ggml_tensor * src1 = dst->src[1]; // B (n×k) 253 254 ggml_is_contiguous(src0); 255 ggml_is_contiguous(src1); 256 257 const int64_t n = src0->ne[0]; 258 const int64_t k = src1->ne[0]; 259 const int64_t ne02 = src0->ne[2]; 260 const int64_t ne03 = src0->ne[3]; 261 262 if (n <= MAX_N_FAST && k <= MAX_K_FAST) { 263 solve_tri_f32_cuda((const float *) src0->data, (const float *) src1->data, (float *) dst->data, n, k, 264 src0->ne[2], src0->ne[3], src0->nb[2] / sizeof(float), src0->nb[3] / sizeof(float), 265 src1->nb[2] / sizeof(float), src1->nb[3] / sizeof(float), dst->nb[2] / sizeof(float), 266 dst->nb[3] / sizeof(float), ctx.stream()); 267 } else { 268 solve_tri_f32_cublas(ctx, (const float *) src0->data, (const float *) src1->data, (float *) dst->data, n, k, 269 ne02, ne03, src0->nb[2] / sizeof(float), src0->nb[3] / sizeof(float), 270 src1->nb[2] / sizeof(float), src1->nb[3] / sizeof(float), dst->nb[2] / sizeof(float), 271 dst->nb[3] / sizeof(float), ctx.stream()); 272 } 273}