Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add vaccel_config bindings and update agent API #6

Merged
merged 5 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion .github/workflows/validate-code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ on:
runner-arch-map:
type: string
default: '[{"amd64":"x86_64", "arm64":"aarch64", "arm":"armv7l"}]'
clippy-features:
type: string
default: 'async,async-stream'
secrets:
GIT_CLONE_PAT:
required: false
Expand Down Expand Up @@ -59,6 +62,13 @@ jobs:
remote-actions-repo: ${{ inputs.actions-repo }}
token: ${{ secrets.GIT_CLONE_PAT || github.token }}

# FIXME: Temp
- name: Install libcurl & stb
run: |
sudo apt-get update
sudo apt-get install -y libcurl4-openssl-dev libstb-dev
shell: bash

- name: Download artifacts from s3
id: download-artifacts
if: ${{ inputs.actions-repo != github.repository }}
Expand All @@ -73,7 +83,14 @@ jobs:
install: 'true'

- name: Run rust-clippy
run: cargo clippy --workspace --all-targets --all-features
run: |
cargo clippy --workspace --all-targets
cargo clippy --workspace --all-targets --all-features
IFS=','
features=${{ inputs.clippy-features }}
for f in $features; do
cargo clippy --workspace --all-targets --features "$f"
done
shell: bash

- name: Clean-up
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ Crates implementing Rust interfaces for the vAccel C library:

Install vAccel with:
```bash
wget https://s3.nbfc.io/nbfc-assets/github/vaccel/rev/main/x86_64/release/vaccel_latest_x86_64.deb
sudo dpkg -i vaccel_latest_x86_64.deb
wget https://s3.nbfc.io/nbfc-assets/github/vaccel/rev/main/x86_64/release/vaccel_latest_amd64.deb
sudo dpkg -i vaccel_latest_amd64.deb
```

## Build the components
Expand Down
1 change: 1 addition & 0 deletions vaccel-bindings/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ protobuf = "3.1"
env_logger = "0.11"
log = "0.4"
libc = "0.2"
thiserror = "1.0"

[build-dependencies]
libc = "0.2"
Expand Down
122 changes: 122 additions & 0 deletions vaccel-bindings/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// SPDX-License-Identifier: Apache-2.0

use crate::{ffi, Error, Result};
use log::warn;
use std::{
ffi::{c_char, c_uint, CString},
ptr,
};

#[derive(Debug)]
pub struct Config {
inner: ffi::vaccel_config,
initialized: bool,
}

// inner (`ffi::vaccel_config`) is only accessed through this (Config) struct's
// methods and does not access TLS variables or global state so this should be
// safe
unsafe impl Send for Config {}

impl Config {
/// Create a new resource object
pub fn new(
plugins: Option<&str>,
log_level: u8,
log_file: Option<&str>,
profiling_enabled: bool,
version_ignore: bool,
) -> Result<Self> {
let plugins_cstr: CString;
let plugins_ptr: *const c_char;
match plugins {
Some(p) => {
plugins_cstr = CString::new(p).map_err(|_| Error::InvalidArgument)?;
plugins_ptr = plugins_cstr.as_c_str().as_ptr();
}
None => {
plugins_ptr = ptr::null();
}
};

let log_file_cstr: CString;
let log_file_ptr: *const c_char;
match log_file {
Some(l) => {
log_file_cstr = CString::new(l).map_err(|_| Error::InvalidArgument)?;
log_file_ptr = log_file_cstr.as_c_str().as_ptr();
}
None => {
log_file_ptr = ptr::null();
}
};

let mut inner = ffi::vaccel_config::default();
match unsafe {
ffi::vaccel_config_init(
&mut inner,
plugins_ptr,
log_level as c_uint,
log_file_ptr,
profiling_enabled,
version_ignore,
) as u32
} {
ffi::VACCEL_OK => Ok(Config {
inner,
initialized: true,
}),
err => Err(Error::Runtime(err)),
}
}

/// Create new config from environment variables
pub fn from_env() -> Result<Self> {
let mut inner = ffi::vaccel_config::default();
match unsafe { ffi::vaccel_config_init_from_env(&mut inner) as u32 } {
ffi::VACCEL_OK => Ok(Config {
inner,
initialized: true,
}),
err => Err(Error::Runtime(err)),
}
}

/// Returns `true` if the config has been initialized
pub fn initialized(&self) -> bool {
self.initialized
}

/// Release config data
pub fn release(&mut self) -> Result<()> {
if !self.initialized {
return Err(Error::Uninitialized);
}

match unsafe { ffi::vaccel_config_release(&mut self.inner) as u32 } {
ffi::VACCEL_OK => {
self.initialized = false;
Ok(())
}
err => Err(Error::Runtime(err)),
}
}

// Warning: Do not copy internal raw pointers
pub(crate) fn inner(&self) -> &ffi::vaccel_config {
&self.inner
}

// Warning: Do not copy internal raw pointers
pub(crate) fn inner_mut(&mut self) -> &mut ffi::vaccel_config {
&mut self.inner
}
}

impl Drop for Config {
fn drop(&mut self) {
if self.initialized && self.release().is_err() {
warn!("Could not release config");
}
}
}
66 changes: 43 additions & 23 deletions vaccel-bindings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
#![allow(improper_ctypes)]

use std::{fmt, slice};
use thiserror::Error as ThisError;

pub mod arg;
pub mod config;
pub mod ffi;
pub mod file;
pub mod ops;
Expand All @@ -17,50 +19,43 @@ pub mod resource;
pub mod session;

pub use arg::Arg;
pub use config::Config;
pub use file::File;
pub use resource::Resource;
pub use session::Session;

#[derive(Debug)]
#[derive(ThisError, Debug)]
pub enum Error {
// Error returned to us by vAccel runtime library
/// Error returned by the vAccel runtime library
#[error("vAccel runtime error: {0}")]
Runtime(u32),

// We received an invalid argument
/// Invalid argument
#[error("Invalid argument")]
InvalidArgument,

// Uninitialized vAccel object
/// Uninitialized vAccel object
#[error("Invalid argument")]
Uninitialized,

// A TensorFlow error
/// TensorFlow error
#[cfg(target_pointer_width = "64")]
#[error("TensorFlow error: {0:?}")]
TensorFlow(ops::tensorflow::Code),

// A TensorFlow Lite error
/// TensorFlow Lite error
#[error("TensorFlow Lite error: {0:?}")]
TensorFlowLite(ops::tensorflow::lite::Code),

// A PyTorch error
/// LibTorch error
#[error("Torch error: {0:?}")]
Torch(ops::torch::Code),

// Other error types
/// Other error types
#[error("Error: {0}")]
Others(String),
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::Runtime(e) => write!(f, "vAccel runtime error: {}", e),
Error::InvalidArgument => write!(f, "Invalid argument"),
Error::Uninitialized => write!(f, "Uninitialized vAccel object"),
#[cfg(target_pointer_width = "64")]
Error::TensorFlow(e) => write!(f, "TensorFlow error: {:?}", e),
Error::TensorFlowLite(e) => write!(f, "TensorFlow Lite error: {:?}", e),
Error::Torch(e) => write!(f, "Torch error: {:?}", e),
Error::Others(e) => write!(f, "Error: {}", e),
}
}
}

pub type Result<T> = std::result::Result<T, Error>;

#[derive(PartialEq, Eq, Hash, Debug)]
Expand Down Expand Up @@ -151,3 +146,28 @@ pub unsafe fn c_pointer_to_mut_slice<'a, T>(buf: *mut T, len: usize) -> Option<&
Some(unsafe { slice::from_raw_parts_mut(buf, len) })
}
}

pub fn bootstrap_with_config(config: &mut Config) -> Result<()> {
match unsafe { ffi::vaccel_bootstrap_with_config(config.inner_mut()) as u32 } {
ffi::VACCEL_OK => Ok(()),
err => Err(Error::Runtime(err)),
}
}

pub fn bootstrap() -> Result<()> {
match unsafe { ffi::vaccel_bootstrap() as u32 } {
ffi::VACCEL_OK => Ok(()),
err => Err(Error::Runtime(err)),
}
}

pub fn cleanup() -> Result<()> {
match unsafe { ffi::vaccel_cleanup() as u32 } {
ffi::VACCEL_OK => Ok(()),
err => Err(Error::Runtime(err)),
}
}

pub fn is_initialized() -> bool {
unsafe { ffi::vaccel_is_initialized() }
}
Loading
Loading