Conv device wrappers: update() leaves stale geometry and fused-output pointers, two wrappers miss the 2 GiB gate, negative output extents not rejected
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 10.5k
- Forks
- 2.1k
- Avg merge
- 3d 11h
- Merged PRs (30d)
- 7
Description
Description
Three validation/update gaps in the 2.x conv device wrappers, plus two smaller latent inconsistencies.
1. update() refreshes pointers but leaves geometry stale
conv/device/implicit_gemm_convolution.h:305-316 (the fusion implicit_gemm_convolution_fusion.h:209-222 and direct direct_convolution.h:192-204 wrappers have the same shape):
Status update(Arguments const &args, void *workspace = nullptr) {
params_.ptr_A = args.ref_A.data();
params_.ptr_B = args.ref_B.data();
params_.ptr_C = args.ref_C.data();
params_.ptr_D = args.ref_D.data();
params_.output_op = args.output_op;
params_.semaphore = static_cast<int *>(workspace);
return Status::kSuccess;
}
problem_size, implicit_gemm_problem_size, grid_tiled_shape, swizzle_log_tile, gemm_k_iterations(_per_channel), all four iterator Params, and split_k_mode are never refreshed. Reusing the operation via update() with a different problem size or split-k mode launches the old grid and old K trip count over new tensors: silent wrong results or OOB.
Additionally, when the plain wrapper is instantiated on kernel::ImplicitGemmConvolutionWithFusedEpilogue or ...WithAbsMax (default_conv2d_fprop_with_broadcast.h), Params also carry ptr_Vector/ptr_Tensor/ldr/ldt (and ptr_Aux), which update() skips even though it is exactly the class of pointer it does refresh for C/D. After updating to a new layer's bias/residual tensor, the kernel keeps reading and writing the previous one.
2. The >=2 GiB offset-overflow gate is missing from two sibling wrappers
The plain wrapper rejects any activation/filter/output tensor of 2 GiB or more because the 2.x iterators use 32-bit offsets:
// conv/device/implicit_gemm_convolution.h:117-126
if (args.problem_size.activation_size() * sizeof(ElementA) >= (1ull << 31) || ...
That gate was added there only (3.8). implicit_gemm_convolution_fusion.h:104-133 and direct_convolution.h:104-157 run the same iterator family but their can_implement goes straight to per-iterator alignment checks without any size gate. A >=2 GiB problem passes validation and overflows iterator offsets at runtime.
3. Degenerate problems yield negative output extents that are never rejected
conv/convnd_problem_shape.hpp:554-572:
return 1 + (act_ext + pad_total - ((filter_ext - 1) * dilation + 1)) / tstride;
When the filter exceeds the padded input this goes negative (C++ truncation): e.g. fprop with activation {5x5}, filter {8x8}, no padding, stride 1 gives z = p = -2, and the linearized M of the GEMM comes back positive (-2 * -2). Nothing in ConvProblemShape construction or the sm90/sm100 collectives' can_implement rejects it (alignment checks see only the positive A/B shapes), so the 3.x path builds TMA im2col descriptors from garbage geometry instead of returning kErrorInvalidProblem. The result is stride-dependent (extent 0 at stride 2, -2 at stride 1).
Additional latent observations (no in-tree trigger today)
conv/kernel/sm100_implicit_gemm_tma_warpspecialized.hpp:to_underlying_argumentssizes the scheduler workspace segment from the transformed problem-shape form whileget_workspace_size/initialize_workspaceuse the linearized form; benign while every reachable conv scheduler reports zero workspace.- Group handling differs between helpers:
conv2d_problem_size.h:264-269groups the filter extent bygroups,conv3d_problem_size.h:295-300does not; grouped conv3d kernels do not exist so the pair never disagrees in practice.
Suggested fixes
- Refresh the full Params set in each wrapper's
update()(or drop the entry points). - Port the 2 GiB gate into the fusion and direct wrappers'
can_implement. - Reject non-positive output extents in
calculate_xformed_actconsumers (or atcan_implement) withkErrorInvalidProblem.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the update() and can_implement() implementations in conv/device/implicit_gemm_convolution.h, conv/device/implicit_gemm_convolution_fusion.h, and conv/device/direct_convolution.h, then trace output-shape handling in conv/convnd_problem_shape.hpp and the sm90/sm100 collective validation paths. Done means all relevant Params and tensor pointers are refreshed, both sibling wrappers reject sizes at or above 2 GiB, and non-positive output extents return kErrorInvalidProblem.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- backend-api-design, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100