-
Notifications
You must be signed in to change notification settings - Fork 21.6k
CUDA: add COL2IM_1D op #25151
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CUDA: add COL2IM_1D op #25151
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,79 @@ | ||||||
| #include "col2im_1d.cuh" | ||||||
|
|
||||||
|
|
||||||
| template <typename T> | ||||||
| static __global__ void col2im_1d_kernel( | ||||||
| const T * src, T * dst, | ||||||
| int64_t T_out, int64_t T_in, int64_t K, int64_t OC, int64_t K_OC, | ||||||
| int s0, int p0) { | ||||||
|
|
||||||
| const int64_t i = (int64_t)threadIdx.x + blockIdx.x * blockDim.x; | ||||||
| if (i >= T_out * OC) { | ||||||
| return; // Guard out-of-bounds threads | ||||||
| } | ||||||
|
|
||||||
| // Decompose 1D thread ID into 2D output coordinates | ||||||
| // dst layout: [T_out, OC] -> flat index = oc * T_out + t_out | ||||||
| const int64_t oc = i / T_out; | ||||||
| const int64_t t_out = i % T_out; | ||||||
|
Comment on lines
+17
to
+18
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure how performance critical this is but you can use
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes I found it. I digged deeper inside the ggml/src/ggml-cuda/common.cuh. I can implement it new faster but it does not mean it is a good idea. here is my analysis. The fast_div_modulo(it calls fastdiv inside of it) speeds up the kernel by avoiding expensive hardware division, but it requires casting thread IDs to 32-bit, Given our 1D tensor use cases, is this 32-bit ceiling a safe tradeoff for the performance boost, or should I stick to standard 64-bit division?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay not required for this PR anyway |
||||||
|
|
||||||
| const int64_t t_abs = t_out + p0; | ||||||
|
|
||||||
| // Establish bounds using the solved equation | ||||||
| int64_t t_in_min = (t_abs - K + 1 + s0 - 1) / s0; | ||||||
| if (t_in_min < 0) t_in_min = 0; | ||||||
|
|
||||||
| float sum = 0.0f; // Accumulate in fp32 | ||||||
|
|
||||||
|
|
||||||
| for (int64_t t_in = t_in_min; t_in * s0 <= t_abs && t_in < T_in; t_in++) { | ||||||
| int64_t k = t_abs - t_in * s0; | ||||||
|
Ssamdeman marked this conversation as resolved.
|
||||||
|
|
||||||
| // src layout: [K_OC, T_in] -> element (oc * K + k) at column t_in | ||||||
| // flat offset = t_in * K_OC + (oc * K + k) | ||||||
| sum += (float)src[t_in * K_OC + (oc * K + k)]; | ||||||
| } | ||||||
|
|
||||||
| // Write directly to current thread's mapped location | ||||||
| dst[i] = (T)sum; | ||||||
| } | ||||||
|
|
||||||
|
|
||||||
| // 2. Host function wrapper | ||||||
| void ggml_cuda_op_col2im_1d(ggml_backend_cuda_context & ctx, ggml_tensor * dst) { | ||||||
| const ggml_tensor * src = dst->src[0]; | ||||||
| cudaStream_t stream = ctx.stream(); | ||||||
|
|
||||||
| // Strict type pairing and format enforcement | ||||||
| GGML_ASSERT(src->type == dst->type); | ||||||
| GGML_ASSERT(src->type == GGML_TYPE_F32 || src->type == GGML_TYPE_F16 || src->type == GGML_TYPE_BF16); | ||||||
|
|
||||||
| // Extract structural parameters | ||||||
| const int32_t s0 = ((const int32_t *)(dst->op_params))[0]; | ||||||
| const int32_t OC = ((const int32_t *)(dst->op_params))[1]; | ||||||
| const int32_t p0 = ((const int32_t *)(dst->op_params))[2]; | ||||||
|
|
||||||
| const int64_t K_OC = src->ne[0]; | ||||||
| const int64_t T_in = src->ne[1]; | ||||||
| const int64_t K = K_OC / OC; | ||||||
| const int64_t T_out = dst->ne[0]; | ||||||
|
|
||||||
| // Grid configuration | ||||||
| const int64_t total_elements = T_out * OC; | ||||||
| const int block_size = 256; | ||||||
| const int num_blocks = (total_elements + block_size - 1) / block_size; | ||||||
|
|
||||||
| // Type dispatching | ||||||
| if (src->type == GGML_TYPE_F32) { | ||||||
| col2im_1d_kernel<float><<<num_blocks, block_size, 0, stream>>>( | ||||||
| (const float *)src->data, (float *)dst->data, T_out, T_in, K, OC, K_OC, s0, p0); | ||||||
| } else if (src->type == GGML_TYPE_F16) { | ||||||
| col2im_1d_kernel<half><<<num_blocks, block_size, 0, stream >>>( | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| (const half *)src->data, (half *)dst->data, T_out, T_in, K, OC, K_OC, s0, p0); | ||||||
| } else if (src->type == GGML_TYPE_BF16) { | ||||||
| col2im_1d_kernel<nv_bfloat16><<<num_blocks, block_size, 0, stream>>>( | ||||||
| (const nv_bfloat16 *)src->data, (nv_bfloat16 *)dst->data, T_out, T_in, K, OC, K_OC, s0, p0); | ||||||
| } else { | ||||||
| GGML_ABORT("col2im_1d: unsupported type %d", src->type); | ||||||
| } | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| #include "common.cuh" | ||
|
|
||
| void ggml_cuda_op_col2im_1d(ggml_backend_cuda_context & ctx, ggml_tensor * dst); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.