First off, thank you for considering contributing to rv-sparse.
This project is under active development. Our goal is to build a clean sparse linear algebra library with a stable public API, while also providing a separate space for experimental kernels, benchmarks, and architecture-specific optimizations.
Please follow the guidelines below when proposing changes, adding new features, optimizing kernels, or submitting benchmark results.
We follow a strict feature-branch workflow.
Do not commit directly to main.
All changes should be submitted through Pull Requests.
Before starting new work, make sure your local repository is up to date.
If you are working directly from the main repository:
git checkout main
git pull origin mainIf you are working from a fork:
git fetch upstream
git checkout main
git merge upstream/main
git push origin mainCreate a new branch for your work.
Use the following naming convention:
dev_YOUR_FEATURE
Keep the feature name concise but descriptive.
Examples:
git checkout -b dev_rvv_intrinsics
git checkout -b dev_spgemm_i8_kernel
git checkout -b dev_spmv_optimization
git checkout -b dev_benchmark_harness
git checkout -b dev_update_docsMaintainers may also use internal integration or review branches such as:
experiment/raw-kernels-rvv
review/<contributor-name>-<topic>
Examples:
experiment/raw-kernels-rvv
review/name-benchmarks
review/name2-rvv-kernel
Use small, logical commits. Each commit should represent one clear change.
We recommend Conventional Commits:
feat: add a new feature
perf: improve performance
fix: fix a bug
docs: update documentation
test: add or update tests
bench: add or update benchmarks
refactor: restructure code without changing behavior
Examples:
git commit -m "perf: add experimental RVV INT8 row accumulation kernel"
git commit -m "test: compare RVV kernel against scalar reference"
git commit -m "bench: add raw SpGEMM benchmark harness"
git commit -m "docs: update raw kernel experiment README"Avoid vague commit messages such as:
update
fix stuff
changes
work
Push your development branch to your fork or to the appropriate remote repository:
git push -u origin dev_YOUR_FEATUREExample:
git push -u origin dev_rvv_intrinsicsOpen a Pull Request from your development branch.
The PR description should include:
- Motivation: why this change is needed.
- Implementation details: brief explanation of the technical approach.
- Testing commands: exact commands used to build and test.
- Benchmark results, if performance is affected.
- Whether the public API is changed.
- Target architecture or emulator used, if applicable.
For stable library changes, open the PR against:
main
For experimental raw kernels, benchmarks, or early optimization work, open the PR against the active experimental branch when available:
experiment/raw-kernels-rvv
Do not target main for experimental kernels unless they are already validated and approved for integration.
The public API must remain stable.
Public API files include:
include/rv_sparse.h
include/rv_sparse_types.h
Do not modify the public API for experimental kernels unless the change has been discussed and approved.
Experimental kernels should first be developed outside the public API path.
Experimental kernels should be developed in:
experiments/raw_kernels/
This directory is used for raw kernels, correctness tests, early benchmarking, and architecture-specific experiments.
Experimental kernels must not be exposed through the public dispatcher until they are:
- Correct.
- Tested against a scalar reference.
- Validated on native builds.
- Validated on RISC-V/QEMU when applicable.
- Benchmarked.
- Reviewed.
Only selected and validated kernels should later be migrated into:
src/kernels/spgemm/
and connected through the wrapper and dispatcher layers.
The initial experimental optimization target is:
INT8 x INT8 -> INT32
This target is used to evaluate:
scalar kernels
unrolled kernels
GCC auto-vectorized kernels
RISC-V Vector intrinsics kernels
RISC-V Vector kernels should use the C intrinsics interface through:
#include <riscv_vector.h>RVV-specific code should be guarded with appropriate compile-time checks when needed.
Example:
#if defined(__riscv_vector)
#include <riscv_vector.h>
#endifIntrinsic-heavy code should include comments explaining:
- The vector type used.
- The widening or narrowing operation.
- The memory access pattern.
- Any assumptions about alignment or index validity.
- Any limitations, such as duplicate column handling.
The main library follows a layered structure:
Public API
Dispatch layer
Internal wrapper layer
Raw kernel layer
Raw kernels should use pointer-based interfaces and should not depend directly on public matrix structs unless they are part of the integration layer.
For experimental kernels, prefer the following structure:
experiments/raw_kernels/
├── kernels/
├── tests/
├── benchmarks/
└── README.md
Every new kernel or backend should include a correctness test.
Tests should compare against a known reference implementation whenever possible.
For main library tests, use:
tests/
For experimental kernels, use:
experiments/raw_kernels/tests/
Before opening a Pull Request, run:
make clean
make
make testFor RISC-V/QEMU validation, run:
make clean
make test TARGET_ARCH=riscvFor experimental raw kernels, run from the experimental directory:
cd experiments/raw_kernels
make clean
make test
make clean
make test TARGET_ARCH=riscvBenchmark contributions must be reproducible.
A benchmark contribution should include:
- Source code.
- A README or usage instructions.
- The exact command used to run the benchmark.
- The metrics reported.
- The tested architecture, compiler, and flags.
- Whether the benchmark was run on native hardware, QEMU, or another emulator.
Useful metrics include:
kernel name
dtype
matrix size
density
nnz(A)
nnz(B)
nnz(C)
execution time
GOPS or GFLOPS
speedup against scalar baseline
memory footprint
correctness status
compiler version
compile flags
target architecture
For INT8 kernels, use GOPS when appropriate.
For FP32 kernels, use GFLOPS when appropriate.
Do not commit large datasets, generated binaries, or heavy raw benchmark outputs unless explicitly approved.
Do not commit generated artifacts such as:
bin/
obj/
lib/
build/
*.o
*.a
*.so
*.exe
*.out
Do not commit local personal notes such as:
docs/personal_notes.md
Do not commit local benchmark executables such as:
bench_f32
bench_i8
bench_unroll4
Large datasets and raw benchmark outputs should be avoided unless explicitly approved.
Do not copy another contributor's work into your own branch manually.
To preserve authorship, use Pull Requests, remotes, or merges from the original contributor branch.
When reviewing another contributor's work, create a review branch:
git fetch <remote-name>
git checkout -b review/<contributor-name>-<topic> <remote-name>/<branch>Example:
git fetch name
git checkout -b review/name-benchmarks name/mainAfter reviewing and testing, merge only if the contribution is correct, clean, and properly attributed.
Before requesting a review, make sure:
- I have followed the
dev_YOUR_FEATUREbranch naming convention. - My code compiles without warnings on the target architecture.
- I have run the relevant correctness tests.
- I have run RISC-V/QEMU tests when applicable.
- I have compared new kernels against a scalar reference.
- I have included benchmark results if performance is affected.
- I have documented the benchmark commands and environment.
- I have performed a self-review of my own code.
- I have commented low-level or hard-to-understand code.
- I have updated README files or documentation when applicable.
- I have not committed generated artifacts, binaries, build folders, or large datasets.
- I have preserved authorship for external contributions.
Once your Pull Request is open, assign it to a maintainer or request review from the appropriate contributor.
The review will check:
- Correctness.
- Code organization.
- API stability.
- Performance impact.
- Benchmark reproducibility.
- RISC-V compatibility when applicable.
- Authorship and commit cleanliness.
Requested changes should be added as new commits to the same development branch.
Once approved, the maintainer may merge using either:
Squash and merge
for small feature branches, or:
Create a merge commit
when preserving individual commit authorship is important.
Experimental kernels should not be integrated into the public API immediately.
The recommended path is:
experiments/raw_kernels/
benchmark and compare
select best kernel
migrate to src/kernels/spgemm/
add wrapper
add dispatcher support
add public tests
update documentation
open PR to main
Only the best validated kernel should be migrated to the main backend.
By contributing, you agree that your contributions are provided under the same license as the project.