13 个不稳定版本 (5 个破坏性更新)

0.8.0 2024 年 5 月 3 日
0.7.0 2023 年 10 月 21 日
0.6.0 2022 年 8 月 5 日
0.5.4 2018 年 3 月 27 日
0.2.0 2015 年 11 月 10 日

#28并发 中排名

Download history 546/week @ 2024-04-30 473/week @ 2024-05-07 213/week @ 2024-05-14 283/week @ 2024-05-21 174/week @ 2024-05-28 135/week @ 2024-06-04 170/week @ 2024-06-11 371/week @ 2024-06-18 179/week @ 2024-06-25 50/week @ 2024-07-02 197/week @ 2024-07-09 149/week @ 2024-07-16 288/week @ 2024-07-23 156/week @ 2024-07-30 204/week @ 2024-08-06 230/week @ 2024-08-13

911 每月下载次数
用于 9 crates

MIT/Apache

300KB
5.5K SLoC

Rust 的 MPI 绑定

GitHub Actions Documentation Crates.io License: Apache License 2.0 or MIT

消息传递接口(MPI)是一种用于消息传递风格并发库的规范。MPI 的实现通常用于在高性能计算系统上结构化并行计算。MPI 规范描述了 C 编程语言(及其通过 C++)以及 Fortran 编程语言的绑定。这个库试图填补进入更 Rust 风格世界的差距。

需求

符合 MPI-3.1 的 C 语言接口实现。目前 rsmpi 正在使用这些实现进行测试

用户还使用这些 MPI 实现取得了成功,但在 CI 中未进行测试

为了在使用任何 MPI 实现时提高 rsmpi 成功的可能性,您必须拥有以下之一

  • MPI_PKG_CONFIG 导出为您的实现中 pkg-config 的名称或路径
    • rsmpi 在 Cray 环境中自动使用 CRAY_MPICH_DIR,因此上述设置无需设置
    • 默认情况下将尝试使用 mpichompi 作为最后的手段
    • 提示:使用类似 pkg-config --cflags ---libs mpich 的命令进行测试
  • 该实现提供了一个 C 编译器包装器 mpicc
    • 导出 MPICC=/path/to/mpicc 来指定完整路径
    • 否则在 $PATH

      中尝试 mpicc
    • mpicc -show 应该打印用于调用包装的 C 编译器的完整命令行,使用与 gcc 兼容的语法(例如,-lmpi-I/usr/local/include,...)
  • 在 Windows 上,应设置变量 MSMPI_INC 以及 MSMPI_LIB32MSMPI_LIB64

由于 MPI 标准未指定 C API 的某些细节(是否使用预处理器宏或原生 C 构造来实现某些常量和函数,以及大多数类型的细节等),rsmpi 采用两步方法来生成功能性的底层绑定。

首先,它使用一个用 C 编写的薄静态库(参见 rsmpi.hrsmpi.c),该库试图捕获未指定的标识符并将它们以固定的 C API 形式重新导出。该库使用 build.rs 并使用 gcc crate 构建。

其次,为了生成针对每个 MPI 实现定制的 FFI 定义,rsmpi 使用 rust-bindgen,它需要 libclang。有关更多信息,请参阅 bindgen 项目页面

此外,rsmpi 使用 libffi crate,它安装了依赖于某些构建工具的本地 libffi。有关更多信息,请参阅 libffi 项目页面

使用方法

mpi crate 添加到您的 Cargo.toml 中的依赖项

# "features" is optional
[dependencies]
mpi = { version = "0.8.0", features = ["user-operations", "derive"] }

然后在您的程序中使用它,如下所示


use mpi::request::WaitGuard;
use mpi::traits::*;

fn main() {
    let universe = mpi::initialize().unwrap();
    let world = universe.world();
    let size = world.size();
    let rank = world.rank();

    let next_rank = (rank + 1) % size;
    let previous_rank = (rank - 1 + size) % size;

    let msg = vec![rank, 2 * rank, 4 * rank];
    mpi::request::scope(|scope| {
        let _sreq = WaitGuard::from(
            world
                .process_at_rank(next_rank)
                .immediate_send(scope, &msg[..]),
        );

        let (msg, status) = world.any_process().receive_vec();

        println!(
            "Process {} got message {:?}.\nStatus is: {:?}",
            rank, msg, status
        );
        let x = status.source_rank();
        assert_eq!(x, previous_rank);
        assert_eq!(vec![x, 2 * x, 4 * x], msg);

        let root_rank = 0;
        let root_process = world.process_at_rank(root_rank);

        let mut a;
        if world.rank() == root_rank {
            a = vec![2, 4, 8, 16];
            println!("Root broadcasting value: {:?}.", &a[..]);
        } else {
            a = vec![0; 4];
        }
        root_process.broadcast_into(&mut a[..]);
        println!("Rank {} received value: {:?}.", world.rank(), &a[..]);
        assert_eq!(&a[..], &[2, 4, 8, 16]);
    });
}

功能

这些绑定遵循 MPI 3.1 规范。

目前支持

  • 组、上下文、通信器:
    • 第 6 节中的组和(内部)通信器管理基本完成。
    • 无互连通信器
    • 无进程拓扑结构
  • 点对点通信:
    • 标准、缓冲、同步和就绪模式发送,有阻塞和非阻塞变体
    • 接收,有阻塞和非阻塞变体
    • 发送-接收
    • 探测
    • 匹配探测/接收
  • 集体通信:
    • 屏障
    • 广播
    • (全部)归约
    • 分散
    • 全部对全部
    • 可变计数操作
    • 归约/扫描
    • 阻塞和非阻塞变体
  • 数据类型:在 Rust 类型与 MPI 基本类型以及可以作为缓冲区视图的自定义 MPI 数据类型之间进行桥接。

不支持(尚不支持)

  • 单方面通信(RMA)
  • MPI 并行 I/O
  • 成千上万的小事情

可选 Cargo 功能

您可以在 cargo 清单中启用这些可选功能。请参阅上面的 使用 部分。

user-operations 启用捕获 lambda 和在 UserOperation 中安全创建。此功能需要 libffi 系统库,该库不是所有系统都默认可用的。

let mut h = 0;
comm.all_reduce_into(
    &(rank + 1),
    &mut h,
    &UserOperation::commutative(|x, y| {
        let x: &[Rank] = x.downcast().unwrap();
        let y: &mut [Rank] = y.downcast().unwrap();
        for (&x_i, y_i) in x.iter().zip(y) {
            *y_i += x_i;
        }
    }),
);

derive 允许启用 Equivalence 派生宏,这使得发送结构体时无需担心填充问题,并允许结构体之间进行任意数据类型的匹配,这些结构体具有相同的字段顺序但不同的布局。

#[derive(Equivalence)]
struct MyProgramOpts {
    name: [u8; 100],
    num_cycles: u32,
    material_properties: [f64; 20],
}

文档

rsmpi 的每个公共项至少应与一段文档相关联。文档可以通过以下方式生成:

cargo doc

最新版本 rsmpi 的文档在 GitHub Pages 上托管。

示例

请参阅 examples/ 目录下的文件。这些示例还充当 集成测试

Python 集成

可以使用 rsmpi 与由 mpi4py 提供的通信器一起使用。一个展示此功能的示例项目是 mpi4py_with_rsmpi

许可证

许可证为以下之一:

任选其一。

贡献

除非你明确说明,否则任何有意提交以包含在你所定义的工作中的贡献,根据 Apache-2.0 许可证,应作为上述双重许可,不附加任何额外条款或条件。

依赖关系

~0.4–3.5MB
~72K SLoC