Contributing to Ztorch
Thank you for your interest in contributing to Ztorch!
Code of Conduct
Be respectful, constructive, and professional. We're building something useful together.
Development Philosophy
Ztorch follows Tiger Style development:
- Safety first
- Benchmarked performance
- Clean developer experience
- Zero technical debt
See tiger-style.md for full details.
Getting Started
Prerequisites
- Zig 0.15.x (latest)
- Git
- (Optional) CUDA Toolkit 12.0+ for GPU development
- (Optional) ROCm 5.0+ for AMD GPU development
Setup
# Clone
git clone https://github.com/mattneel/ztorch.git
cd ztorch
# Build
zig build
# Run tests
zig build test
# Run benchmarks
zig build bench
Contribution Workflow
1. Find or Create an Issue
- Check existing issues first
- For new features, discuss in an issue before implementing
- For bugs, provide minimal reproduction
2. Fork and Branch
git checkout -b feature/add-conv2d
# or
git checkout -b fix/matmul-gradient-bug
3. Implement
TDD Workflow:
- Write test first (red)
- Implement minimal code (green)
- Refactor
- Benchmark if performance-sensitive
Example: Adding a New Operation
// 1. Write test (test/ops/new_op_test.zig)
test "new_op: known result" {
const input = [_]f32{ 1, 2, 3 };
var output: [3]f32 = undefined;
ztorch.ops.new_op_cpu(&input, &output);
try testing.expectEqual(@as(f32, expected), output[0]);
}
// 2. Implement (src/ops/cpu/new_op.zig)
pub fn new_op_cpu(input: []const f32, output: []f32) void {
for (input, output) |in, *out| {
out.* = /* implementation */;
}
}
// 3. Add gradient test
test "new_op: gradient check" {
// ... numerical gradient verification
}
// 4. Benchmark
bench "new_op: 1M elements" {
// ... measure performance
}
// 5. Add to public API (src/ztorch.zig)
pub const new_op = ops.new_op_cpu;
4. Test
# Run all tests
zig build test
# Run specific test
zig build test -- test/ops/new_op_test.zig
# Check formatting
zig fmt --check .
# Fix formatting
zig fmt .
5. Benchmark
If your change affects performance:
# Run benchmarks
zig build bench
# Compare against main
git checkout main
zig build bench --save-baseline main.json
git checkout your-branch
zig build bench --compare main.json
Include benchmark results in your PR description.
6. Document
- Add docstrings to public functions
- Update README if adding features
- Update relevant docs/ files
- Add examples/ if appropriate
7. Commit
git add .
git commit -m "feat: add conv2d operation
- Implement CPU scalar version
- Add unit tests and gradient checks
- Benchmark: 2.3 GFLOPS on 32x32 kernels
- Refs #42"
Commit Message Format:
<type>: <subject>
<body>
<footer>
Types:
feat: New featurefix: Bug fixperf: Performance improvementtest: Adding testsdocs: Documentation onlyrefactor: Code change that neither fixes bug nor adds featurechore: Maintenance tasks
8. Push and PR
git push origin feature/add-conv2d
Create PR with:
- Clear description of what and why
- Link to related issue
- Test results
- Benchmark results (if applicable)
- Breaking changes (if any)
PR Review Process
- Automated Checks: CI must pass (all platforms)
- Code Review: Maintainer reviews code
- Discussion: Address feedback
- Approval: Maintainer approves
- Merge: Maintainer merges
Review Timeline:
- Initial response: 1-3 days
- Complete review: 1-2 weeks (depending on complexity)
What We're Looking For
High Priority
- Core operations (MatMul, Conv, Attention, etc.)
- Backend implementations (CUDA, ROCm, Vulkan)
- Performance optimizations (with benchmarks!)
- Bug fixes
- Test coverage improvements
- Documentation improvements
Medium Priority
- Additional frontends (PyTorch, TensorFlow import)
- Serialization/deserialization
- Quantization support
- More activation functions
Low Priority
- Minor refactors
- Code style changes
- Non-critical features
Guidelines
Code Style
Follow Tiger Style principles:
Do:
// Clear names
pub fn matmul_cpu_scalar(a: Tensor, b: Tensor) Tensor { ... }
// Explicit sizes
const n: u32 = 1024;
// Fixed limits
const MAX_BATCH_SIZE: usize = 1024;
for (0..@min(batch_size, MAX_BATCH_SIZE)) |i| { ... }
// Simple control flow
if (condition) {
simple_case();
} else {
other_case();
}
Don't:
// Vague names
pub fn mm(a: T, b: T) T { ... }
// Architecture-dependent sizes
const n: usize = 1024;
// Unbounded loops
while (has_more()) { ... }
// Complex nested logic
if (a) {
if (b) {
if (c) { ... }
}
}
Testing
Every PR must include:
- Unit tests for new functionality
- Gradient checks for differentiable ops
- Backend parity tests for GPU implementations
- Benchmarks for performance-sensitive code
Test Coverage:
- Minimum 90% line coverage
- All error paths tested
- Edge cases covered
Documentation
/// Matrix multiplication: C = A @ B
///
/// Computes the matrix product of two 2D tensors.
///
/// # Arguments
/// * `a` - Left matrix of shape (M, K)
/// * `b` - Right matrix of shape (K, N)
///
/// # Returns
/// Result matrix of shape (M, N)
///
/// # Example
/// ```
/// const a = try Tensor.randn(.{32, 64});
/// const b = try Tensor.randn(.{64, 128});
/// const c = try matmul(a, b);
/// ```
pub fn matmul(a: Tensor, b: Tensor) !Tensor {
// ...
}
Performance
- Always napkin math first
- Benchmark before and after
- Document expected vs actual performance
- Prove optimizations with numbers
Safety
- No undefined behavior
- Explicit error handling
- Fixed resource limits
- Assertions for invariants
Common Issues
CI Failures
"Test failed on Windows"
- Windows has different line endings
- Use
\nconsistently - Run tests locally on Windows if possible
"Formatting check failed"
zig fmt .
git add .
git commit --amend --no-edit
git push --force
"Benchmark regression"
- Investigate why performance decreased
- Either fix the regression or justify it
- Update baseline if intentional
Review Feedback
"This needs tests"
- Add missing test cases
- Ensure coverage is adequate
"Can you add a benchmark?"
- Add benchmark for the new code
- Compare against baseline
"This violates Tiger Style"
- Review tiger-style.md
- Refactor accordingly
Getting Help
- Questions: Open a discussion
- Bugs: Open an issue
- Features: Open an issue for discussion first
- Chat: (Discord/Matrix link if available)
Recognition
Contributors are recognized in:
- CONTRIBUTORS.md file
- Release notes
- Git history
Significant contributions may earn you commit access.
License
By contributing, you agree that your contributions will be licensed under the same license as the project (Apache 2.0 or MIT).