#ifndef CUDART_VERSION #error CUDART_VERSION Undefined! #elif (CUDART_VERSION >= 11000) #include #else #include "3rdparty/cub/cub.cuh" #endif #include "src/turbomind/kernels/sampling_kernels.h" #include "src/turbomind/kernels/sampling_topp_kernels.h" #include "src/turbomind/utils/constant.h" namespace turbomind { template __global__ void sampling(const T* logits, const int stride, const int* indices, const int* kept, curandState_t* curandstate, int* output_ids, int* sequence_length, T* sampled_logprobs, int* sampled_indexes, int* sampled_nums) { int tid = threadIdx.x; int batch_id = blockIdx.x; int n = kept[batch_id]; logits += stride * batch_id; indices += stride * batch_id; __shared__ float rand_num_s; __shared__ int selected; if (tid == 0) { rand_num_s = curand_uniform(curandstate + batch_id); } __syncthreads(); typedef cub::BlockScan BlockScan; __shared__ typename BlockScan::TempStorage temp_storage; float local_rand = rand_num_s; float prefix_sum = 0.f; BlockPrefixCallbackOp prefix_op{0}; int end = (n + BLOCK_SIZE - 1) / BLOCK_SIZE * BLOCK_SIZE; for (int i = tid; i < end; i += BLOCK_SIZE) { float thread_logit = (i < n) ? static_cast(logits[i]) : 0.f; BlockScan(temp_storage).InclusiveSum(thread_logit, prefix_sum, prefix_op); auto count = __syncthreads_count(prefix_sum > local_rand); if (count != 0 || (i + BLOCK_SIZE) >= end) { if (tid == min(BLOCK_SIZE - count, BLOCK_SIZE - 1)) { selected = min(i, n - 1); output_ids[batch_id] = indices[selected]; } break; } } if (tid == 0) { sequence_length[batch_id] += 1; } if (sampled_logprobs != nullptr && sampled_indexes != nullptr && sampled_nums != nullptr) { __syncthreads(); sampled_logprobs += batch_id * kMaxLogProb; sampled_indexes += batch_id * kMaxLogProb; int end = min(n, kMaxLogProb); for (int i = tid; i < end; i += BLOCK_SIZE) { sampled_logprobs[i] = logf(logits[i]); sampled_indexes[i] = indices[i]; } if (n > kMaxLogProb && selected >= kMaxLogProb) { if ((kMaxLogProb - 1 + BLOCK_SIZE - tid) % BLOCK_SIZE == 0) { sampled_logprobs[kMaxLogProb - 1] = logf(logits[selected]); sampled_indexes[kMaxLogProb - 1] = indices[selected]; } } sampled_nums[batch_id] = min(n, kMaxLogProb); } } template void invokeSampling(SamplingParams& params, cudaStream_t stream) { const int grid = params.batch_size; const int block = 256; sampling<<>>((T*)params.logits, params.stride, params.indices, params.kept, params.curandstate, params.output_ids, params.sequence_length, (T*)params.sampled_logprobs, params.sampled_indexes, params.sampled_nums); } template void invokeSampling(SamplingParams& params, cudaStream_t stream); } // namespace turbomind