Skip to content

Latest commit

 

History

History
283 lines (212 loc) · 7.05 KB

File metadata and controls

283 lines (212 loc) · 7.05 KB

Contributing to MLX-Go

Thank you for your interest in contributing to MLX-Go! This document provides guidelines and instructions for contributing to the project.

Code of Conduct

This project follows the Contributor Covenant Code of Conduct. By participating, you are expected to uphold this code.

Getting Started

Prerequisites

  • Go 1.25 or later
  • CMake 3.24 or later
  • g++ or clang++
  • Xcode Command Line Tools on macOS
  • Git with submodule support

Setting Up Your Development Environment

  1. Fork the repository on GitHub

  2. Clone your fork with submodules:

    git clone --recursive https://github.com/YOUR_USERNAME/mlx_go
    cd mlx_go
  3. Add the upstream remote:

    git remote add upstream https://github.com/guptaaryan16/mlx_go
  4. Build contributor-local MLX dependencies:

    ./scripts/build_local.sh
  5. Verify the contributor build:

    go test -v -tags mlx_vendor ./core
    go test -v -tags mlx_vendor ./nn

If you are only changing Go code and want to test the default install mode, install the native MLX libraries once with the release installer or ./scripts/install.sh, then run the normal go test ./... workflow.

Development Workflow

1. Create a Branch

Always create a new branch for your changes:

git checkout -b feature/your-feature-name

Use descriptive branch names:

  • feature/add-conv2d — New features
  • fix/memory-leak-indexing — Bug fixes
  • docs/improve-readme — Documentation improvements
  • perf/optimize-matmul — Performance improvements

2. Make Your Changes

  • Write clean, idiomatic Go code
  • Follow the existing code style
  • Add tests for new functionality
  • Update documentation as needed

3. Test Your Changes

Run unit tests:

go test -v ./...

Run specific package tests:

go test -v ./core
go test -v ./nn

Run benchmarks:

go test -bench=. -benchtime=5s ./core

Check test coverage:

go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out

4. Format and Lint

Format your code:

gofmt -w .

Run go vet:

go vet ./...

Run golangci-lint (if installed):

golangci-lint run

5. Commit Your Changes

Write clear, descriptive commit messages:

Add Conv2d layer implementation

- Implement Conv2d wrapper around MLX C API
- Add comprehensive tests for various kernel sizes
- Update documentation with usage examples

Closes #42

Commit message guidelines:

  • Use present tense ("Add feature" not "Added feature")
  • First line should be a concise summary (50 chars or less)
  • Add detailed description after a blank line if needed
  • Reference relevant issues (e.g., "Closes #42", "Fixes #123")

6. Push and Create a Pull Request

git push origin feature/your-feature-name

Then create a pull request on GitHub with:

  • Clear title describing the change
  • Description of what changed and why
  • Reference to related issues
  • Screenshots/benchmarks if relevant

Code Style Guidelines

Go Style

  • Follow the Effective Go guidelines
  • Use gofmt for formatting
  • Use meaningful variable and function names
  • Add comments for exported functions following godoc conventions

Documentation Comments

All exported functions should have documentation comments:

// MatMul performs matrix multiplication of two arrays.
//
// The function follows NumPy broadcasting rules. The last two dimensions
// are treated as matrices and multiplied. All other dimensions are broadcast.
//
// Example:
//   a := mx.RandomUniform(0, 1, []int32{10, 20}, mx.Float32)
//   b := mx.RandomUniform(0, 1, []int32{20, 30}, mx.Float32)
//   c := mx.MatMul(a, b)  // Shape: [10, 30]
//
// Options:
//   - WithStream: Specify computation stream
//   - WithDevice: Override default device
func MatMul(a, b Array, opts ...Option) Array {
    // implementation
}

Testing

  • Write table-driven tests where appropriate
  • Test edge cases and error conditions
  • Use descriptive test names: TestMatMul_BroadcastShapes
  • Add benchmarks for performance-critical code

Example test:

func TestTranspose(t *testing.T) {
    tests := []struct {
        name     string
        shape    []int32
        expected []int32
    }{
        {"2D", []int32{3, 4}, []int32{4, 3}},
        {"3D", []int32{2, 3, 4}, []int32{4, 3, 2}},
    }
    
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            arr := mx.Ones(tt.shape, mx.Float32)
            result := mx.Transpose(arr)
            if !reflect.DeepEqual(result.Shape(), tt.expected) {
                t.Errorf("got %v, want %v", result.Shape(), tt.expected)
            }
        })
    }
}

What to Contribute

High Priority

  • Bug fixes — Especially memory leaks or crashes
  • Performance improvements — Benchmarks and optimizations
  • Documentation — Examples, guides, API docs
  • Tests — Improve coverage, add edge cases
  • Core features — Training support, quantization, model implementations

Medium Priority

  • New operations — Additional MLX operations not yet wrapped
  • Utility functions — Helper functions for common tasks
  • Examples — Real-world use cases and demos
  • Benchmarks — Performance comparisons vs other frameworks

Ideas and Discussions

  • Feature proposals — Open an issue to discuss before implementing
  • API improvements — Suggestions for better ergonomics
  • Performance ideas — Profiling results and optimization proposals

Pull Request Process

  1. Ensure all tests pass locally before submitting
  2. Update documentation for any API changes
  3. Add tests for new functionality
  4. Keep PRs focused — One feature/fix per PR
  5. Respond to feedback — Address review comments promptly
  6. Squash commits if requested before merging

PR Review Criteria

Your PR will be reviewed for:

  • Correctness — Does it work as intended?
  • Tests — Is new code adequately tested?
  • Performance — Does it maintain or improve performance?
  • Code quality — Is it readable and maintainable?
  • Documentation — Are changes documented?
  • Compatibility — Does it break existing APIs?

Reporting Issues

Bug Reports

Include:

  • MLX-Go version (commit hash)
  • Go version (go version)
  • macOS version and chip (M1/M2/M3/M4)
  • Minimal code to reproduce the issue
  • Expected vs actual behavior
  • Error messages and stack traces

Feature Requests

Include:

  • Clear use case and motivation
  • Proposed API (if applicable)
  • Alternatives considered
  • Willingness to contribute implementation

Questions?

  • General questions — Open a GitHub Discussion
  • Bug reports — Open an Issue
  • Security issues — Email the maintainers directly

License

By contributing, you agree that your contributions will be licensed under the project's MIT License.


Thank you for helping make MLX-Go better! 🚀