Download kernels/rope.cu from Snapkitty/hilbert: direct link, hf CLI and curl.
- Browser
- Download file 2.8 kB
-
https://huggingface.co/Snapkitty/hilbert/resolve/main/kernels/rope.cu
- Command line
-
hf download hf://Snapkitty/hilbert/kernels/rope.cu
-
curl -L -o rope.cu https://huggingface.co/Snapkitty/hilbert/resolve/main/kernels/rope.cu
2.8 kB
| // Hilbert — Rotary Position Embedding (RoPE) Kernel | |
| // Applies rotary encoding in-place on Q and K tensors | |
| // Supports partial rotation (rope_dim <= head_dim) | |
| #include <cuda_fp16.h> | |
| #include <cuda_bf16.h> | |
| #include <math.h> | |
| __global__ void hilbert_rope_kernel( | |
| half* __restrict__ q, // [batch, seq_len, n_heads, d_head] | |
| half* __restrict__ k, // [batch, seq_len, n_kv_heads, d_head] | |
| const int seq_len, | |
| const int n_heads, | |
| const int n_kv_heads, | |
| const int d_head, | |
| const int rope_dim, // Number of dimensions to rotate (<= d_head) | |
| const float theta_base, | |
| const int start_pos // For KV-cache continuation | |
| ) { | |
| const int tid = blockIdx.x * blockDim.x + threadIdx.x; | |
| const int batch_idx = blockIdx.z; | |
| const int seq_idx = blockIdx.y; | |
| const int pos = start_pos + seq_idx; | |
| // Each thread handles one (head, dim_pair) for Q or K | |
| const int total_pairs = n_heads * (rope_dim / 2); | |
| if (tid >= total_pairs) return; | |
| const int head_idx = tid / (rope_dim / 2); | |
| const int pair_idx = tid % (rope_dim / 2); | |
| const int d0 = pair_idx * 2; | |
| const int d1 = d0 + 1; | |
| // Compute rotation angle: theta_i = pos * theta_base^(-2i/rope_dim) | |
| float freq = 1.0f / powf(theta_base, (float)(2 * pair_idx) / (float)rope_dim); | |
| float angle = (float)pos * freq; | |
| float cos_val = cosf(angle); | |
| float sin_val = sinf(angle); | |
| // Rotate Q | |
| { | |
| int offset = ((batch_idx * seq_len + seq_idx) * n_heads + head_idx) * d_head; | |
| float q0 = __half2float(q[offset + d0]); | |
| float q1 = __half2float(q[offset + d1]); | |
| q[offset + d0] = __float2half_rn(q0 * cos_val - q1 * sin_val); | |
| q[offset + d1] = __float2half_rn(q0 * sin_val + q1 * cos_val); | |
| } | |
| // Rotate K (only if this head maps to a KV head) | |
| if (head_idx < n_kv_heads) { | |
| int kv_pair_idx = pair_idx; | |
| int offset = ((batch_idx * seq_len + seq_idx) * n_kv_heads + head_idx) * d_head; | |
| float k0 = __half2float(k[offset + d0]); | |
| float k1 = __half2float(k[offset + d1]); | |
| k[offset + d0] = __float2half_rn(k0 * cos_val - k1 * sin_val); | |
| k[offset + d1] = __float2half_rn(k0 * sin_val + k1 * cos_val); | |
| } | |
| } | |
| void hilbert_rope_launch( | |
| half* q, | |
| half* k, | |
| int batch_size, | |
| int seq_len, | |
| int n_heads, | |
| int n_kv_heads, | |
| int d_head, | |
| int rope_dim, | |
| float theta_base, | |
| int start_pos, | |
| cudaStream_t stream | |
| ) { | |
| int pairs_per_seq = n_heads * (rope_dim / 2); | |
| int threads = 256; | |
| int blocks_x = (pairs_per_seq + threads - 1) / threads; | |
| dim3 grid(blocks_x, seq_len, batch_size); | |
| dim3 block(threads); | |
| hilbert_rope_kernel<<<grid, block, 0, stream>>>( | |
| q, k, seq_len, n_heads, n_kv_heads, d_head, | |
| rope_dim, theta_base, start_pos | |
| ); | |
| } | |