Add raw pointer upload support for Matrix data#42
Open
moulin1024 wants to merge 1 commit into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds raw pointer upload support for
pyamgx.Matrix, enabling matrix data to be copied directly from raw host or device pointers into AMGX.The main motivation is interoperability with GPU array frameworks such as JAX, CuPy, Numba, or other libraries that can expose raw device pointers but may not provide NumPy-compatible host arrays or
__cuda_array_interface__objects in the form expected by the existingMatrix.upload()method.This PR adds two new methods:
and
These methods mirror the existing vector-level
Vector.upload_raw()functionality, but for CSR matrix data and matrix coefficient replacement.Motivation
pyamgx.Vectoralready supports uploading from raw pointers through:This allows efficient GPU-to-GPU copies from arrays that already live on the device.
However,
pyamgx.Matrixpreviously only exposed:The existing
Matrix.upload()path expects Python array-like objects and performs host-side operations such as calling.max(). This means it does not work with raw GPU buffers or NumbaDeviceNDArrayobjects in all cases.For example, attempting to upload CSR arrays through Numba device arrays can fail with:
This PR enables applications to bypass that limitation by passing explicit raw pointer addresses and matrix metadata directly.
This is particularly useful for workflows where sparse matrix data is already generated or stored on the GPU, for example:
New API
Matrix.upload_raw(...)Copies CSR matrix data into an AMGX matrix directly from raw pointers.
Parameters:
row_ptrs_addr: address of the CSR row pointer bufferint32*nrows + 1col_indices_addr: address of the CSR column index bufferint32*nnzdata_addr: address of the CSR values bufferfloat64*fordDDInnz * block_dimx * block_dimynrows: number of matrix rows, in block unitsnnz: number of nonzero blocksblock_dims: block dimensions, default[1, 1]shape: optional matrix shape(nrows, ncols)The method calls AMGX directly through:
AMGX_matrix_upload_all(...)Matrix.replace_coefficients_raw(...)Replaces matrix coefficients in-place from a raw pointer while preserving the existing sparsity pattern.
This is useful for workflows where the CSR structure is fixed but values change between solves.
The method calls AMGX directly through:
AMGX_matrix_replace_coefficients(...)Example
Validation
This feature was tested with a GPU-resident JAX workflow.
The test constructs CSR arrays on the GPU with JAX:
Then it passes the raw JAX device pointers directly to PyAMGX:
The AMGX solution was compared against SciPy’s host-side sparse solver.
Result for the initial matrix upload:
The coefficient replacement path was also tested using:
Result after coefficient replacement:
Both tests passed.
Notes on memory ownership
These methods do not make PyAMGX alias the external buffers permanently.
They copy from the provided raw pointers into AMGX-owned matrix storage, consistent with AMGX upload semantics.
The pointer memory space must match the matrix mode:
mode="dDDI"expects device pointersmode="hDDI"expects host pointersThe caller is responsible for ensuring that:
For example, with
mode="dDDI":int32int32float64Backward compatibility
This PR is additive.
Existing APIs are unchanged:
Existing user code should continue to work as before.
Why this is useful
This enables efficient integration with modern GPU-native Python workflows, including:
In particular,
replace_coefficients_raw()makes it possible to update matrix values without re-uploading or reconstructing the sparsity structure, which is useful for repeated solves over the same matrix pattern.