8个版本

0.3.7 2023年9月8日
0.3.6 2023年8月23日
0.3.4 2023年7月28日

#14 in 仿真

Download history 4/week @ 2024-04-01

每月下载量76次

MIT 许可证

3MB
30K SLoC

C++ 9K SLoC // 0.1% comments C 8K SLoC // 0.2% comments Rust 7K SLoC // 0.0% comments JavaScript 3K SLoC // 0.2% comments CUDA 3K SLoC // 0.1% comments

quest_bind

Test Docs

QuEST v3.5.0的包装器。

量子精确仿真工具包(QuEST)是一个无冗余、追求速度的量子电路仿真器 [1]。它以MIT许可证分发。

如何使用

初始化一个新的二进制crate

cargo new tryme
cd tryme/

quest_bind 添加到项目的依赖项

cargo add quest_bind

现在编写一些代码并将其放入 ./src/main.rs

use quest_bind::*;

fn main() -> Result<(), QuestError> {
    // Initialize QuEST environment and report to screen
    let env = &QuestEnv::new();
    env.report_quest_env();

    // Create a 2-qubit register and report its parameters
    let mut qureg = Qureg::try_new(2, env).expect("cannot allocate new Qureg");
    qureg.report_qureg_params();
    // Initialize |00> state and print out the state to screen
    qureg.init_zero_state();
    qureg.report_state_to_screen(0);

    // Prepare a Bell state `|00> + |11>`: apply Hadamard gate
    // on qubit 0, then NOT on qubit 1, controlled by qubit 0.
    println!("---\nPrepare Bell state: |00> + |11>");
    qureg.hadamard(0).and(qureg.controlled_not(0, 1))?;

    // Measure both qubits
    let outcome0 = qureg.measure(0)?;
    let outcome1 = qureg.measure(1)?;
    println!("Qubit \"0\" measured in state: |{outcome0}>");
    println!("Qubit \"1\" measured in state: |{outcome1}>");

    // Because the state was entangled, the outcomes
    // should always be the same
    if outcome0 == outcome1 {
        println!("They match!");
        Ok(())
    } else {
        panic!("qubits in Bell state should be perfectly correlated");
    }

    // At this point both `qureg` and `env` are dropped and
    // the allocated memory is freed.
}

文档可在 线上 以及本地找到

cargo doc --open

最后,编译并运行程序

cargo run

你应该能看到类似的内容

EXECUTION ENVIRONMENT:
Running locally on one node
Number of ranks is 1
OpenMP enabled
Number of threads available is 8
Precision: size of qreal is 8 bytes
QUBITS:
Number of qubits is 2.
Number of amps is 4.
Number of amps per rank is 4.
---
Prepare Bell state: |00> + |11>
Qubit "0" measured in state: |0>
Qubit "1" measured in state: |0>
They match!

分布式和GPU加速模式

可以通过设置适当的特性标志在 quest_bind 中启用QuEST对MPI和GPU加速计算的支持。要启用QuEST的MPI模式,设置quest_bindmpi特性。只需编辑二进制crate的Cargo.toml

[package]
name = "tryme"
version = "0.1.0"
edition = "2021"

[dependencies]
quest_bind = { features = ["mpi"] }

现在,如果你再次编译并运行上述程序,输出应该是

EXECUTION ENVIRONMENT:
Running distributed (MPI) version
Number of ranks is 1
...

特性 "gpu" 启用GPU加速模式。这两个特性是互斥的,如果同时设置了这两个标志,则特性 "mpi" 优先。

测试

要为此库运行单元测试,首先将QuEST源代码作为子模块一起克隆仓库

git clone --recurse-submodules https://github.com/marek-miller/quest_bind.git
cd quest_bind

然后运行

cargo test

请注意,quest_bind 不会运行 QuEST 的测试套件,也不会检查 QuEST 的正确性。这里的测试旨在检查是否正确调用了C API,以及Rust的类型是否安全地在FFI边界之间传递。

如果您想以单精度浮点模式运行测试套件,请确保构建脚本使用正确的类型定义重新编译 libQuEST.so

cargo clean
cargo test --features=f32

默认情况下,quest_bind 使用Rust的双精度浮点类型:f64。请参阅下文中的 数值类型 部分。

您还可以通过运行,例如,来尝试可用的示例。

 cargo run --release --example grovers_search

要查看所有可用示例的列表,请尝试

cargo run --example

性能说明

在典型情况下,当CPU使用率主要由数值计算主导而不是API调用时,使用QuEST例程直接调用程序与使用quest_bind的类似应用程序之间应该没有可察觉的性能差异。但是,请记住,通过使用“发布”配置文件编译您的代码来启用对quest_bindQuEST的优化。

cargo run --release

异常处理

在失败的情况下,QuEST通过用户可配置的全局invalidQuESTInputError()抛出异常。默认情况下,此函数会打印错误消息并中止,这在大型分布式设置中是有问题的。

我们选择通过重新实现invalidQuESTInputError()来捕获所有异常,使用Rust的panic机制来展开堆栈。

此外,QuEST报告的所有错误消息都记录为错误。要查看它们,请在您的crate中添加一个记录器,例如

cargo add env_logger

然后在您的应用程序中启用日志记录

fn main()  {
    env_logger::init();
    // (...)
}

并运行

RUST_LOG=info cargo run

有关Rust中的日志记录的更多信息,请参阅log crate

QuestError类型不包含API调用在失败时返回的(可能是格式错误的)数据。只有成功的调用才能达到库用户。这是根据QuEST文档的指南故意为之的。

[失败时] 用户必须确保触发的API调用不会继续(例如,用户退出或抛出异常),否则QuEST将继续使用有效的[ sic! ]输入并可能触发段错误。

有关更多信息,请参阅Quest API

数值类型

目前,quest_bind使用的数值类型与QuEST在x86_64上使用的C类型完全匹配。这是一个安全但不太可移植的策略。我们直接将Rust类型传递给QuEST而不进行转换,假设以下类型定义

pub type c_float = f32;
pub type c_double = f64;
pub type c_int = i32;
pub type c_longlong = i64;
pub type c_ulong = u64;

这应该适用于许多不同的架构。如果您的系统使用稍微不同的数值类型,quest_bind将无法编译,除了手动更改源代码之外,您几乎无能为力。

要检查Rust安装中定义的C类型,请参阅Rust标准库中模块std::ffi的本地文档。

rustup doc

贡献

如果您想为quest_bind做出贡献,这里有一些需要了解的事项。

  • Rust代码库的格式与./rustfmt.toml中的设置一致。我们启用了rustfmt的一些不稳定功能。要正确格式化您的补丁,您将需要Rust编译器的夜间版本。在打开pull请求之前,通过运行以下命令从代码中删除lint:

    just lint
    

依赖项