Implement stable row-wise softmax in CUDA using online summaries. A summary contains the maximum m and the shifted exponential sum ℓ of its values:
ℓ=j∑exj−m.Here, j indexes values and xj is one value. For another block with summary mb,ℓb, the combined summary is:
mnew=max(m,mb). ℓnew=em−mnewℓ+emb−mnewℓb.Here, subscript b denotes the other block and subscript new denotes their union. Once m and ℓ summarize the complete row, its normalized output at column j is:
yj=ℓexj−m.Complete the empty CUDA kernel; the supplied solve launcher is already implemented. Input and output are preallocated matrices with the supplied dimensions and element strides. The kernel returns no value and writes the probabilities into output, preserving the input shape and storage dtype.
Input: input = [[1, 2, 3], [-1, 0, 1]], dtype = float32, block_size = 64
Output: [[0.090031, 0.244728, 0.665241], [0.090031, 0.244728, 0.665241]]
Explanation: The rows differ by a constant shift, so they have the same probabilities.
Input: input = [[1000, 1001, 1002, 999]], dtype = float32, block_size = 128
Output: [[0.087144, 0.236883, 0.643914, 0.032059]]
Input: input = [[-3, 2, 0.5, 4, -1]], dtype = float16, block_size = 32
Output: [[0.000777, 0.115356, 0.025742, 0.852539, 0.005745]]
expf evaluates the exponential in float32.
__syncthreads coordinates access to shared-memory summaries.
__half2float and __bfloat162float convert low-precision input values.
Accepts: array
Accepts: string
Accepts: number
Submit a correct solution to see your kernel performance.
Implement stable row-wise softmax in CUDA using online summaries. A summary contains the maximum m and the shifted exponential sum ℓ of its values:
ℓ=j∑exj−m.Here, j indexes values and xj is one value. For another block with summary mb,ℓb, the combined summary is:
mnew=max(m,mb). ℓnew=em−mnewℓ+emb−mnewℓb.Here, subscript b denotes the other block and subscript new denotes their union. Once m and ℓ summarize the complete row, its normalized output at column j is:
yj=ℓexj−m.Complete the empty CUDA kernel; the supplied solve launcher is already implemented. Input and output are preallocated matrices with the supplied dimensions and element strides. The kernel returns no value and writes the probabilities into output, preserving the input shape and storage dtype.
Input: input = [[1, 2, 3], [-1, 0, 1]], dtype = float32, block_size = 64
Output: [[0.090031, 0.244728, 0.665241], [0.090031, 0.244728, 0.665241]]
Explanation: The rows differ by a constant shift, so they have the same probabilities.
Input: input = [[1000, 1001, 1002, 999]], dtype = float32, block_size = 128
Output: [[0.087144, 0.236883, 0.643914, 0.032059]]
Input: input = [[-3, 2, 0.5, 4, -1]], dtype = float16, block_size = 32
Output: [[0.000777, 0.115356, 0.025742, 0.852539, 0.005745]]
expf evaluates the exponential in float32.
__syncthreads coordinates access to shared-memory summaries.
__half2float and __bfloat162float convert low-precision input values.
Accepts: array
Accepts: string
Accepts: number
Submit a correct solution to see your kernel performance.