CharlesCNorton commited on
Commit ·
335d7ff
1
Parent(s): 1e410e6
spec-decode-ops: grid-stride cast_kernel rows so M may exceed the 65535 gridDim.y cap
Browse files
spec_decode_cuda/spec_decode_ops.cu
CHANGED
|
@@ -94,10 +94,19 @@ __device__ void block_argmax(float v, int64_t idx, float* out_v, int64_t* out_i)
|
|
| 94 |
template <typename T>
|
| 95 |
__global__ void cast_kernel(const T* __restrict__ logits, int64_t M, int64_t V,
|
| 96 |
float* __restrict__ out) {
|
| 97 |
-
|
| 98 |
-
for (int64_t
|
| 99 |
-
|
| 100 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
}
|
| 102 |
}
|
| 103 |
|
|
@@ -133,7 +142,27 @@ __global__ void sorted_sample_kernel(const float* __restrict__ sorted_logits,
|
|
| 133 |
const float* sl = sorted_logits + row * V;
|
| 134 |
const int* si = sorted_idx + row * V;
|
| 135 |
const float lmax = sl[0] * inv_temp;
|
| 136 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
|
| 138 |
// Z over the top_k prefix (post-temperature).
|
| 139 |
float part = 0.f;
|
|
@@ -197,9 +226,12 @@ __global__ void sorted_sample_kernel(const float* __restrict__ sorted_logits,
|
|
| 197 |
__syncthreads();
|
| 198 |
|
| 199 |
if (write_mask) {
|
|
|
|
|
|
|
|
|
|
| 200 |
float* mo = masked_out + row * V;
|
| 201 |
for (int64_t i = threadIdx.x; i < V; i += blockDim.x) {
|
| 202 |
-
mo[si[i]] = (i < L) ? sl[i] * inv_temp :
|
| 203 |
}
|
| 204 |
return;
|
| 205 |
}
|
|
@@ -498,7 +530,7 @@ void run_sample(const torch::Tensor& logits, const c10::optional<torch::Tensor>&
|
|
| 498 |
TORCH_CHECK(M * V < INT32_MAX, "M * V must fit in int32 for the segmented sort");
|
| 499 |
auto work = torch::empty({M, V}, opts_f);
|
| 500 |
{
|
| 501 |
-
dim3 grid((unsigned)grid_x_for(V), (unsigned)M);
|
| 502 |
cast_kernel<T><<<grid, kThreads, 0, stream>>>(tptr<T>(logits), M, V, work.data_ptr<float>());
|
| 503 |
if (prev.has_value() && rep != 1.0) {
|
| 504 |
penalty_kernel<<<M, kThreads, 0, stream>>>(work.data_ptr<float>(), V,
|
|
@@ -509,7 +541,8 @@ void run_sample(const torch::Tensor& logits, const c10::optional<torch::Tensor>&
|
|
| 509 |
|
| 510 |
// segmented descending sort with indices
|
| 511 |
auto sorted = torch::empty({M, V}, opts_f);
|
| 512 |
-
auto idx_in = torch::
|
|
|
|
| 513 |
auto idx_out = torch::empty({M, V}, logits.options().dtype(torch::kInt32));
|
| 514 |
auto offs = torch::arange(0, (M + 1) * V, V, logits.options().dtype(torch::kInt32)).contiguous();
|
| 515 |
size_t temp_bytes = 0;
|
|
|
|
| 94 |
template <typename T>
|
| 95 |
__global__ void cast_kernel(const T* __restrict__ logits, int64_t M, int64_t V,
|
| 96 |
float* __restrict__ out) {
|
| 97 |
+
// grid-stride over rows so M may exceed the 65535 gridDim.y hardware cap.
|
| 98 |
+
for (int64_t row = blockIdx.y; row < M; row += gridDim.y) {
|
| 99 |
+
for (int64_t v = blockIdx.x * (int64_t)blockDim.x + threadIdx.x; v < V;
|
| 100 |
+
v += (int64_t)gridDim.x * blockDim.x) {
|
| 101 |
+
out[row * V + v] = ldf(logits, row * V + v);
|
| 102 |
+
}
|
| 103 |
+
}
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
__global__ void iota_kernel(int* __restrict__ out, int64_t M, int64_t V) {
|
| 107 |
+
for (int64_t i = blockIdx.x * (int64_t)blockDim.x + threadIdx.x; i < M * V;
|
| 108 |
+
i += (int64_t)gridDim.x * blockDim.x) {
|
| 109 |
+
out[i] = (int)(i % V);
|
| 110 |
}
|
| 111 |
}
|
| 112 |
|
|
|
|
| 142 |
const float* sl = sorted_logits + row * V;
|
| 143 |
const int* si = sorted_idx + row * V;
|
| 144 |
const float lmax = sl[0] * inv_temp;
|
| 145 |
+
|
| 146 |
+
// top-k with tie inclusion: transformers removes only values strictly
|
| 147 |
+
// below the k-th, so equal-valued tokens past position k stay kept.
|
| 148 |
+
int64_t kk = V;
|
| 149 |
+
if (top_k > 0 && top_k < V) {
|
| 150 |
+
const float kth = sl[top_k - 1];
|
| 151 |
+
__shared__ int64_t s_kk;
|
| 152 |
+
if (threadIdx.x == 0) s_kk = V;
|
| 153 |
+
__syncthreads();
|
| 154 |
+
const int64_t start = (top_k / kThreads) * kThreads;
|
| 155 |
+
for (int64_t base = start; base < V; base += blockDim.x) {
|
| 156 |
+
const int64_t i = base + threadIdx.x;
|
| 157 |
+
if (i >= top_k && i < V && sl[i] < kth) {
|
| 158 |
+
atomicMin((unsigned long long*)&s_kk, (unsigned long long)i);
|
| 159 |
+
}
|
| 160 |
+
__syncthreads();
|
| 161 |
+
if (s_kk < base + (int64_t)kThreads) break;
|
| 162 |
+
}
|
| 163 |
+
kk = s_kk;
|
| 164 |
+
__syncthreads();
|
| 165 |
+
}
|
| 166 |
|
| 167 |
// Z over the top_k prefix (post-temperature).
|
| 168 |
float part = 0.f;
|
|
|
|
| 226 |
__syncthreads();
|
| 227 |
|
| 228 |
if (write_mask) {
|
| 229 |
+
// masked entries carry true -inf, matching the transformers chain's
|
| 230 |
+
// filter_value; -FLT_MAX would evaluate identically under softmax but
|
| 231 |
+
// fails isinf-based consumers.
|
| 232 |
float* mo = masked_out + row * V;
|
| 233 |
for (int64_t i = threadIdx.x; i < V; i += blockDim.x) {
|
| 234 |
+
mo[si[i]] = (i < L) ? sl[i] * inv_temp : -INFINITY;
|
| 235 |
}
|
| 236 |
return;
|
| 237 |
}
|
|
|
|
| 530 |
TORCH_CHECK(M * V < INT32_MAX, "M * V must fit in int32 for the segmented sort");
|
| 531 |
auto work = torch::empty({M, V}, opts_f);
|
| 532 |
{
|
| 533 |
+
dim3 grid((unsigned)grid_x_for(V), (unsigned)std::min<int64_t>(M, 65535));
|
| 534 |
cast_kernel<T><<<grid, kThreads, 0, stream>>>(tptr<T>(logits), M, V, work.data_ptr<float>());
|
| 535 |
if (prev.has_value() && rep != 1.0) {
|
| 536 |
penalty_kernel<<<M, kThreads, 0, stream>>>(work.data_ptr<float>(), V,
|
|
|
|
| 541 |
|
| 542 |
// segmented descending sort with indices
|
| 543 |
auto sorted = torch::empty({M, V}, opts_f);
|
| 544 |
+
auto idx_in = torch::empty({M, V}, logits.options().dtype(torch::kInt32));
|
| 545 |
+
iota_kernel<<<grid_x_for(M * V), kThreads, 0, stream>>>(idx_in.data_ptr<int>(), M, V);
|
| 546 |
auto idx_out = torch::empty({M, V}, logits.options().dtype(torch::kInt32));
|
| 547 |
auto offs = torch::arange(0, (M + 1) * V, V, logits.options().dtype(torch::kInt32)).contiguous();
|
| 548 |
size_t temp_bytes = 0;
|