Sparse Convolution

class fvdb.ConvolutionPlan(_source_grid: GridBatch, _target_grid: GridBatch, _geometry: fvdb._fvdb_cpp.ConvolutionGeometry, _channel_pairs: tuple[tuple[int, int], ...], _transposed: bool, _backend: _MatmulBackend | _GatherScatterBackend | _PredGatherIGemmBackend, _transform_compatibility: ConvolutionTransformCompatibility, _topology_policy: ConvolutionTopologyPolicy, _topology_provenance: ConvolutionTopologyProvenance, _coverage_report_cache: _CoverageReportCache, _coverage_report_swapped: bool)[source]

A pre-configured plan for efficient sparse 3D convolution operations on fvdb.GridBatch.

ConvolutionPlan encapsulates all the configuration and optimization structures needed to perform sparse convolution operations efficiently. Like FFT plans in signal processing libraries, a ConvolutionPlan represents a single direction of computation - either regular convolution or transposed convolution.

The plan handles the complex sparse data structures and backend optimizations internally, allowing users to focus on the core convolution parameters: input/output channels, kernel size, stride, and the grid structure.

A plan stores one finite convolution relation. Componentwise, that relation is fine_ijk = stride * coarse_ijk + tap_ijk - padding_before, where padding_before = floor((kernel_size - 1) / 2) and each zero-based tap satisfies 0 <= tap_ijk[axis] < kernel_size[axis]. Generated plans use complete structural support; an explicit target restricts that relation. A transposed plan evaluates the same fine/coarse connectivity in the opposite direction and is not a value inverse. For an exact finite adjoint, use from_plan_transposed() rather than reconstructing a plan from grids.

For framework portability, this index relation matches spconv and TorchSparse when they use padding=(kernel_size - 1) // 2. MinkowskiEngine corner-anchors even kernels on [0, kernel_size), so porting an even-kernel topology from MinkowskiEngine shifts it by floor((kernel_size - 1) / 2). fVDB’s complete policy also materializes uncropped boundary support: a full 16^3 input with kernel_size=stride=4 produces a 5^3 coarse topology rather than 4^3.

Usage Pattern:

  1. Create a plan using one of the from_* class methods (see from_grid_batch()).

  2. Use the execute() method to perform convolutions with different weights and data on the same grid structures.

  3. Reuse the same plan for multiple convolutions with the same configuration

Example Usage:

from fvdb import GridBatch, ConvolutionPlan

# Create a grid batch
my_grid_batch = GridBatch.from_ijk(...)

# Create a plan for 3x3x3 convolution with stride 1
plan = ConvolutionPlan.from_grid_batch(
    kernel_size=3,
    stride=1,
    source_grid=my_grid_batch
)

# execute convolution with different weights
features = torch.randn(num_voxels, 32, device="cuda")
weights = torch.randn(64, 32, 3, 3, 3, device="cuda")
output = plan.execute(features, weights)

Note

  • Always create plans using the from_* class methods, never call __init__ directly

  • Plans are immutable once created

  • The same plan can be reused for multiple execute() calls with different data/weights

  • Channel pairs can be specified at plan creation time for optimal backend selection

property coverage_report: ConvolutionCoverageReport | None

Exact input/output rulebook degree diagnostics, when the backend has a rulebook.

execute(data: Tensor, weights: Tensor) Tensor[source]
execute(data: JaggedTensor, weights: Tensor) JaggedTensor

Execute this ConvolutionPlan with the input data and weights.

This is the main method for performing convolution operations. It applies the convolution kernel to the sparse voxel data according to the plan’s pre-configured structure and optimizations.

If the source grid batch has size 1, then data can be a torch.Tensor with shape (total_voxels, in_channels).

If the source grid batch has size > 1, then data should be a JaggedTensor with shape (batch_size, num_voxels_in_grid_b, in_channels).

Note

  • The same plan can be reused with different weights and data

  • Channel pairs must match those specified during plan creation

  • The plan automatically handles the sparse structure and backend optimizations

  • For transposed convolution plans, this performs the transpose operation

Parameters:
  • data (torch.Tensor | JaggedTensor) – Input voxel features. Can be either: (i) torch.Tensor for single grids: shape (total_voxels, in_channels) or (ii) JaggedTensor for batches of grids: shape (batch_size, num_voxels_in_grid_b, in_channels)

  • weights (torch.Tensor) – Convolution kernel weights with shape: (out_channels, in_channels, kernel_size[0], kernel_size[1], kernel_size[2]). Identity K=1, S=1 plans also accept the compact shape (out_channels, in_channels).

Returns:

output_features (torch.Tensor | JaggedTensor) – Convolved features with the same type as input: (i) torch.Tensor with shape (total_output_voxels, out_channels) for single grids or (ii) JaggedTensor with shape (batch_size, output_voxels_per_grid, out_channels) for batches

Raises:

ValueError – If the channel pair (in_channels, out_channels) from the weights is not supported by this plan’s channel_pairs configuration.

Example:

# Single grid example
features = torch.randn(1000, 32, device="cuda")  # 1000 voxels, 32 channels
weights = torch.randn(64, 32, 3, 3, 3, device="cuda")  # 32->64 channels, 3x3x3 kernel
output = plan.execute(features, weights)  # Shape: (output_voxels, 64)

# Batched example
batch_features = JaggedTensor(torch.randn(5, 1000, 32, device="cuda"))
output = plan.execute(batch_features, weights)  # Shape: (5, output_voxels, 64)
classmethod from_grid_batch(kernel_size: Tensor | ndarray | int | float | integer | floating | Sequence[int | float | integer | floating] | Size, stride: Tensor | ndarray | int | float | integer | floating | Sequence[int | float | integer | floating] | Size, source_grid: GridBatch, target_grid: GridBatch | None = None, *, expert_config: dict[str, Any] = {'backend': 'default'}, channel_pairs: tuple[tuple[int, int], ...] = (), topology_policy: ConvolutionTopologyPolicy | None = None, strict_output_coverage: bool = False, acknowledge_incomplete_coverage: bool = False) ConvolutionPlan[source]

Create a ConvolutionPlan for convolution on batches of grids. i.e. convolution where the input and output domains are both of type fvdb.GridBatch.

The plan returned by this method is optimized for running convolution on a batch of grids simultaneously and in parallel, which is more efficient than processing individual grids separately when you have a batch of data.

Parameters:
  • kernel_size (NumericRank1) – Size of the convolution kernel. Can be a single int (cubic kernel) or a 3-element sequence for (x, y, z) dimensions.

  • stride (NumericRank1) – Convolution stride. Can be a single int or 3-element sequence.

  • source_grid (GridBatch) – fvdb.GridBatch encoding the structure of the input domain.

  • target_grid (GridBatch | None) – fvdb.GridBatch encoding the structure of the output domain. If None, the target_grid is automatically computed based on kernel_size and stride applied to source_grid.

  • expert_config (dict[str, Any]) – Advanced configuration options (rarely needed by typical users).

  • channel_pairs (tuple[tuple[int, int], ...]) – Supported input/output channel combinations as tuples. Each tuple represents (input_channels, output_channels). e.g: ((32, 64), (64, 128)) supports 32->64 and 64->128 convolutions. Defaults to _ANY_CHANNEL_PAIRS, which means any channel pairs are supported.

  • topology_policy (ConvolutionTopologyPolicy | None) – COMPLETE generates the complete structural support; RESTRICTED requires target_grid and restricts the relation to it. When omitted, the policy is inferred from target_grid.

  • strict_output_coverage (bool) – Reject explicit targets with degree-zero output rows.

  • acknowledge_incomplete_coverage (bool) – Suppress the once-per-geometry warning for stride residues that are intentionally not sampled.

Returns:

convolution_plan (ConvolutionPlan) – Configured plan ready for execute() operations.

Example:

# Create a batched grid
grid_batch = GridBatch.from_points(...)

# Create plan for 3x3x3 convolution on batched grids
plan = ConvolutionPlan.from_grid_batch(
    kernel_size=3,
    stride=1,
    source_grid=grid_batch
)

# execute to batched data
batch_data = JaggedTensor(torch.randn(5, 1000, 8, device="cuda"))
weights = torch.randn(16, 8, 3, 3, 3, device="cuda")
output = plan.execute(batch_data, weights)
classmethod from_grid_batch_transposed(kernel_size: Tensor | ndarray | int | float | integer | floating | Sequence[int | float | integer | floating] | Size, stride: Tensor | ndarray | int | float | integer | floating | Sequence[int | float | integer | floating] | Size, source_grid: GridBatch, target_grid: GridBatch | None = None, *, expert_config: dict[str, Any] = {'backend': 'default'}, channel_pairs: tuple[tuple[int, int], ...] = (), topology_policy: ConvolutionTopologyPolicy | None = None, strict_output_coverage: bool = False, acknowledge_incomplete_coverage: bool = False) ConvolutionPlan[source]

Create a ConvolutionPlan for transposed convolution on batches of grids. i.e. transposed convolution where the input and output domains are both of type fvdb.GridBatch.

Transposed convolution is commonly used for decoder and generative operations. It evaluates the same fine/coarse graph in the opposite direction; it is not an inverse and need not recover an input or its topology.

Note

target_grid=None selects COMPLETE and generates the complete uncropped transposed support. An explicit target selects RESTRICTED and may contain zero-degree rows. This factory supports independently learned transpose weights; for the exact weighted adjoint of a particular plan, use from_plan_transposed() and pass weight.transpose(0, 1).contiguous() at execution.

Parameters:
  • kernel_size (NumericMaxRank1) – Size of the convolution kernel. Can be a single int (cubic kernel) or a 3-element sequence for (x, y, z) dimensions.

  • stride – Convolution stride. Can be a single int or 3-element sequence.

  • source_grid (GridBatch) – fvdb.GridBatch encoding the structure of the input domain.

  • target_grid (GridBatch | None) – fvdb.GridBatch encoding the structure of the output domain. If None, the target_grid is automatically computed based on kernel_size and stride applied to source_grid.

  • expert_config (dict[str, Any]) – Advanced configuration options (rarely needed by typical users).

  • channel_pairs (tuple[tuple[int, int], ...]) – Supported input/output channel combinations as tuples. Defaults to _ANY_CHANNEL_PAIRS, which means any channel pairs are supported.

  • topology_policy (ConvolutionTopologyPolicy | None) – COMPLETE generates the complete structural support; RESTRICTED requires target_grid. When omitted, the policy is inferred from target_grid.

  • strict_output_coverage (bool) – Reject explicit targets with degree-zero output rows.

  • acknowledge_incomplete_coverage (bool) – Suppress the once-per-geometry warning for stride residues that are intentionally not sampled.

Returns:

convolution_plan (ConvolutionPlan) – Configured plan ready for transposed convolution operations via execute().

classmethod from_plan_transposed(plan: ConvolutionPlan) ConvolutionPlan[source]

Create a transposed version of an existing ConvolutionPlan.

This method creates a new plan that performs the exact transpose operation of the given plan (i.e convolution becomes transposed convolution and vice versa). It swaps the source and target grids, reverses the stored finite edge set and channel pairs, and flips the transposed flag. It does not reconstruct topology from the swapped grids.

Note

This is useful when a paired layer must apply the exact finite adjoint connectivity of an existing plan. It is not an inverse and need not recover the original input.

Parameters:

plan (ConvolutionPlan) – An existing ConvolutionPlan to transpose.

Returns:

convolution_plan (ConvolutionPlan) – A new plan that performs the transpose of the input plan.

Example:

# Create forward plan
forward_plan = ConvolutionPlan.from_grid_batch(
    kernel_size=3,
    stride=1,
    source_grid=input_grid_batch
)

# Create the corresponding backward/transpose plan
transposed_plan = ConvolutionPlan.from_plan_transposed(forward_plan)
property geometry: fvdb._fvdb_cpp.ConvolutionGeometry

Canonical immutable geometry shared by this plan’s topology and executors.

property has_fixed_topology: bool

Returns True if the source and target grids have the same topology, meaning the same voxel structure.

Returns:

has_fixed_topology (bool) – True if source and target grids are the same topology, False otherwise.

property kernel_size: Tensor

Kernel dimensions in the canonical torch_same_phase geometry.

property phase_policy: ConvolutionPhasePolicy

Kernel phase convention used by this plan.

property source_grid_batch: GridBatch

Return the fvdb.GridBatch representing the source domain of the convolution. If the plan was created for a single grid, it is returned as a batch of size 1.

Returns:

source_grid_batch (GridBatch) – The source fvdb.GridBatch of the convolution plan.

property stride: Tensor

Stride dimensions in the canonical torch_same_phase geometry.

property target_grid_batch: GridBatch

Return the fvdb.GridBatch representing the target domain of the convolution. If the plan was created for a single grid, it is returned as a batch of size 1.

Returns:

target_grid_batch (GridBatch) – The target fvdb.GridBatch of the convolution plan.

property topology_policy: ConvolutionTopologyPolicy

Resolved complete or restricted topology policy.

property topology_provenance: ConvolutionTopologyProvenance

How this plan’s finite topology was obtained.

Exact transposes always use the stored finite edge set of their source plan and therefore have restricted policy.

property transform_compatibility: ConvolutionTransformCompatibility

Validated fine/coarse transform compatibility diagnostic.

valid_usage(in_channels: int, out_channels: int, kernel_size: Tensor | ndarray | int | float | integer | floating | Sequence[int | float | integer | floating] | Size, stride: Tensor | ndarray | int | float | integer | floating | Sequence[int | float | integer | floating] | Size, transposed: bool) bool[source]

Check if this ConvolutionPlan is valid for the given usage. This method returns True if the plan can apply a (transposed) convolution with the given kernel_size and stride from in_channels to out_channels.

Parameters:
  • in_channels (int) – Number of input channels.

  • out_channels (int) – Number of output channels.

  • kernel_size (NumericMaxRank1) – Kernel size. Can be a single int or 3-element sequence.

  • stride (NumericMaxRank1) – Stride. Can be a single int or 3-element sequence.

  • transposed (bool) – Whether the plan is transposed.

Returns:

is_valid (bool) – True if the plan is valid for the given configuration, False otherwise.

class fvdb.ConvolutionCoverageReport(input_row_count: int, output_row_count: int, input_zero_count: int, input_zero_fraction: float, input_degree_min: int, input_degree_max: int, input_degree_histogram: tuple[tuple[int, int], ...], output_zero_count: int, output_zero_fraction: float, output_degree_min: int, output_degree_max: int, output_degree_histogram: tuple[tuple[int, int], ...])[source]

Exact rulebook degree diagnostics for a finite convolution plan.

input_degree_histogram: tuple[tuple[int, int], ...]
input_degree_max: int
input_degree_min: int
input_row_count: int
input_zero_count: int
input_zero_fraction: float
output_degree_histogram: tuple[tuple[int, int], ...]
output_degree_max: int
output_degree_min: int
output_row_count: int
output_zero_count: int
output_zero_fraction: float
class fvdb.ConvolutionTransformCompatibility(fine_grid_count: int, coarse_grid_count: int, same_batch_size: bool, same_device: bool, scale_compatible: bool, registration_integer: bool, registration_zero: bool, compatible: bool, registration_offset: Tensor | None)[source]

Compatibility of a plan’s normalized fine and coarse lattices.

Compatibility requires matching batch/device metadata, h_coarse == stride * h_fine, and the canonical uniform registration a == 0. Comparisons use atol=rtol=1e-6.

coarse_grid_count: int
compatible: bool
fine_grid_count: int
registration_integer: bool
registration_offset: Tensor | None
registration_zero: bool
same_batch_size: bool
same_device: bool
scale_compatible: bool
class fvdb.ConvolutionCoverageWarning[source]

A convolution geometry leaves some stride residues structurally uncovered.

The warning is emitted once per (kernel_size, stride) geometry for the lifetime of the process. Pass acknowledge_incomplete_coverage=True when constructing a plan to acknowledge and suppress it explicitly.