3 个版本

0.1.2 2020 年 2 月 22 日
0.1.1 2020 年 2 月 22 日
0.1.0 2020 年 2 月 20 日

#182 in 图形 API

自定义许可证

155KB
3.5K SLoC

filum

使用 Rust 和 Vulkan 的简易 GPGPU。

提供简单易用的接口来执行一些实际并行执行的计算。

示例

计算斐波那契数列

extern crate filum;
use filum::{Context, BufferViewBuilder, PipelineBuilder};

fn main() {
    // setup data to calculate fibonacci sequence
    let num_elements = 32usize;
    let mut v: Vec<u32> = (0..num_elements as u32).collect();
    // filum automatically selects one from available GPUs. 
    // context contains information of the GPU.
    let context = Context::new().unwrap();
    // allocates contiguous memory of u32 with the number of `num_elements`.
    let buffer_view = BufferViewBuilder::new(&context)
        .bind_array::<u32>(num_elements)
        .build()
        .unwrap();
    // loads a compute shader from the specified file path
    // and associates it to the buffer.
    let pipeline = PipelineBuilder::new(buffer_view.buffer())
        .shader("data/fibonacci.comp.spv")
        .build()
        .unwrap();
    // in order to transfer our data to the GPU, 
    // gets a reference which corresponds to the binding point that
    // indicates the location of the array of u32 stored on the GPU.
    let binding = buffer_view.binding();
    // sends data to the GPU
    binding.update_array_copying(&v);
    // runs the computation specifying how many invocations of 
    // the shader performed.
    pipeline.dispatch(num_elements);
    // retrieves back data from the GPU
    binding.fetch_array_copying(&mut v);
    println!("{:?}", v);
}
// outputs
// [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269]

特性

  • 高级接口
  • 轻量级
  • 类型安全的输入输出缓冲区访问
  • Cargo 支持
  • Vulkan 计算着色器
    • 多个绑定点
    • 多个计算着色器
    • 推送常数
    • 专用常数

快速入门

确保在您的系统上运行 vulkaninfo 命令,并且 Vulkan 版本匹配 1.1.x 或更高。

运行示例项目

git clone https://github.com/ogukei/filum-example
cd filum-example/fibonacci
cargo run --release

如果您想从头开始,请更新 Cargo.toml。

[dependencies]
filum = "*"

另一个示例

连通组件标记,实现了以下算法。

大规模图像中对象识别的并行方法
https://www.academia.edu/29842500/

实际的实现可在 filum-example 获得

#[macro_use]
extern crate filum;
use filum::{Context, BufferViewBuilder, PipelineBuilder, DispatchBuilder};

fn main() {
    let dim = (8usize, 8usize);
    let table: Vec<i32> = vec![
        0, 0, 0, 0, 0, 0, 0, 0,
        0, 1, 1, 0, 1, 1, 1, 0,
        0, 1, 1, 0, 1, 1, 1, 0,
        1, 1, 1, 0, 0, 0, 0, 1,
        0, 1, 1, 1, 0, 0, 0, 1,
        0, 0, 0, 0, 0, 1, 1, 0,
        0, 1, 0, 1, 1, 1, 1, 0,
        0, 1, 1, 1, 0, 0, 0, 0,
    ];
    let mut table: Vec<i32> = table.into_iter()
        .enumerate()
        .map(|(i, v)| if v == 0 { -1i32 } else { i as i32 })
        .collect();
    let len = table.len();
    assert_eq!(len, dim.0 * dim.1);
    assert!(dim.0.is_power_of_two());
    let context = Context::new().unwrap();
    let buffer_view = BufferViewBuilder::new(&context)
        .bind_array::<i32>(len)
        .build()
        .unwrap();
    let buffer = buffer_view.buffer();
    let column = PipelineBuilder::new(buffer)
        .shader("data/column.comp.spv")
        .specialization(constants!(dim.0 as u32, dim.1 as u32))
        .build()
        .unwrap();
    let merge = PipelineBuilder::new(buffer)
        .shader("data/merge.comp.spv")
        .specialization(constants!(dim.0 as u32, dim.1 as u32))
        .build()
        .unwrap();
    let relabel = PipelineBuilder::new(buffer)
        .shader("data/relabel.comp.spv")
        .build()
        .unwrap();
    let binding = buffer_view.binding();
    binding.update_array_copying(&table);
    // column
    column.dispatch(dim.0);
    // merge
    {
        let mut step_index = 0;
        let mut n = dim.0 >> 1;
        while n != 0 {
            let dispatch = DispatchBuilder::new(&merge)
                .workgroup_count(n, 1, 1)
                .push_constants(constants!(step_index as u32))
                .build()
                .unwrap();
            dispatch.dispatch();
            n = n >> 1;
            step_index += 1;
        }
    }
    // relabel
    relabel.dispatch(len);
    binding.fetch_array_copying(&mut table);
    // output
    dump(&table, dim.0);
}
// outputs
/*
 -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 
 -1,   9,   9,  -1,  12,  12,  12,  -1, 
 -1,   9,   9,  -1,  12,  12,  12,  -1, 
  9,   9,   9,  -1,  -1,  -1,  -1,  31, 
 -1,   9,   9,   9,  -1,  -1,  -1,  31, 
 -1,  -1,  -1,  -1,  -1,  45,  45,  -1, 
 -1,  45,  -1,  45,  45,  45,  45,  -1, 
 -1,  45,  45,  45,  -1,  -1,  -1,  -1,
*/

性能

连通组件标记 8K 图像

GPU 计算包括与以下环境的内存传输操作耗时 ~210ms

  • OS: Ubuntu 18.04 LTS
  • CPU: Intel(R) Core(TM) i7-3930K CPU @ 3.20GHz
  • GPU: NVIDIA GeForce RTX 2070
结果(已调整大小)
image

Vulkan 标志是 Khronos Group Inc. 的商标。

运行环境

  • 需要 Vulkan 1.1 运行时
  • Vulkan 1.1 兼容的图形驱动程序

要编译 GLSL 计算着色器到 SPIR-V,我们建议使用 Vulkan SDK 进行编译。

入门指南

安装兼容 Vulkan 1.1 的操作系统。强烈推荐 Ubuntu 18.04 LTS,因为其图形驱动程序安装相对简单。

对于 Ubuntu 18.04 LTS 用户,请按照以下步骤进行。其他操作系统用户,请参阅 https://www.lunarg.com/vulkan-sdk/ 的信息,并在您的 Vulkan 设置完成后继续进行第 3 步。

  1. 如果您还没有兼容Vulkan 1.1的图形驱动程序,请运行以下命令:

请确保您的图形卡支持Vulkan 1.1,请检查以下页面。

针对NVIDIA图形卡用户
https://developer.nvidia.com/vulkan-driver

针对AMD图形卡用户
https://gpuopen.com/gaming-product/vulkan/

ubuntu-drivers list
ubuntu-drivers install <recommended-version>

请重新启动您的系统以完成驱动程序的安装。

  1. 如果您还没有安装Vulkan SDK,请运行以下命令
sudo apt update
sudo apt install vulkan-sdk
  1. 运行以下命令以检查您的设置是否正确完成
vulkaninfo
  1. 克隆我们的示例项目
git clone https://github.com/ogukei/filum-example
  1. 运行示例项目
cd filum-example
cd fibonacci
cargo run --release
  1. 使用 glslc 编译GLSL计算着色器
cd filum-example
cd fibonacci
make -j

依赖项