# How to Use MPI for Distributed Parallel Computing in Nelson: A Complete Guide

> Learn to use MPI for distributed parallel computing in Nelson. This guide covers the native MPI module and high-level functions for efficient parallel scripting.

- Repository: [The Nelson Programming Language/nelson](https://github.com/nelson-lang/nelson)
- Tags: tutorial
- Published: 2026-03-08

---

**Nelson provides a native MPI module that wraps the standard MPI C API, allowing you to write distributed parallel scripts using high-level functions like `MPI_Init`, `MPI_Comm_rank`, and `MPI_Send` directly from Nelson code.**

Nelson, the open-source numerical computing environment, includes a built-in **MPI module** for distributed parallel computing that exposes standard Message Passing Interface (MPI) functions directly to Nelson scripts. Located in the `nelson-lang/nelson` repository, this module provides a C++ backend that wraps system MPI libraries (OpenMPI, MPICH, or MS-MPI) while presenting a familiar, high-level API for launching multi-process numerical workloads across clusters or multi-core workstations.

## MPI Module Architecture

The Nelson MPI implementation consists of a thin C++ backend that interfaces with system MPI libraries and a set of Nelson-level wrapper functions.

### C++ Backend Components

The core MPI functionality resides in [`modules/mpi/src/cpp/MPI_helpers.cpp`](https://github.com/nelson-lang/nelson/blob/main/modules/mpi/src/cpp/MPI_helpers.cpp), with declarations in [`modules/mpi/src/include/MPI_helpers.hpp`](https://github.com/nelson-lang/nelson/blob/main/modules/mpi/src/include/MPI_helpers.hpp). These files implement the low-level initialization, error handling, and data packing routines that bridge Nelson's data types with MPI C calls.

**MPI communicator objects** are represented by `MPI_CommHandleObject`, defined in [`modules/mpi/src/include/MPI_CommHandleObject.hpp`](https://github.com/nelson-lang/nelson/blob/main/modules/mpi/src/include/MPI_CommHandleObject.hpp). This class wraps the native `MPI_Comm` handle and manages its lifecycle within the Nelson environment.

### Nelson-Level API

The functions you call from Nelson scripts—such as `MPI_Init`, `MPI_Finalize`, `MPI_Comm_rank`, and `MPI_Comm_size`—are thin wrappers that forward calls to the C++ helpers. These reside in the `modules/mpi` directory, with the launcher script `mpiexec.m` handling process spawning.

## Installation and Build Configuration

MPI support is optional in Nelson and controlled via CMake configuration flags.

### Prerequisites

Install a system MPI library before building Nelson:

- **Ubuntu/Debian**: `sudo apt install libopenmpi-dev`
- **macOS**: `brew install open-mpi`
- **Windows**: Install MS-MPI redistributable

The repository includes dependency installation scripts in `tools/install_dependencies/` (e.g., [`install-ubuntu-24.04.sh`](https://github.com/nelson-lang/nelson/blob/main/install-ubuntu-24.04.sh)) that automate MPI library installation.

### Building with MPI

Enable MPI support by ensuring the `WITHOUT_MPI_MODULE` CMake flag is **OFF** (the default for binary releases):

```bash
cmake -DCMAKE_BUILD_TYPE=Release -DWITHOUT_MPI_MODULE=FALSE <repo_root>
make -j$(nproc)

```

Verify the installation by querying the linked MPI library version:

```matlab
getMpiLibraryVersion()

```

## Basic MPI Usage in Nelson

All Nelson MPI programs follow a standard pattern: initialize the runtime, obtain communicator information, perform work, and finalize.

### Hello World Example

The minimal Nelson MPI script demonstrates rank identification and size queries. This example is available in `modules/mpi/examples/MPI_helloworld.m`:

```matlab
% MPI_helloworld.m
if ~MPI_Initialized()
    MPI_Init();
end

comm = MPI_Comm_object();      % Returns MPI_COMM_WORLD
rank = MPI_Comm_rank(comm);    % My process ID
size = MPI_Comm_size(comm);    % Total number of processes

fprintf('Hello from rank %d of %d\n', rank, size);

if MPI_Initialized()
    MPI_Finalize();
end
exit

```

### Launching MPI Jobs

Use the `mpiexec` helper function to launch scripts across multiple processes:

```matlab
mpiexec('MPI_helloworld.m', 4)

```

This builds and executes the shell command:

```bash
mpiexec -n 4 nelson-cli -q -e "run('MPI_helloworld.m');exit()"

```

## Point-to-Point and Collective Operations

Nelson wraps standard MPI communication patterns for data exchange between processes.

### Send and Receive

Use `MPI_Send` and `MPI_Recv` for point-to-point communication. The following pattern from `modules/mpi/examples/MPI_parallel_sum.m` shows a master-worker reduction:

```matlab
% Worker process sends partial result
if rank ~= 0
    MPI_Send(partial_sum, 0, 1000+rank, comm);
else
    % Master receives from all workers
    total = partial_sum;
    for src = 1:size-1
        total = total + MPI_Recv(src, 1000+src, comm);
    end
end

```

### Collective Operations

For better performance, use collective operations that wrap `MPI_Bcast`, `MPI_Reduce`, `MPI_Allreduce`, and `MPI_Barrier`:

- **Broadcast**: `MPI_Bcast(data, root, comm)` sends data from the root rank to all others.
- **Reduction**: `MPI_Reduce(sendbuf, op, root, comm)` combines values from all ranks to the root.
- **All-Reduce**: `MPI_Allreduce(sendbuf, op, comm)` combines values and distributes the result to all ranks.
- **Barrier**: `MPI_Barrier(comm)` synchronizes all processes at a synchronization point.

## Advanced MPI Features

### Custom Communicators

Create sub-groups of processes using `MPI_Comm_split`. This is useful for hybrid parallelism or dividing a global communicator into row/column groups:

```matlab
% Split MPI_COMM_WORLD into even and odd ranks
world = MPI_Comm_object('MPI_COMM_WORLD');
rank = MPI_Comm_rank(world);
color = mod(rank, 2);  % 0 for even, 1 for odd
newComm = MPI_Comm_split(world, color, rank);

newRank = MPI_Comm_rank(newComm);
fprintf('World rank %d → new rank %d in group %d\n', ...
        rank, newRank, color);

MPI_Comm_free(newComm);

```

### Error Handling

The C++ backend in [`MPI_helpers.cpp`](https://github.com/nelson-lang/nelson/blob/main/MPI_helpers.cpp) installs a custom `MPIErrorHandler` that converts MPI errors into Nelson exceptions. When an MPI call fails, the wrapper throws a standard Nelson `Error` with diagnostic information rather than terminating the process, allowing you to handle failures using Nelson's standard try-catch mechanisms.

## Summary

- **Nelson's MPI module** provides native distributed parallel computing by wrapping standard MPI C APIs in [`modules/mpi/src/cpp/MPI_helpers.cpp`](https://github.com/nelson-lang/nelson/blob/main/modules/mpi/src/cpp/MPI_helpers.cpp) and exposing them as high-level Nelson functions.
- **Build configuration** requires a system MPI library (OpenMPI, MPICH, or MS-MPI) and CMake flag `-DWITHOUT_MPI_MODULE=FALSE` (default enabled).
- **Core workflow** involves `MPI_Init()`, `MPI_Comm_object()` for communicators, `MPI_Comm_rank()`/`MPI_Comm_size()` for process info, communication calls like `MPI_Send()`/`MPI_Recv()` or collectives, and `MPI_Finalize()`.
- **Execution** uses `mpiexec('script.m', n)` which invokes `mpiexec -n n nelson-cli` to launch distributed jobs.
- **Advanced features** include custom communicators via `MPI_Comm_split()` and automatic error handling through the C++ backend.

## Frequently Asked Questions

### How do I check if MPI is available in my Nelson installation?

Call `getMpiLibraryVersion()` in the Nelson console. If MPI is compiled and linked, this function returns a string describing the underlying MPI implementation (e.g., "Open MPI 4.1.4"). If the module is disabled, the function will be undefined.

### Can I use Nelson MPI on Windows?

Yes. Nelson supports MS-MPI on Windows. Install the MS-MPI redistributable and ensure Nelson is built with `-DWITHOUT_MPI_MODULE=FALSE`. The `mpiexec.m` launcher and all MPI functions work identically across Linux, macOS, and Windows platforms.

### What is the difference between MPI_Comm_object and MPI_Comm_split?

`MPI_Comm_object()` returns a handle to a predefined communicator—typically `MPI_COMM_WORLD` containing all launched processes. `MPI_Comm_split()` creates a new communicator by partitioning an existing one into sub-groups based on a color value, allowing you to organize processes into rows, columns, or functional groups for more complex parallel algorithms.

### How does Nelson handle MPI errors?

The C++ backend in [`MPI_helpers.cpp`](https://github.com/nelson-lang/nelson/blob/main/MPI_helpers.cpp) installs a custom `MPIErrorHandler` that intercepts MPI errors and converts them into Nelson exceptions. When an MPI call fails, Nelson throws a standard `Error` with a descriptive message rather than terminating the process or returning an error code, allowing you to handle failures using Nelson's standard try-catch mechanisms.