Implement L2 normalization of a 1-D vector of 32-bit floats. For each element of the input array, compute:
output[i]=∑j=0N−1input[j]2input[i]The kernel must first reduce the squared values into a single scalar, then take the square root before dividing every element by that scalar. A single embarrassingly-parallel kernel cannot compute this because the denominator depends on every element.
The output array has the same length as the input.
Input: input = [3.0, 4.0]
Output: [0.6, 0.8]
The L2 norm is 9+16=5, so each element is divided by 5.
Input: input = [-1.0, 2.0, -2.0]
Output: [-0.3333, 0.6667, -0.6667]
The L2 norm is 1+4+4=3.
You need one whole-array reduction: the sum of squares. A single thread cannot see all elements, so use a shared-memory tree reduction across one block with a grid-stride loop.
Two kernels is the cleanest split: one writes the scalar ∑jinput[j]2 to a single-float scratch buffer, the second reads that scratch, computes ⋅ once per thread, and divides input[i] by it into output[i].
Use cudaMalloc inside solve for the scratch float, call cudaDeviceSynchronize before cudaFree, and remember rsqrtf as a fast alternative to 1/sqrtf.
Accepts: array
Submit a correct solution to see your kernel performance.
Implement L2 normalization of a 1-D vector of 32-bit floats. For each element of the input array, compute:
output[i]=∑j=0N−1input[j]2input[i]The kernel must first reduce the squared values into a single scalar, then take the square root before dividing every element by that scalar. A single embarrassingly-parallel kernel cannot compute this because the denominator depends on every element.
The output array has the same length as the input.
Input: input = [3.0, 4.0]
Output: [0.6, 0.8]
The L2 norm is 9+16=5, so each element is divided by 5.
Input: input = [-1.0, 2.0, -2.0]
Output: [-0.3333, 0.6667, -0.6667]
The L2 norm is 1+4+4=3.
You need one whole-array reduction: the sum of squares. A single thread cannot see all elements, so use a shared-memory tree reduction across one block with a grid-stride loop.
Two kernels is the cleanest split: one writes the scalar ∑jinput[j]2 to a single-float scratch buffer, the second reads that scratch, computes ⋅ once per thread, and divides input[i] by it into output[i].
Use cudaMalloc inside solve for the scratch float, call cudaDeviceSynchronize before cudaFree, and remember rsqrtf as a fast alternative to 1/sqrtf.
Accepts: array
Submit a correct solution to see your kernel performance.