TensorTonic
Problems
Mean and Variance as a CUDA Kernel
Probability and StatisticsGPU Programming
Medium

Compute the population mean and population variance of a 1D float array on the GPU. Write two scalar results to two separate 1-element device buffers.

μ=1N∑i=0N−1input[i]\mu = \frac{1}{N} \sum_{i=0}^{N-1} \text{input}[i]μ=N1​i=0∑N−1​input[i] σ2=1N∑i=0N−1(input[i]−μ)2\sigma^2 = \frac{1}{N} \sum_{i=0}^{N-1} (\text{input}[i] - \mu)^2σ2=N1​i=0∑N−1​(input[i]−μ)2

The divisor is NNN (population, biased variance), not N−1N-1N−1. The buffers mean_out\texttt{mean\_out}mean_out and var_out\texttt{var\_out}var_out are device pointers to single floats; solve\texttt{solve}solve writes the mean to mean_out[0]\texttt{mean\_out}[0]mean_out[0] and the variance to var_out[0]\texttt{var\_out}[0]var_out[0]. Both reductions run on the GPU; no host-side accumulation.

Loading visualization...

Examples

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

Output: mean = 3.0, variance = 2.0

Mean is (1+2+3+4+5)/5=3(1+2+3+4+5)/5 = 3(1+2+3+4+5)/5=3. Squared deviations are 4,1,0,1,44, 1, 0, 1, 44,1,0,1,4; their mean is 10/5=210/5 = 210/5=2.

Input: input = [2, 2, 2, 2], N = 4

Output: mean = 2.0, variance = 0.0

A constant array has zero variance.

Hint 1

You can compute both reductions in one pass by accumulating ∑xi\sum x_i∑xi​ and ∑xi2\sum x_i^2∑xi2​ together, then using Var(X)=E[X2]−E[X]2\text{Var}(X) = E[X^2] - E[X]^2Var(X)=E[X2]−E[X]2.

Hint 2

Block-local shared-memory reductions followed by one atomicAdd per block to the global sum and sum-of-squares keep atomic traffic at O(N/256)O(N/256)O(N/256).

Hint 3

After the reduction kernel finishes, a tiny single-thread finalize kernel can divide by NNN to write mean_out\texttt{mean\_out}mean_out and var_out\texttt{var\_out}var_out.

Requirements

  • Implement solve(const float* input, float* mean_out, float* var_out, int N)\texttt{solve(const float* input, float* mean\_out, float* var\_out, int N)}solve(const float* input, float* mean_out, float* var_out, int N) with extern "C"\texttt{extern "C"}extern "C" linkage.
  • Write the population mean to mean_out[0]\texttt{mean\_out}[0]mean_out[0] and the population variance (divisor NNN) to var_out[0]\texttt{var\_out}[0]var_out[0].
  • All accumulation happens on device; do not copy input\texttt{input}input to host.
  • Call cudaDeviceSynchronize\texttt{cudaDeviceSynchronize}cudaDeviceSynchronize before solve\texttt{solve}solve returns so both outputs are visible to the caller.

Constraints

  • 1≤N≤5⋅1061 \le N \le 5 \cdot 10^61≤N≤5⋅106.
  • Each input[i]\texttt{input}[i]input[i] fits in a 32-bit float.
  • input\texttt{input}input, mean_out\texttt{mean\_out}mean_out, var_out\texttt{var\_out}var_out are device pointers owned by the harness; do not cudaMalloc\texttt{cudaMalloc}cudaMalloc or cudaMemcpy\texttt{cudaMemcpy}cudaMemcpy them inside solve\texttt{solve}solve.
  • The solve\texttt{solve}solve signature must not change.
Try Similar Problems
Argmax as a CUDA KernelMediumL1 Normalization as a CUDA KernelMediumCUDA Dot Product: Multi-Block ReductionMediumL2 Normalization as a CUDA KernelMediumArgmin as a CUDA KernelMediumSingle-Pass Mean and Variance in TritonMediumMin of Array as a CUDA KernelEasySum of Array as a CUDA KernelEasyMax of Array as a CUDA KernelEasyRMS Normalization as a CUDA KernelMediumLayer Normalization as a CUDA KernelMediumSoftmax as a CUDA KernelMedium

Accepts: array

You must run your code first.

Kernel performance

Submit a correct solution to see your kernel performance.

Mean and Variance as a CUDA Kernel

Mean and Variance as a CUDA Kernel

Probability and StatisticsGPU Programming
Medium

Compute the population mean and population variance of a 1D float array on the GPU. Write two scalar results to two separate 1-element device buffers.

μ=1N∑i=0N−1input[i]\mu = \frac{1}{N} \sum_{i=0}^{N-1} \text{input}[i]μ=N1​i=0∑N−1​input[i] σ2=1N∑i=0N−1(input[i]−μ)2\sigma^2 = \frac{1}{N} \sum_{i=0}^{N-1} (\text{input}[i] - \mu)^2σ2=N1​i=0∑N−1​(input[i]−μ)2

The divisor is NNN (population, biased variance), not N−1N-1N−1. The buffers mean_out\texttt{mean\_out}mean_out and var_out\texttt{var\_out}var_out are device pointers to single floats; solve\texttt{solve}solve writes the mean to mean_out[0]\texttt{mean\_out}[0]mean_out[0] and the variance to var_out[0]\texttt{var\_out}[0]var_out[0]. Both reductions run on the GPU; no host-side accumulation.

Loading visualization...

Examples

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

Output: mean = 3.0, variance = 2.0

Mean is (1+2+3+4+5)/5=3(1+2+3+4+5)/5 = 3(1+2+3+4+5)/5=3. Squared deviations are 4,1,0,1,44, 1, 0, 1, 44,1,0,1,4; their mean is 10/5=210/5 = 210/5=2.

Input: input = [2, 2, 2, 2], N = 4

Output: mean = 2.0, variance = 0.0

A constant array has zero variance.

Hint 1

You can compute both reductions in one pass by accumulating ∑xi\sum x_i∑xi​ and ∑xi2\sum x_i^2∑xi2​ together, then using Var(X)=E[X2]−E[X]2\text{Var}(X) = E[X^2] - E[X]^2Var(X)=E[X2]−E[X]2.

Hint 2

Block-local shared-memory reductions followed by one atomicAdd per block to the global sum and sum-of-squares keep atomic traffic at O(N/256)O(N/256)O(N/256).

Hint 3

After the reduction kernel finishes, a tiny single-thread finalize kernel can divide by NNN to write mean_out\texttt{mean\_out}mean_out and var_out\texttt{var\_out}var_out.

Requirements

  • Implement solve(const float* input, float* mean_out, float* var_out, int N)\texttt{solve(const float* input, float* mean\_out, float* var\_out, int N)}solve(const float* input, float* mean_out, float* var_out, int N) with extern "C"\texttt{extern "C"}extern "C" linkage.
  • Write the population mean to mean_out[0]\texttt{mean\_out}[0]mean_out[0] and the population variance (divisor NNN) to var_out[0]\texttt{var\_out}[0]var_out[0].
  • All accumulation happens on device; do not copy input\texttt{input}input to host.
  • Call cudaDeviceSynchronize\texttt{cudaDeviceSynchronize}cudaDeviceSynchronize before solve\texttt{solve}solve returns so both outputs are visible to the caller.

Constraints

  • 1≤N≤5⋅1061 \le N \le 5 \cdot 10^61≤N≤5⋅106.
  • Each input[i]\texttt{input}[i]input[i] fits in a 32-bit float.
  • input\texttt{input}input, mean_out\texttt{mean\_out}mean_out, var_out\texttt{var\_out}var_out are device pointers owned by the harness; do not cudaMalloc\texttt{cudaMalloc}cudaMalloc or cudaMemcpy\texttt{cudaMemcpy}cudaMemcpy them inside solve\texttt{solve}solve.
  • The solve\texttt{solve}solve signature must not change.
Try Similar Problems
Argmax as a CUDA KernelMediumL1 Normalization as a CUDA KernelMediumCUDA Dot Product: Multi-Block ReductionMediumL2 Normalization as a CUDA KernelMediumArgmin as a CUDA KernelMediumSingle-Pass Mean and Variance in TritonMediumMin of Array as a CUDA KernelEasySum of Array as a CUDA KernelEasyMax of Array as a CUDA KernelEasyRMS Normalization as a CUDA KernelMediumLayer Normalization as a CUDA KernelMediumSoftmax as a CUDA KernelMedium

Accepts: array

You must run your code first.

Kernel performance

Submit a correct solution to see your kernel performance.

Problems
Loading...
1 / 1