今天來介紹 candle
這個開源專案,candle
由 Hugging Face 團隊打造,是近乎全由 Rust 所實現的神經網路模型框架,主要被視為推理引擎。Hugging Face 的團隊和社群應該不用多做說明,是現今爆發的大型語言模型時代下最閃耀的平台,提供工程師、技術者、研究員等能夠下載和分享大型語言模型與資料集的平台。Hugging Face 平台已經非常強大,也無庸置疑的可以被稱之為 Hugging Face 生態系,它們本身早已有成熟強大的 Python library,如:transformers
、optimum
等等,都是在大型語言模型領域中不可或缺的基石。如今,Hugging Face 也加入戰局,推出 candle
,有別於前幾日介紹的 ort
是由 C++ 所建構的 onnx runtime
進行 FFI binding 來實現神經網路模型的導入和推理,而 candle
是以 Rust 的方式建構神經網路底層的邏輯演算法,最終實現高效能、輕量化、易於部署。
需要清楚說明的也還是這三個核心理念:高效能、輕量化、易於部署。高效能的部分並不是說比 C++ 所建構的生態來得好,而是從 Rust 的軟體開發面作為出發點進行討論,從頭到尾都是同一種語言規則下,在演算法優化的過程中自然就只需要考慮這一種環境,如果開發是 C++ 為底層的方式,這對 Rust 軟體便會綁手綁腳的,受制於 C++ 的套件,你也無法控制其底層邏輯,除非你同時精通 Rust 和 C/C++ 語言,不過開發和維運的成本自然較高。
同樣的,上面提到的輕量化和易於部署亦同,全 Rust 實現,意味著在編譯優化的階段是為同一環境下進行優化,並且編譯成可執行檔案也都全然在一起,這和 C++ FFI binding 的分離比較起來,必然相對輕量化和易於部署。所以,這並不是 Rust 具備上述的絕對性優勢,而是在單純以 Rust 軟體開發維運的角度下所產生的核心理念。
Candle 是一個專為 Rust 語言設計的極簡機器學習框架,專注於高效能(包括 GPU 支援)和易用性。它的核心目標是讓無伺服器推理成為可能,並從生產工作負載中移除 Python。
Candle 採用 Rust workspace 架構,包含以下主要模組:
candle/
├── .cargo/ # Cargo 配置
│ └── config.toml
├── .github/ # GitHub Actions 工作流程
│ ├── dependabot.yml
│ └── workflows/
├── candle-core/ # 核心張量操作和裝置管理
│ ├── src/
│ │ ├── lib.rs # 主要 API 入口點
│ │ ├── tensor.rs # 張量實作
│ │ ├── device.rs # 裝置抽象(CPU/CUDA/Metal)
│ │ ├── dtype.rs # 資料型別定義
│ │ ├── backend.rs # 後端介面
│ │ ├── cpu/ # CPU 實作
│ │ ├── cpu_backend/ # CPU 後端
│ │ ├── quantized/ # 量化支援
│ │ └── ...
│ └── tests/ # 單元測試
├── candle-nn/ # 神經網路建構模組
│ ├── src/
│ │ ├── lib.rs # 神經網路 API
│ │ ├── linear.rs # 線性層
│ │ ├── conv.rs # 卷積層
│ │ ├── activation.rs # 激活函數
│ │ ├── optim.rs # 優化器(Adam、SGD 等)
│ │ ├── loss.rs # 損失函數
│ │ ├── layer_norm.rs # 層正規化
│ │ ├── batch_norm.rs # 批次正規化
│ │ └── ...
│ └── tests/ # 神經網路測試
├── candle-transformers/ # 預建 Transformer 模型
│ ├── src/
│ │ ├── models/ # 各種模型實作
│ │ │ ├── llama.rs # LLaMA 模型
│ │ │ ├── bert.rs # BERT 模型
│ │ │ ├── mistral.rs # Mistral 模型
│ │ │ ├── whisper/ # Whisper 語音模型
│ │ │ ├── stable_diffusion/ # Stable Diffusion
│ │ │ └── ...
│ │ ├── generation/ # 文字生成工具
│ │ └── pipelines/ # 預建管道
│ └── tests/
├── candle-examples/ # 範例和教學
│ ├── examples/
│ │ ├── mnist-training/ # MNIST 訓練範例
│ │ ├── llama/ # LLaMA 推理範例
│ │ ├── whisper/ # 語音識別範例
│ │ ├── yolo-v8/ # 物件偵測範例
│ │ └── ...
│ └── src/
├── candle-datasets/ # 資料集工具
│ └── src/
│ ├── vision/ # 視覺資料集(MNIST、CIFAR 等)
│ └── nlp/ # NLP 資料集
├── candle-kernels/ # CUDA 自訂核心
│ └── src/
│ ├── *.cu # CUDA 核心檔案
│ └── lib.rs
├── candle-flash-attn/ # Flash Attention 實作
├── candle-metal-kernels/ # Metal 核心(macOS GPU)
├── candle-onnx/ # ONNX 模型支援
├── candle-pyo3/ # Python 綁定
├── candle-wasm-examples/ # WebAssembly 範例
│ ├── bert/ # 瀏覽器中的 BERT
│ ├── yolo/ # 瀏覽器中的 YOLO
│ └── ...
├── candle-book/ # 官方文檔
└── tensor-tools/ # 張量工具
Tensor
:多維陣列操作Device
:CPU/CUDA/Metal 裝置抽象DType
:資料型別系統Storage
:記憶體管理cargo add --git https://github.com/huggingface/candle.git candle-core
use candle_core::{Device, Tensor};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let device = Device::Cpu;
// 創建隨機張量
let a = Tensor::randn(0f32, 1., (2, 3), &device)?;
let b = Tensor::randn(0f32, 1., (3, 4), &device)?;
// 矩陣乘法
let c = a.matmul(&b)?;
println!("{c}");
Ok(())
}
操作 | PyTorch | Candle |
---|---|---|
創建張量 | torch.Tensor([[1, 2], [3, 4]]) |
Tensor::new(&[[1f32, 2.], [3., 4.]], &Device::Cpu)? |
零張量 | torch.zeros((2, 2)) |
Tensor::zeros((2, 2), DType::F32, &Device::Cpu)? |
索引 | tensor[:, :4] |
tensor.i((.., ..4))? |
重塑 | tensor.view((2, 2)) |
tensor.reshape((2, 2))? |
矩陣乘法 | a.matmul(b) |
a.matmul(&b)? |
算術運算 | a + b |
&a + &b |
裝置轉換 | tensor.to(device="cuda") |
tensor.to_device(&Device::new_cuda(0)?)? |