GPU.js Out of Bounds Array Access Behavior
When running kernels in gpu.js, accessing an input array at indices
beyond its dimensions does not trigger a typical JavaScript runtime
error. Instead, the behavior depends directly on whether the kernel runs
on the GPU via WebGL or falls back to the CPU. In GPU mode,
out-of-bounds reads typically return zero or clamped edge values due to
how textures are sampled, whereas CPU mode returns
undefined, which frequently coerces to NaN in
mathematical calculations. Understanding this divergence is essential
for preventing silent data corruption in parallel processing
pipelines.
GPU Mode Behavior (WebGL)
In GPU mode, gpu.js compiles your kernel function into GLSL shaders
and loads input arrays into WebGL textures. When a thread accesses an
input array using this.thread.x,
this.thread.y, or calculated coordinates, the operation
translates into texture lookups.
- No Memory Exceptions: GPUs do not throw
IndexOutOfBoundsorRangeErrorexceptions. Execution proceeds for all threads regardless of the coordinates requested. - Texture Clamping and Zero Padding: WebGL textures
are typically configured with
CLAMP_TO_EDGEor return0.0(transparent black) when reading outside designated coordinate normalized spaces, depending on the internal texture wrapper used by gpu.js. In most standard mathematical kernels, reading past the boundaries yields0. - Interpolation Artifacts: If coordinates fall slightly outside expected discrete integer steps due to precision issues, the value retrieved may be an interpolated edge value rather than clean data.
CPU Fallback Mode Behavior
If WebGL is unsupported or if the kernel is explicitly configured
with { mode: 'cpu' }, gpu.js runs using standard JavaScript
loops.
- JavaScript Semantics Apply: Reading an array at an
out-of-bounds index yields
undefined. - Arithmetic Degradation: If the kernel performs
arithmetic operations (such as addition or multiplication) on
undefined, the result becomesNaN. - Output Contamination: The resulting output array
will contain
NaNentries in positions corresponding to threads that attempted out-of-bounds reads, directly altering downstream calculations.
Consequences of Boundary Mismatches
A common scenario causing coordinate overruns occurs when the
kernel's output dimensions are larger than the dimensions
of the input array.
Because gpu.js runs one thread per unit of the specified
output dimensions, threads assigned to higher coordinates
will systematically request indices that do not exist in the source
data. Because no error is thrown in GPU mode, kernels may produce output
matrices filled partially with correct data and partially with
unexpected zeros, masking logical bugs during development.
How to Prevent Out-of-Bounds Access
To ensure deterministic and accurate results across all execution modes:
- Synchronize Output and Input Dimensions: Ensure the
outputconfiguration of the kernel matches the size of the data being processed. - Implement Manual Bounds Checking: If the output grid must exceed the input size, add conditional logic inside the kernel to handle boundary limits explicitly:
const kernel = gpu.createKernel(function(data, width, height) {
const x = this.thread.x;
const y = this.thread.y;
if (x >= width || y >= height) {
return 0; // Explicit fallback value
}
return data[y][x] * 2;
}).setOutput([largerWidth, largerHeight]);- Pass Array Dimensions as Arguments: Kernels cannot
inspect the
.lengthproperty of input arrays on the GPU. Always supply array boundaries as uniform arguments to facilitate runtime boundary checks.