TensorTonic
Problems
2D Convolution as a CUDA Kernel
Computer VisionGPU Programming
Medium

Implement a CUDA kernel that performs a 2D cross-correlation of a single-channel input III of shape (H,W)(H, W)(H,W) with a single-channel kernel KKK of shape (kH,kW)(kH, kW)(kH,kW). This is the operation deep learning frameworks call "convolution" (no kernel flip). Stride is 111 and there is no padding (valid).

For each output position (i,j)(i, j)(i,j):

output[i,j]=∑a=0kH−1∑b=0kW−1input[i+a,  j+b]⋅kernel[a,b]\text{output}[i, j] = \sum_{a=0}^{kH-1} \sum_{b=0}^{kW-1} \text{input}[i + a,\; j + b] \cdot \text{kernel}[a, b]output[i,j]=a=0∑kH−1​b=0∑kW−1​input[i+a,j+b]⋅kernel[a,b]

The output has shape (H−kH+1,W−kW+1)(H - kH + 1, W - kW + 1)(H−kH+1,W−kW+1). All three buffers are stored as row-major flat arrays, so element (i,j)(i, j)(i,j) of an R×CR \times CR×C matrix lives at linear index i⋅C+ji \cdot C + ji⋅C+j.

Loading visualization...

Examples

Input: H = 3, W = 3, kH = 2, kW = 2, input = [[1, 2, 3], [4, 5, 6], [7, 8, 9]], kernel = [[1, 0], [0, -1]]

Output: [[-4.0, -4.0], [-4.0, -4.0]]

Each 2×22 \times 22×2 window contributes top-left−bottom-right\text{top-left} - \text{bottom-right}top-left−bottom-right, which is −4-4−4 everywhere on this diagonal ramp.

Input: H = 2, W = 3, kH = 1, kW = 2, input = [[1, 2, 3], [4, 5, 6]], kernel = [[1, 1]]

Output: [[3.0, 5.0], [9.0, 11.0]]

A horizontal sum of every adjacent pair in each row.

Hint 1

Each output position owns an independent kH×kWkH \times kWkH×kW window of input reads, so threads do not need to synchronize or share state.

Hint 2

Map blockIdx.y, threadIdx.y\texttt{blockIdx.y, threadIdx.y}blockIdx.y, threadIdx.y to the output row iii and blockIdx.x, threadIdx.x\texttt{blockIdx.x, threadIdx.x}blockIdx.x, threadIdx.x to the output column jjj, and remember the output buffer has its own stride outW=W−kW+1\texttt{outW} = W - kW + 1outW=W−kW+1.

Hint 3

For small kernel sizes the inner double loop is tight enough that the compiler unrolls it; accumulating into a local float\texttt{float}float avoids repeated global memory writes.

Requirements

  • Launch one thread per output element using a 2D grid of 16×1616 \times 1616×16 blocks
  • Accumulate the dot product over the kH×kWkH \times kWkH×kW kernel window
  • Respect row-major layout when computing linear indices into input\texttt{input}input, kernel\texttt{kernel}kernel, and output\texttt{output}output
  • The solve\texttt{solve}solve signature must not change

Constraints

  • 1≤H,W≤10241 \le H, W \le 10241≤H,W≤1024
  • 1≤kH≤H1 \le kH \le H1≤kH≤H and 1≤kW≤W1 \le kW \le W1≤kW≤W
  • All buffers are device pointers
  • Use 16×1616 \times 1616×16 thread blocks
  • Values are 32-bit float, cross-correlation only (no kernel flip)
Try Similar Problems
Max Pool 2D as a CUDA KernelMedium3D Convolution as a CUDA KernelHard1D Convolution as a CUDA KernelEasyArgmax as a CUDA KernelMediumRMS Normalization as a CUDA KernelMediumMean and Variance as a CUDA KernelMediumLayer Normalization as a CUDA KernelMediumSoftmax as a CUDA KernelMediumMatrix Multiplication as a CUDA KernelMediumL1 Normalization as a CUDA KernelMediumCosine Similarity as a CUDA KernelMediumCUDA Dot Product: Multi-Block ReductionMedium

Accepts: array

Accepts: array

Accepts: number

Accepts: number

Accepts: number

Accepts: number

You must run your code first.

Kernel performance

Submit a correct solution to see your kernel performance.

2D Convolution as a CUDA Kernel

2D Convolution as a CUDA Kernel

Computer VisionGPU Programming
Medium

Implement a CUDA kernel that performs a 2D cross-correlation of a single-channel input III of shape (H,W)(H, W)(H,W) with a single-channel kernel KKK of shape (kH,kW)(kH, kW)(kH,kW). This is the operation deep learning frameworks call "convolution" (no kernel flip). Stride is 111 and there is no padding (valid).

For each output position (i,j)(i, j)(i,j):

output[i,j]=∑a=0kH−1∑b=0kW−1input[i+a,  j+b]⋅kernel[a,b]\text{output}[i, j] = \sum_{a=0}^{kH-1} \sum_{b=0}^{kW-1} \text{input}[i + a,\; j + b] \cdot \text{kernel}[a, b]output[i,j]=a=0∑kH−1​b=0∑kW−1​input[i+a,j+b]⋅kernel[a,b]

The output has shape (H−kH+1,W−kW+1)(H - kH + 1, W - kW + 1)(H−kH+1,W−kW+1). All three buffers are stored as row-major flat arrays, so element (i,j)(i, j)(i,j) of an R×CR \times CR×C matrix lives at linear index i⋅C+ji \cdot C + ji⋅C+j.

Loading visualization...

Examples

Input: H = 3, W = 3, kH = 2, kW = 2, input = [[1, 2, 3], [4, 5, 6], [7, 8, 9]], kernel = [[1, 0], [0, -1]]

Output: [[-4.0, -4.0], [-4.0, -4.0]]

Each 2×22 \times 22×2 window contributes top-left−bottom-right\text{top-left} - \text{bottom-right}top-left−bottom-right, which is −4-4−4 everywhere on this diagonal ramp.

Input: H = 2, W = 3, kH = 1, kW = 2, input = [[1, 2, 3], [4, 5, 6]], kernel = [[1, 1]]

Output: [[3.0, 5.0], [9.0, 11.0]]

A horizontal sum of every adjacent pair in each row.

Hint 1

Each output position owns an independent kH×kWkH \times kWkH×kW window of input reads, so threads do not need to synchronize or share state.

Hint 2

Map blockIdx.y, threadIdx.y\texttt{blockIdx.y, threadIdx.y}blockIdx.y, threadIdx.y to the output row iii and blockIdx.x, threadIdx.x\texttt{blockIdx.x, threadIdx.x}blockIdx.x, threadIdx.x to the output column jjj, and remember the output buffer has its own stride outW=W−kW+1\texttt{outW} = W - kW + 1outW=W−kW+1.

Hint 3

For small kernel sizes the inner double loop is tight enough that the compiler unrolls it; accumulating into a local float\texttt{float}float avoids repeated global memory writes.

Requirements

  • Launch one thread per output element using a 2D grid of 16×1616 \times 1616×16 blocks
  • Accumulate the dot product over the kH×kWkH \times kWkH×kW kernel window
  • Respect row-major layout when computing linear indices into input\texttt{input}input, kernel\texttt{kernel}kernel, and output\texttt{output}output
  • The solve\texttt{solve}solve signature must not change

Constraints

  • 1≤H,W≤10241 \le H, W \le 10241≤H,W≤1024
  • 1≤kH≤H1 \le kH \le H1≤kH≤H and 1≤kW≤W1 \le kW \le W1≤kW≤W
  • All buffers are device pointers
  • Use 16×1616 \times 1616×16 thread blocks
  • Values are 32-bit float, cross-correlation only (no kernel flip)
Try Similar Problems
Max Pool 2D as a CUDA KernelMedium3D Convolution as a CUDA KernelHard1D Convolution as a CUDA KernelEasyArgmax as a CUDA KernelMediumRMS Normalization as a CUDA KernelMediumMean and Variance as a CUDA KernelMediumLayer Normalization as a CUDA KernelMediumSoftmax as a CUDA KernelMediumMatrix Multiplication as a CUDA KernelMediumL1 Normalization as a CUDA KernelMediumCosine Similarity as a CUDA KernelMediumCUDA Dot Product: Multi-Block ReductionMedium

Accepts: array

Accepts: array

Accepts: number

Accepts: number

Accepts: number

Accepts: number

You must run your code first.

Kernel performance

Submit a correct solution to see your kernel performance.

Problems
Loading...
1 / 1