From e7e7bf711be1a80d1b3879c9a5504b812f246861 Mon Sep 17 00:00:00 2001 From: "Chanyub.Park" Date: Sat, 26 Sep 2026 23:30:37 +0900 Subject: [PATCH] docs: refresh README for CRAN release --- README.md | 286 +++++++++++++++++++++++++++--------------------------- 1 file changed, 142 insertions(+), 144 deletions(-) diff --git a/README.md b/README.md index e4421ef..098a2fd 100644 --- a/README.md +++ b/README.md @@ -1,190 +1,188 @@ -# churon: ONNX Runtime Integration for R +# churon -[![R-CMD-check](https://github.com/churon-project/churon/workflows/R-CMD-check/badge.svg)](https://github.com/churon-project/churon/actions) -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +[![CRAN version](https://www.r-pkg.org/badges/version/churon)](https://CRAN.R-project.org/package=churon) +[![R CMD Check](https://github.com/mrchypark/churon/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/mrchypark/churon/actions/workflows/R-CMD-check.yaml) +[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE.md) -churon provides R bindings for ONNX Runtime, enabling high-performance machine learning inference with ONNX models. +Run ONNX models from R using [ONNX Runtime](https://onnxruntime.ai/). +churon provides model sessions, named tensor inputs and outputs, and a bundled +MNIST model through Rust bindings built with [extendr](https://extendr.github.io/). -## Features +## Install -- 🚀 **High Performance**: Core logic implemented in Rust for speed -- 🛡️ **Memory Safety**: Rust's memory safety guarantees -- 🔧 **Comprehensive Error Handling**: Detailed error messages and validation -- 🌐 **Multiple Execution Providers**: CUDA, TensorRT, DirectML, OneDNN, CoreML, CPU support (on supported platforms) -- 📦 **Bundled Example Models**: MNIST included for testing - -## Installation - -### System Requirements - -- R (>= 4.0.0) -- Supported platforms: macOS (ARM64), Linux (x64/ARM64), Windows (x64) - -### Install from R-universe (Recommended) - -Pre-built binaries are available from [R-universe](https://mrchypark.r-universe.dev/churon), which means **no Rust toolchain required**: +Install the released package from [CRAN](https://CRAN.R-project.org/package=churon): ```r -install.packages('churon', repos = c('https://mrchypark.r-universe.dev', 'https://cloud.r-project.org')) +install.packages("churon") ``` -### Install from GitHub +R 4.0.0 or later is required. Installing a binary package does not require Rust. +Building from source requires Cargo and rustc 1.88.0 or later, along with the +platform's R compilation tools. Rust dependencies are vendored in the CRAN +source package for offline compilation. -If you prefer to build from source (requires Rust >= 1.88.0): +For alternative builds, use [R-universe](https://mrchypark.r-universe.dev/churon): ```r -devtools::install_github("mrchypark/churon") +install.packages( + "churon", + repos = c("https://mrchypark.r-universe.dev", "https://cloud.r-project.org") +) ``` -## Quick Start +## Set up ONNX Runtime -### Basic Usage +ONNX Runtime is a separate native library. The R package can load without it, +but inference requires it. Nothing is downloaded automatically. + +For a first run, install the runtime into a temporary directory: ```r library(churon) -# Download ONNX Runtime once after installing churon -if (!onnx_runtime_is_installed()) { - install_onnx_runtime() -} +install_onnx_runtime(destdir = file.path(tempdir(), "onnxruntime")) +check_onnx_runtime_available() +# TRUE +``` -# Check available example models -models <- onnx_example_models() -print(models) +The installer requires an explicit destination, verifies the download's SHA-256 +checksum, and sets `ORT_DYLIB_PATH` for the current R session. It supports runtime +versions 1.28.0 and 1.29.0; the default is 1.29.0. -# Create a session with the example MNIST model -session <- onnx_example_session("mnist") +To keep the runtime between sessions, choose a persistent directory instead of +`tempdir()`. After installation, inspect the library's full path: -# Get model information -input_info <- onnx_input_info(session) -output_info <- onnx_output_info(session) +```r +get_onnx_runtime_info()$dylib_path +``` -print(input_info[[1]]$get_name()) # Input tensor name -print(input_info[[1]]$get_shape()) # Input tensor shape -print(input_info[[1]]$get_data_type()) # Input tensor data type +In each new R session, set that path **before** loading churon. You can also set +`ORT_DYLIB_PATH` in your `.Renviron` file. It must point to the library file, not +its directory: -# Run inference -input_name <- input_info[[1]]$get_name() -input_shape <- input_info[[1]]$get_shape() # c(1, 1, 28, 28) for MNIST +| Platform | Library under your installation directory | +| --- | --- | +| macOS ARM64 | `lib/libonnxruntime.dylib` | +| Linux x64 / ARM64 | `lib/libonnxruntime.so` | +| Windows x64 / ARM64 | `lib/onnxruntime.dll` | -# Create random input (28x28 grayscale image) -input_data <- array(rnorm(prod(input_shape)), dim = input_shape) -result <- onnx_run(session, setNames(list(input_data), input_name)) +An existing compatible ONNX Runtime installation can be used the same way, +without running the installer. Restart R before switching a runtime that has +already been loaded. The installer does not support Intel macOS. -# Result is class probabilities -cat("Predicted digit:", which.max(result[[1]]) - 1, "\n") -``` +## Run the bundled MNIST model -### Using Custom ONNX Models +Once the runtime is configured, this example runs without any model downloads: ```r -library(churon) - -# Load any ONNX model -session <- onnx_session("path/to/your/model.onnx") +session <- onnx_example_session("mnist") -# Get expected input/output information -input_info <- onnx_input_info(session) -output_info <- onnx_output_info(session) +# MNIST expects one grayscale image: batch x channel x height x width. +# A blank image demonstrates the API; it is not a useful recognition example. +image <- array(0, dim = c(1, 1, 28, 28)) +input_name <- onnx_input_info(session)[[1]]$get_name() +inputs <- setNames(list(image), input_name) -# Run inference with your data -inputs <- list() -inputs[[input_info[[1]]$get_name()]] <- your_data outputs <- onnx_run(session, inputs) +scores <- as.numeric(outputs[[1]]) +predicted_digit <- which.max(scores) - 1L +predicted_digit ``` -### Session Management +Inputs are a named list of numeric vectors, matrices, or arrays. Names must +match the model's input names. Outputs are a named list of tensors; their +meaning depends on the model. The MNIST outputs are scores for digits 0–9, +not automatically normalized probabilities. -```r -# Create session with default providers -session <- onnx_session("model.onnx") +For real images, use the preprocessing and tensor layout expected by your +model. churon does not resize, normalize, or otherwise preprocess images. -# Get available providers (note: may return limited set on current platform) -providers <- onnx_providers(session) -cat("Available providers:", paste(providers, collapse = ", "), "\n") +## Use your own model -# Get model path -model_path <- onnx_model_path(session) -``` - -### Safe Session Creation with Error Handling +Replace the path and supply `input_data` with the dimensions and preprocessing +required by your model: ```r -# Safe session creation with automatic error handling -session <- safe_onnx_session("model.onnx") - -if (!is.null(session)) { - # Session created successfully - result <- onnx_run(session, inputs) -} else { - cat("Failed to create session\n") -} - -# Safe inference with monitoring -result <- safe_onnx_run(session, inputs, monitor_performance = TRUE) -``` - -## API Reference - -### Core Functions - -| Function | Description | -|----------|-------------| -| `onnx_session(model_path, providers = NULL)` | Create an ONNX Runtime session | -| `onnx_run(session, inputs)` | Run inference with input data | -| `onnx_input_info(session)` | Get input tensor information | -| `onnx_output_info(session)` | Get output tensor information | -| `onnx_providers(session)` | Get available execution providers | - -### Example Models - -| Function | Description | -|----------|-------------| -| `onnx_example_models()` | List bundled example models | -| `onnx_example_session(model_name)` | Create session with example model | - -### Utility Functions - -| Function | Description | -|----------|-------------| -| `install_onnx_runtime(version)` | Download and install ONNX Runtime | -| `find_model_path(model_name)` | Find full path to a model file | -| `get_onnx_runtime_info()` | Get ONNX Runtime version info | -| `check_onnx_runtime_available()` | Check if ONNX Runtime is available | -| `safe_onnx_session()` | Create session with error handling | -| `safe_onnx_run()` | Run inference with error handling | - -## Current Status +session <- onnx_session("path/to/model.onnx") -### ✅ Fully Working Features - -- ONNX model loading and session management -- Model metadata extraction and querying -- Tensor conversion (f32, f64 support) -- Inference execution with multiple execution providers -- Comprehensive error handling and validation -- Bundled MNIST model for testing +input_info <- onnx_input_info(session) +output_info <- onnx_output_info(session) +print(input_info) +print(output_info) -### ⚠️ Limitations +# For a single-input model, after preparing input_data: +inputs <- setNames(list(input_data), input_info[[1]]$get_name()) +outputs <- onnx_run(session, inputs) +``` -- **Platform Support**: Currently optimized for macOS ARM64 -- **Execution Providers**: Some providers (CUDA, TensorRT) require additional system libraries -- **Performance Features**: Advanced optimization features pending implementation +For models with multiple inputs, provide one named list entry per input. +Use the model's specification for tensor dimensions: the current metadata +implementation returns `-1` as a shape placeholder, so do not construct arrays +from `$get_shape()`. + +## API at a glance + +| Function | Purpose | +| --- | --- | +| `onnx_session(model_path)` | Load a model into a session | +| `onnx_run(session, inputs)` | Run inference and return named output tensors | +| `onnx_input_info(session)` / `onnx_output_info(session)` | Inspect tensor metadata | +| `onnx_model_path(session)` | Get the session's model path | +| `onnx_providers(session)` | Get the session's reported execution providers | +| `onnx_example_models()` | List bundled model paths | +| `onnx_example_session("mnist")` | Load the bundled MNIST model | +| `install_onnx_runtime(destdir = ...)` | Explicitly download and install the runtime | +| `onnx_runtime_is_installed()` | Check whether a runtime library file can be found | +| `check_onnx_runtime_available()` | Check whether the configured runtime path exists | +| `get_onnx_runtime_info()` | Inspect runtime paths, platform, and configuration | +| `safe_onnx_session()` / `safe_onnx_run()` | Warn and return `NULL` on failure | +| `batch_process_data(session, data_list)` | Process a list of input sets in batches | + +See `?onnx_session`, `?onnx_run`, and `?install_onnx_runtime` in R for details, +or read the [reference manual](https://CRAN.R-project.org/web/packages/churon/churon.pdf). + +## Current limitations + +- **CPU inference:** the current R session API uses CPU execution. Its + `providers` argument validates names but does not yet select a backend; + passing `"cuda"` does not enable GPU inference. +- **Tensor types:** the public inference API accepts numeric inputs and converts + them to float32. Do not assume support for integer, boolean, string, or + float64 model inputs. +- **Shape metadata:** reported shapes are placeholders. Supply dimensions from + your model's specification. +- **Runtime checks:** path checks confirm that a file exists, not that it is a + compatible library. Actual model loading can still fail. + +## Troubleshooting + +**Runtime not found:** inspect `get_onnx_runtime_info()`. Set `ORT_DYLIB_PATH` +to the full library filename before loading churon, or run the installer with +an explicit destination. Temporary installations disappear after the R session. + +**Model or input errors:** check that the model file exists, input names match, +and tensor types and dimensions agree with the model. `onnx_run()` reports +errors; `safe_onnx_run()` turns them into warnings and returns `NULL`. + +## Development and support + +Report bugs or request features in +[GitHub issues](https://github.com/mrchypark/churon/issues). Include your OS, +R and churon versions, runtime configuration, and a minimal reproducible example. +Pull requests are welcome. + +With the development dependencies and Rust toolchain installed, run from a +checkout: -## Contributing +```r +devtools::load_all() +devtools::test() +``` -1. Fork this repository -2. Create a feature branch (`git checkout -b feature/amazing-feature`) -3. Commit your changes (`git commit -m 'Add amazing feature'`) -4. Push to the branch (`git push origin feature/amazing-feature`) -5. Open a Pull Request +Tests requiring ONNX Runtime are skipped when it is unavailable. ## License -This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. - -## Acknowledgments - -- [ONNX Runtime](https://onnxruntime.ai/) team -- [extendr](https://github.com/extendr/extendr) project -- R community +churon is licensed under [MIT](LICENSE.md). The bundled MNIST model and external +ONNX Runtime library have their own licensing terms; see +[third-party notices](inst/COPYRIGHTS) and [contributors](inst/AUTHORS).