TensorTonic
Problems
L1 Normalization as a CUDA Kernel
Linear AlgebraGPU Programming
Medium

Implement L1 normalization of a 1D vector on the GPU. For each element of the input array, compute:

output[i]=input[i]∑j=0N−1∣input[j]∣\text{output}[i] = \frac{\text{input}[i]}{\sum_{j=0}^{N-1} |\text{input}[j]|}output[i]=∑j=0N−1​∣input[j]∣input[i]​

The kernel must first perform a reduction over ∣input∣|\text{input}|∣input∣ to compute the denominator, then divide each element by that sum. The output array has the same length as the input.

Function Arguments

  • input\texttt{input}input: device pointer to NNN float values.
  • output\texttt{output}output: device pointer to NNN float slots that receive the L1-normalized values.
  • N\texttt{N}N: number of elements in input\texttt{input}input and output\texttt{output}output.
Loading visualization...

Examples

Input: input = [1, 2, 3, 4]

Output: [0.1, 0.2, 0.3, 0.4]

The sum of absolute values is 101010, so each element is divided by 101010.

Input: input = [-1, 2, -3]

Output: [-0.1667, 0.3333, -0.5]

The sum of absolute values is 666, so each element is divided by 666 while keeping its sign.

Hint 1

Compute the denominator in a separate reduction kernel before the divide pass. A shared-memory tree reduction followed by atomicAdd into a single device float is a clean pattern.

Hint 2

fabsf gives the per-element absolute value. Zero the scratch sum with cudaMemset before launching the reduction so the atomics accumulate from a clean baseline.

Hint 3

Once the sum is on the device, a second elementwise kernel can read the scratch scalar and write input[i] / sum into output[i].

Requirements

  • Export extern "C" void solve(const float* input, float* output, int N)\texttt{extern "C" void solve(const float* input, float* output, int N)}extern "C" void solve(const float* input, float* output, int N) with the exact signature.
  • Treat input\texttt{input}input and output\texttt{output}output as device pointers; do not cudaMemcpy\texttt{cudaMemcpy}cudaMemcpy them.
  • Compute the sum of absolute values across the entire array, then divide each element by that scalar.
  • Call cudaDeviceSynchronize\texttt{cudaDeviceSynchronize}cudaDeviceSynchronize before solve\texttt{solve}solve returns and free any scratch device memory you allocate.

Constraints

  • 1≤N≤1071 \le N \le 10^71≤N≤107.
  • All values fit in 32-bit float.
  • The sum ∑j∣input[j]∣\sum_j |\text{input}[j]|∑j​∣input[j]∣ is guaranteed to be strictly positive (no all-zero inputs).
  • The solve\texttt{solve}solve signature must not change.
Try Similar Problems
CUDA Dot Product: Multi-Block ReductionMediumL2 Normalization as a CUDA KernelMediumRMS Normalization as a CUDA KernelMediumLayer Normalization as a CUDA KernelMediumMatrix Multiplication as a CUDA KernelMediumCosine Similarity as a CUDA KernelMediumMatrix-Vector Multiplication as a CUDA KernelMediumArgmax as a CUDA KernelMediumMean and Variance as a CUDA KernelMediumArgmin as a CUDA KernelMediumOuter Product as a CUDA KernelEasyTiled Matrix Multiplication as a CUDA KernelHard

Accepts: array

You must run your code first.

Kernel performance

Submit a correct solution to see your kernel performance.

L1 Normalization as a CUDA Kernel

L1 Normalization as a CUDA Kernel

Linear AlgebraGPU Programming
Medium

Implement L1 normalization of a 1D vector on the GPU. For each element of the input array, compute:

output[i]=input[i]∑j=0N−1∣input[j]∣\text{output}[i] = \frac{\text{input}[i]}{\sum_{j=0}^{N-1} |\text{input}[j]|}output[i]=∑j=0N−1​∣input[j]∣input[i]​

The kernel must first perform a reduction over ∣input∣|\text{input}|∣input∣ to compute the denominator, then divide each element by that sum. The output array has the same length as the input.

Function Arguments

  • input\texttt{input}input: device pointer to NNN float values.
  • output\texttt{output}output: device pointer to NNN float slots that receive the L1-normalized values.
  • N\texttt{N}N: number of elements in input\texttt{input}input and output\texttt{output}output.
Loading visualization...

Examples

Input: input = [1, 2, 3, 4]

Output: [0.1, 0.2, 0.3, 0.4]

The sum of absolute values is 101010, so each element is divided by 101010.

Input: input = [-1, 2, -3]

Output: [-0.1667, 0.3333, -0.5]

The sum of absolute values is 666, so each element is divided by 666 while keeping its sign.

Hint 1

Compute the denominator in a separate reduction kernel before the divide pass. A shared-memory tree reduction followed by atomicAdd into a single device float is a clean pattern.

Hint 2

fabsf gives the per-element absolute value. Zero the scratch sum with cudaMemset before launching the reduction so the atomics accumulate from a clean baseline.

Hint 3

Once the sum is on the device, a second elementwise kernel can read the scratch scalar and write input[i] / sum into output[i].

Requirements

  • Export extern "C" void solve(const float* input, float* output, int N)\texttt{extern "C" void solve(const float* input, float* output, int N)}extern "C" void solve(const float* input, float* output, int N) with the exact signature.
  • Treat input\texttt{input}input and output\texttt{output}output as device pointers; do not cudaMemcpy\texttt{cudaMemcpy}cudaMemcpy them.
  • Compute the sum of absolute values across the entire array, then divide each element by that scalar.
  • Call cudaDeviceSynchronize\texttt{cudaDeviceSynchronize}cudaDeviceSynchronize before solve\texttt{solve}solve returns and free any scratch device memory you allocate.

Constraints

  • 1≤N≤1071 \le N \le 10^71≤N≤107.
  • All values fit in 32-bit float.
  • The sum ∑j∣input[j]∣\sum_j |\text{input}[j]|∑j​∣input[j]∣ is guaranteed to be strictly positive (no all-zero inputs).
  • The solve\texttt{solve}solve signature must not change.
Try Similar Problems
CUDA Dot Product: Multi-Block ReductionMediumL2 Normalization as a CUDA KernelMediumRMS Normalization as a CUDA KernelMediumLayer Normalization as a CUDA KernelMediumMatrix Multiplication as a CUDA KernelMediumCosine Similarity as a CUDA KernelMediumMatrix-Vector Multiplication as a CUDA KernelMediumArgmax as a CUDA KernelMediumMean and Variance as a CUDA KernelMediumArgmin as a CUDA KernelMediumOuter Product as a CUDA KernelEasyTiled Matrix Multiplication as a CUDA KernelHard

Accepts: array

You must run your code first.

Kernel performance

Submit a correct solution to see your kernel performance.

Problems
Loading...
1 / 1