MLX C API

repository·main·Indexed 42 days ago

https://github.com/ml-explore/mlx-c

A C API for the MLX array framework designed for machine learning research and experimentation on Apple silicon. MLX C can be used as a standalone library for writing ML code in C or as a bridge to provide bindings for other languages, such as Swift.

Tokens
1.6K
Snippets
10
Records
14
Agent score
54%

What's inside MLX C

  1. Overview of MLX C

    main

    MLX C is a C API for the MLX array framework. It is designed for machine learning on Apple silicon, enabling research and experimentation directly in the C language.

    MLX C serves two primary purposes:

    1. Standalone usage: Writing machine learning code directly in C.
    2. Language Bridge: Acting as a binding layer for other languages. For example, the mlx-swift package utilizes MLX C to provide Swift bindings for MLX.
  2. Manage memory for Vectors of Arrays

    main

    MLX C provides specialized vector types for grouping arrays:

    • mlx_vector_array: A vector that can hold multiple mlx_array objects.
    • mlx_vector_vector_array: A vector that can hold multiple mlx_vector_array objects.

    Memory Rule: An array added to a mlx_vector_array will remain alive until the vector itself is destroyed using mlx_vector_array_free().

  3. Use closures for function transformations

    main

    MLX C supports function transformations (like gradients or compilation) using mlx_closure. A closure encapsulates a C function pointer and optional payloads (upvalues).

    Closures are treated as standard MLX C objects: they must be managed according to the same memory rules and released using mlx_closure_free(). Transformations are applied to closures and may return new closures.

  4. Core MLX C objects and memory management

    main

    MLX C operates using several opaque C struct objects. Most objects follow a strict lifecycle: they must be created with a constructor function (e.g., mlx_array_new()) and must be manually released with a corresponding free function (e.g., mlx_array_free()). There must always be exactly one free call for every new call.

    Key compute-related objects include:

    • mlx_array: The primary object holding data for computations.
    • mlx_device: Defines the compute unit (e.g., CPU or GPU).
    • mlx_stream: Ingests and executes array operations on a specific device.

    Other data-holding objects include mlx_string, mlx_vector, mlx_map, mlx_closure, and mlx_distributed_group.

    mlx_stream stream = mlx_default_gpu_stream_new();
    mlx_array a = mlx_array_new_float(1.0);
    mlx_array b = mlx_array_new_float(1.0);
    mlx_array_add(&b, a, b, stream); // b now holds a+b=2
    mlx_array_set(&a, b);           // a now holds 3
    mlx_array_free(a);
    mlx_array_free(b);
  5. How arrays and streams interact

    main

    In MLX C, arrays are not tied to a specific device. Instead, computations are scheduled on a mlx_stream, which is associated with a mlx_device.

    To use default streams, you can use the predefined constants:

    • MLX_CPU_STREAM for the default CPU stream.
    • MLX_GPU_STREAM for the default GPU stream.

    Note on Lazy Evaluation: MLX is a lazy framework. Data obtained via mlx_array_data_*() functions is only guaranteed to be valid after mlx_eval() has been called to trigger the computation.

  6. Push documentation to GitHub Pages

    main

    To deploy the documentation to GitHub Pages, follow these steps:

    1. Switch to the gh-pages branch:
      git switch gh-pages
    2. Build the documentation (using the build commands).
    3. Force add the build/html directory to the repository:
      git add -f build/html
    4. Commit and push the changes to the gh-pages branch.
    git switch gh-pages
    git add -f build/html
  7. Install and build MLX C

    main

    MLX C requires CMake to build. You can install CMake using Homebrew. Once installed, use CMake to configure the build directory and then build the project using multiple cores for efficiency.

    # Install CMake
    brew install cmake
    
    # Configure the build directory
    cmake -B build -DCMAKE_BUILD_TYPE=Release
    
    # Build the project
    cmake --build build -j
  8. Build and Install MLX C

    main

    To build MLX C, use CMake to configure the build directory and then compile the project. The build process automatically fetches, compiles, and links the core MLX repository before compiling the C API.

    cmake -B build -DCMAKE_BUILD_TYPE=Release
    cmake --build build -j
  9. Setup the documentation build environment

    main

    To build the project documentation, you need to install Doxygen and the required Python dependencies.

    1. Install Doxygen using Homebrew:
      brew install doxygen
    2. Install the necessary Python packages from the requirements file:
      pip install -r requirements.txt
    brew install doxygen
    
    pip install -r requirements.txt
  10. View the built documentation locally

    main

    After building the documentation, you can view it by starting a local HTTP server in the mlx-c/docs/ directory.

    1. Run the server:
      python -m http.server <port>
    2. Open your browser and navigate to http://localhost:<port>.
    python -m http.server <port>