v1.16.0 #1716
shi-eric
announced in
Announcements
v1.16.0
#1716
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Warp v1.16.0
Warp v1.16 adds in-place rebuilding for fixed-capacity NanoVDB volumes, including during CUDA graph capture. This lets fluid simulations update sparse-grid topologies without allocating new volumes. The release also adds grouped HashGrid queries for multi-environment workloads, NumPy-style tile slicing, CPU support for JAX FFI wrappers, experimental support for replaying more operations in CPU graphs and saved
.wrpgraphs, and CUDA profiler range controls.New features
Rebuild sparse NanoVDB volumes in place
Previously, a volume's sparse topology was fixed at allocation time. Simulations whose active grid changed from one step to the next, such as the affine particle-in-cell (APIC) fluid example, had to allocate a new volume. That allocation required host synchronization and could not be replayed inside a CUDA graph. Warp 1.16 adds fixed-capacity, in-place rebuilding so simulations can reuse the same volume and dependent FEM topology buffers across graph replays (#1606).
The excerpt below follows that example's allocation, rebuild, and replay flow. It omits particle initialization, capacity estimation, FEM space construction, and the APIC transfer and solve.
Capacity does not grow automatically. Pass a one-element
wp.uint32status array to the allocation method and torebuild(), then check forwp.Volume.REBUILD_SUCCESS, aREBUILD_*_CAPACITY_EXCEEDEDflag, orREBUILD_INVALID_INPUT. A tile-allocated volume must be rebuilt from tile positions, while a voxel-allocated volume must be rebuilt from voxel positions. Thepoint_maskparameter can exclude input points, and Warp deduplicates repeated positions.On CUDA, rebuildable allocation and rebuilding can run inside graph capture when memory-pool allocation is enabled. Exact, non-rebuildable allocation and host-side queries such as
get_active_stats()must remain outside capture.See
example_apic_fluid.pyfor the complete capacity estimation, topology construction, and captured simulation loop.API changes:
wp.Volume.allocate_by_tiles()rebuildable,max_tiles,max_lower_nodes,max_upper_nodes,status, andpoint_maskparameters.wp.Volume.allocate_by_voxels()rebuildable,max_active_voxels,max_leaf_nodes,max_lower_nodes,max_upper_nodes,status, andpoint_maskparameters.warp.fem.Nanogrid()rebuildableparameter for retaining capacity-sized topology buffers.wp.Volume.rebuild()andwarp.fem.Nanogrid.rebuild()Nanogridthat also refreshes its geometry buffers.topology.rebuild()on compatibleNanogridfunction spaceswp.Volume.is_rebuildable,wp.Volume.get_rebuild_info(), andwp.Volume.get_active_stats()wp.Volume.REBUILD_*statusarray.wp.volume_voxel_count()Multi-environment spatial queries
Grouped HashGrid construction and queries
Independent simulation environments can now share one spatial grid without visiting candidates from neighboring worlds. Assign each point an
int32group inHashGrid.build(), then pass the desired group towp.hash_grid_query()(#1579).Group IDs may be any
int32values and can change between rebuilds, including during graph replay. If the query omits the group argument, it visits all candidates. Before capturing a grouped CUDA rebuild without a warm-up build, callgrid.reserve(num_points, with_groups=True). Hash-grid queries return cell candidates, so kernels should still test the actual distance.Tile programming
NumPy-style tile slicing
Tile kernels now use NumPy-style indexing to select, reverse, stride, gather, and assign subregions. An integer index collapses a dimension and may be negative. Use
wp.tile_slice_indexed()for one-axis gathers such astile[indices, :](#1176).Output:
The source tile in a slice assignment must have a matching shape. Tile views do not support compound assignment, and slices do not support scalar broadcasting. Indexed gathers select one axis at a time and require full
:slices on the other axes.The out-of-place
wp.tile_lower_solve()now supports gradients for vector and matrix right-hand sides. This makes lower-triangular solves available inwp.Tapebackward passes (#1378).JAX integration
Run Warp FFI callbacks on CPU
JAX can now run
wp.jax_kernel()andwp.jax_callable()wrappers on CPU as well as CUDA. JAX selects the device, so a CPUjax.jitprogram invokes the Warp callback without routing buffers through a GPU (#1661).JAX 0.5.0 or newer is required.
JaxCallableGraphMode.NONEandJaxCallableGraphMode.JAXwork on CPU. The Warp-managed graph modes remain CUDA-only.example_jax_kernel.pyshows more call shapes.Set CUDA block sizes for JAX tile kernels
JAX FFI wrappers created with
wp.jax_kernel()now acceptblock_dim, letting a CUDA tile kernel choose how many threads cooperate on each tile. The value is fixed when the wrapper is constructed and is also used for generated adjoint launches (#1436).TILE_SIZEis the logical data shape, whileTILE_THREADSis a CUDA execution choice. Keepoutput_dimsequal to the logical result shape rather than including the block width. See CUDA block dimensions and tile kernels for more detail.Graph capture
Replay more operations in CPU and saved
.wrpgraphsImportant
This is an experimental feature. The API may change without a formal deprecation cycle.
API Capture can now record
wp.utils.array_sum()andwp.utils.array_inner()on CPU and CUDA, allowing saved.wrpgraphs to recompute those reductions from current inputs during replay. Live CPU graphs can also rebuildwp.HashGriddata and refit or rebuildwp.Bvhtrees from their current arrays (#1663, #1664, #1665).Non-empty reductions recorded through API Capture require an explicit output array. Negative strides are unsupported. Counts and layout strides must fit a signed 32-bit integer. Because resources use process-local handles, graphs that record
HashGrid.build(),Bvh.refit(), orBvh.rebuild()are replay-only.wp.capture_save()rejects these graphs instead of writing a non-portable file. See CPU Graphs and Saving and Loading Graphs for the full lists of operations and limitations.Profiling
Target external profiler captures
External profilers can now skip initialization and warm-up work and capture only the steady-state region.
wp.cuda_profiler_start(),wp.cuda_profiler_stop(), andwp.ScopedCudaProfilerexpose CUDA profiler range controls from Python (#1596).The warm-up launch stays outside the capture range. The synchronization inside the scope ensures that the asynchronous launches complete before
wp.cuda_profiler_stop()marks the end of collection. CUDA does not guarantee that the stop call synchronizes the device.Configure the external profiler to honor these calls. For example:
For Nsight Compute, use
--profile-from-start off. Warp invokes the profiler-control calls with the selected device's CUDA context current; the profiler and its configuration determine which activity is collected during that interval.Additional API improvements
wp.quat_twist_angle_signed()recovers the signed rotational coordinate represented by a quaternion. For smallfloat32rotations, the existing unsignedwp.quat_twist_angle()is now more accurate (Stabilizewp.quat_twist_angle()near zero and add a signed variant #1631).wp.Stream.is_blockingreports which behavior a stream uses. Interoperability code can check borrowed streams before releasing temporary Warp resources, then either synchronize a non-blocking stream on the host or make a blocking Warp stream wait on it. See Warp's non-blocking stream guidance for both patterns (Add documentation for working with non-blocking CUDA streams #1618).repr()output such aswp.array4d[wp.uint32]. Generated API documentation uses the same form that appears in annotations (Array annotationrepr()uses constructor form instead of subscript syntax #1628).Performance and diagnostics
@wp.kernel(module="unique")declarations from factory functions are roughly 2x faster in microbenchmarks, whether their captured values produce identical or specialized kernels (@wp.kernel(module="unique")Python-side decoration cost makes factory-pattern kernels expensive #1486).New examples
Two new distributed Jacobi solver examples expand on
example_jacobi_mpi.py, which uses CUDA-aware mpi4py directly for nearest-neighbor halo exchange. The new variants keep MPI for process setup but move the halo transfers to GPU communication libraries:example_jacobi_nccl.pyuses NCCL, NVIDIA's topology-aware inter-GPU communication library, through nccl4py, with MPI retained for rank setup (Add NCCL Jacobi example #1576).example_jacobi_nvshmem.pyuses NVSHMEM, NVIDIA's symmetric-memory library for GPU clusters, to allocate Warp arrays on the symmetric heap and exchange halo rows through host-initiatednvshmem4pytransfers (CUDA 12 package, CUDA 13 package), with MPI retained for bootstrap (Add NVSHMEM Jacobi example #1582).Announcements
Tentative CUDA 13 PyPI wheel builds
pipdoes not check the installed driver and may install a wheel whose CUDA backend cannot run on an older driver.This repeats the tentative plan announced in Warp v1.15.0. See NVIDIA's CUDA minor-version compatibility table for driver requirements.
Upcoming removals
wp.vec3(...)orwp.mat22(...)when launching kernels or assigning struct fields (Deprecate Implicit Promotion of Numbers to Composite Types #1022).wp.Texture.copy_from_array()andwp.Texture.copy_to_array()are scheduled for removal in Warp 1.17. Usewp.Texture.copy_from()andwp.Texture.copy_to()instead ([REQ] Support zero-copy interop with external textures #1238).warp.jax_experimentalnamespace will remain available through Warp 1.17. Its removal, including the legacy custom-calljax_kernel()and graph-cache getter and setter APIs, is now scheduled for Warp 1.18. Migrate to the top-levelwp.jax_kernel()andwp.jax_callable()APIs (Promotewarp.jax_experimentalAPI towarp.jax#1370).warp.config.verboseandwarp.config.quietare scheduled for removal in Warp 1.18. Usewarp.config.log_level = warp.LOG_DEBUGandwarp.config.log_level = warp.LOG_WARNING, respectively.warp.config.verbose_warningsis unaffected ([BUG]:warp.utils.warn()overrides user warning filters, making deprecation warnings unsuppressible #1315).wp.HashGridQueryHandwp.HashGridQueryDare scheduled for removal in Warp 1.18. Usewp.HashGridQueryin public type annotations (Consolidate documented HashGrid query types #1452).max_verts,max_tris, anddevicearguments and compatibility attributes onwp.MarchingCubesare scheduled for removal in Warp 1.19. This includes themax_vertsandmax_trisarguments towp.MarchingCubes.resize()and theidandruntimeattributes. Output arrays are dynamically sized, and extraction uses the input field's device (Deprecate legacy MarchingCubes arguments and state #1594).masked=Trueform ofwarp.sparsetopology-changing operations is scheduled for removal in Warp 1.19. Usetopology="masked"withbsr_set_from_triplets(),bsr_assign(),bsr_set_transpose(),bsr_axpy(), andbsr_mm()(Add 4-array BSR storage with row capacity #1537).warp.fem.Nanogrid.from_environment_voxels()andwarp.fem.AdaptiveNanogrid.from_environment_voxels()is deprecated. It is scheduled for removal in Warp 1.19. Pass flatpoints,cell_levelswhere applicable,point_envs, andenv_countinstead (Graph-capturable NanoVDB volume allocation and rebuild #1606).warp.sparse.BsrMatrix.copy_nnz_async()is deprecated. It is scheduled for removal in Warp 1.20. Usewarp.sparse.BsrMatrix.notify_nnz_changed()after updating the nonzero count ([REQ] Allocation-free path for masked sparse matrix operations #987).Acknowledgments
We also thank the following contributors from outside the core Warp development team:
wp.quat_twist_angle()near zero and add a signed variant #1631).warp.fem.lookup()withwp.float64warp.fem.Grid2Dandwarp.fem.Grid3Dgeometries (fem.lookup fails to compile with FP64 geometries #1660) and updating the FEM examples for current Matplotlib releases.wp.float16parameters (Adam.set_params re-zeros fp16 optimizer moment state on every call #1593).For a complete list of changes, see the full changelog.
This discussion was created from the release v1.16.0.
All reactions