voidsoftmax_cpu(float *h_out, float *h_data, int B, int T, int C) { for (int i = 0; i < B * T; ++i) { float *inp = h_data + i * C; float *out = h_out + i * C;
float sum = 0.0f; for (int j = 0; j < C; ++j) { sum += expf(inp[j] - maxval); } for (int j = 0; j < C; ++j) { out[j] = expf(inp[j] - maxval) / sum; } } }
版本V0一个线程处理一行
假设B表示Batch size,T表示序列长度,C表示通道数,我们要处理的维度是在C这个维度,如果是一个线程处理一行,那么我们总共需要B*T个线程,也就是说block_size为BLOCK_SIZE时,grid_size为(B * T + BLOCK_SIZE - 1) / BLOCK_SIZE。
__global__ voidsoftmax_gpu(float *d_out, float *d_data, int N, int C) { int tid = threadIdx.x + blockDim.x * blockIdx.x; int row = tid; if (row >= N) { return; }
float maxval = -INFINITY; for (int i = 0; i < C; ++i) { if (inp[i] > maxval) { maxval = inp[i]; } }
float sum = 0.0f; for (int i = 0; i < C; ++i) { sum += expf(inp[i] - maxval); } for (int i = 0; i < C; ++i) { out[i] = expf(inp[i] - maxval) / sum; } }
__global__ voidonline_softmax(float *d_out, float *d_data, int N, int C) { int tid = threadIdx.x + blockDim.x * blockIdx.x; int row = tid; if (row >= N) { return; } float *inp = d_data + row * C; float *out = d_out + row * C;
float sum = 0.0f; float maxval = -INFINITY; for (int i = 0; i < C; ++i) { float val = inp[i]; if (inp[i] > maxval) { sum *= expf(maxval - val); maxval = val; } sum += expf(val - maxval); }
float r = 1 / sum; for (int i = 0; i < C; ++i) { out[i] = expf(inp[i] - maxval) * r; } }
版本V2 一个Warp处理一行
#define BLOCK_SIZE 32
__global__ voidsoftmax_gpu(float *d_out, float *d_data, int N, int C) { int tid = threadIdx.x + blockDim.x * blockIdx.x; int row_id = tid / blockDim.x; int lane_id = tid % blockDim.x; if (row_id >= N) { return; }
float maxval = -INFINITY; float sum = 0.0f; for (int i = lane_id; i < C; i += BLOCK_SIZE) { float val = inp[i]; if (val > maxval) { sum *= expf(maxval - val); maxval = val; } sum += expf(val - maxval); }