JuliaParallel / JuliaParallel/rodinia

[CUDA][srad_v2] Out-of-bounds neighbor reads occur before boundary correction

Open Beginner friendly
#12 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C
Stars
56
Forks
42
PR merge metrics
No merged PRs in 30d

Description

The `srad_v2` CUDA implementation in this repository contains global-memory out-of-bounds reads in `srad_cuda_1` and `srad_cuda_2`.

The kernels compute neighbor indices and immediately use them to load data from global memory. For boundary blocks, some of these indices fall outside the underlying allocation. The code only replaces the corresponding shared-memory values with valid boundary values after the
loads have already occurred.

I detected these invalid reads during memory-safety testing and subsequently confirmed the issue from the source-level index calculations.

## Affected Code

File: `cuda/srad_v2/srad_kernel.cu`

In `srad_cuda_1`, neighbor values are loaded before the boundary condition is handled:

```cpp
north[ty][tx] = J_cuda[index_n];
south[ty][tx] = J_cuda[index_s];

if (by == 0) {
north[ty][tx] = J_cuda[BLOCK_SIZE * bx + tx];
} else if (by == gridDim.y - 1) {
south[ty][tx] =
J_cuda[cols * BLOCK_SIZE * (gridDim.y - 1)
+ BLOCK_SIZE * bx
+ cols * (BLOCK_SIZE - 1) + tx];
}
```

A similar pattern occurs in srad_cuda_2:

```
south_c[ty][tx] = C_cuda[index_s];

if (by == gridDim.y - 1) {
south_c[ty][tx] =
C_cuda[cols * BLOCK_SIZE * (gridDim.y - 1)
+ BLOCK_SIZE * bx
+ cols * (BLOCK_SIZE - 1) + tx];
}
```

## Root Cause

The device arrays contain exactly:

`rows * cols`

elements, so the valid index range is:

`0 ... rows * cols - 1`

For the top block row (`by == 0`), `index_n` is negative, causing a read before the beginning of `J_cuda`.

For the bottom block row (`by == gridDim.y - 1`), the south-neighbor index satisfies:

`index_s >= rows * cols`

and therefore accesses memory beyond the end of the allocation.

For example, with:

`rows = 128`

`cols = 128`

the allocation contains:

`128 * 128 = 16384`

floating-point elements, corresponding to:

`16384 * sizeof(float) = 65536 bytes`

The first invalid south-neighbor access can therefore occur at:

`base + 65536`

which is exactly the first address beyond the allocation.

The later boundary correction only overwrites the value stored in shared memory. It cannot undo the out-of-bounds global-memory read
that has already occurred.

The same issue also affects the corresponding neighbor accesses in `srad_cuda_2`.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in cuda/srad_v2/srad_kernel.cu at srad_cuda_1 and srad_cuda_2, tracing index_n and index_s through the boundary branches. Verify that no neighbor load can access outside the rows * cols allocation before correction, then validate the result with the repository's memory-safety testing.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
hpc
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.