Skip to content

Commit

Permalink
rust runtime crate
Browse files Browse the repository at this point in the history
  • Loading branch information
yshekel committed Jun 16, 2024
1 parent a7e288e commit 0b47758
Show file tree
Hide file tree
Showing 8 changed files with 251 additions and 10 deletions.
2 changes: 1 addition & 1 deletion icicle_v3/include/icicle/runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ using namespace icicle;
* @param path Path of the backend library or directory where backend libraries are installed
* @return eIcicleError Status of the loaded backend
*/
extern "C" eIcicleError icicle_load_backend(const std::string& path, bool is_recursive);
extern "C" eIcicleError icicle_load_backend(const char* path, bool is_recursive);

/**
* @brief Set active device for thread
Expand Down
24 changes: 15 additions & 9 deletions icicle_v3/src/runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@

using namespace icicle;

extern "C" eIcicleError icicle_nop()
{
std::cout << "HELLO icicle V3" << std::endl;
return eIcicleError::SUCCESS;
}

extern "C" eIcicleError icicle_set_device(const Device& device) { return DeviceAPI::set_thread_local_device(device); }

extern "C" eIcicleError icicle_malloc(void** ptr, size_t size)
Expand Down Expand Up @@ -89,11 +95,11 @@ const std::string SHARED_LIB_EXTENSION = ".dylib";
#error "Unsupported operating system"
#endif

extern "C" eIcicleError icicle_load_backend(const std::string& path, bool is_recursive)
extern "C" eIcicleError icicle_load_backend(const char* path, bool is_recursive)
{
auto is_directory = [](const std::string& path) {
auto is_directory = [](const char* path) {
struct stat pathStat;
if (stat(path.c_str(), &pathStat) != 0) { return false; }
if (stat(path, &pathStat) != 0) { return false; }
return S_ISDIR(pathStat.st_mode);
};

Expand All @@ -103,30 +109,30 @@ extern "C" eIcicleError icicle_load_backend(const std::string& path, bool is_rec
filename.size() - SHARED_LIB_EXTENSION.size(), SHARED_LIB_EXTENSION.size(), SHARED_LIB_EXTENSION) == 0;
};

auto load_library = [](const std::string& filePath) {
auto load_library = [](const char* filePath) {
ICICLE_LOG_DEBUG << "Attempting load: " << filePath;
void* handle = dlopen(filePath.c_str(), RTLD_LAZY | RTLD_GLOBAL);
void* handle = dlopen(filePath, RTLD_LAZY | RTLD_GLOBAL);
if (!handle) { ICICLE_LOG_ERROR << "Failed to load " << filePath << ": " << dlerror(); }
};

if (is_directory(path)) {
// Path is a directory, recursively search for libraries
DIR* dir = opendir(path.c_str());
DIR* dir = opendir(path);
if (!dir) {
ICICLE_LOG_ERROR << "Cannot open directory: " << path;
return eIcicleError::INVALID_ARGUMENT;
}

struct dirent* entry;
while ((entry = readdir(dir)) != nullptr) {
std::string entryPath = path + "/" + entry->d_name;
const std::string& entryPath = std::string(path) + "/" + entry->d_name;

// Skip "." and ".." entries
if (std::string(entry->d_name) == "." || std::string(entry->d_name) == "..") { continue; }

// Recurse into subdirectories and load libraries in files
const bool is_nested_dir = is_directory(entryPath);
if (is_recursive || !is_nested_dir) { icicle_load_backend(entryPath, is_recursive); }
const bool is_nested_dir = is_directory(entryPath.c_str());
if (is_recursive || !is_nested_dir) { icicle_load_backend(entryPath.c_str(), is_recursive); }
}

closedir(dir);
Expand Down
16 changes: 16 additions & 0 deletions wrappers/rust_v3/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[workspace]
resolver = "2"
members = [
"icicle-runtime",
]
exclude = []

[workspace.package]
version = "3.0.0"
edition = "2021"
authors = [ "Ingonyama" ]
homepage = "https://www.ingonyama.com"
repository = "https://github.com/ingonyama-zk/icicle"

[workspace.dependencies]
icicle-cuda-runtime = { path = "icicle-runtime" }
14 changes: 14 additions & 0 deletions wrappers/rust_v3/icicle-runtime/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "icicle-runtime"
version.workspace = true
edition.workspace = true
authors.workspace = true
homepage.workspace = true
repository.workspace = true

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

[build-dependencies]
cmake = "0.1.50"
25 changes: 25 additions & 0 deletions wrappers/rust_v3/icicle-runtime/src/device.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use std::ffi::{CStr, CString};
use std::os::raw::c_char;

#[repr(C)]
pub struct Device {
pub device_type: *const std::os::raw::c_char,
pub id: i32,
}

#[repr(C)]
pub struct DeviceProperties {
pub using_host_memory: bool,
pub num_memory_regions: i32,
pub supports_pinned_memory: bool,
}

impl Device {
pub fn new(device_type: &str, id: i32) -> Device {
let c_string = CString::new(device_type).expect("CString::new failed");
Device {
device_type: c_string.into_raw(),
id,
}
}
}
17 changes: 17 additions & 0 deletions wrappers/rust_v3/icicle-runtime/src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#[repr(C)]
#[derive(Debug, PartialEq)]
pub enum eIcicleError {
Success = 0, // Operation completed successfully
InvalidDevice, // The specified device is invalid
OutOfMemory, // Memory allocation failed due to insufficient memory
InvalidPointer, // The specified pointer is invalid
AllocationFailed, // Memory allocation failed
DeallocationFailed, // Memory deallocation failed
CopyFailed, // Data copy operation failed
SynchronizationFailed, // Device synchronization failed
StreamCreationFailed, // Stream creation failed
StreamDestructionFailed, // Stream destruction failed
ApiNotImplemented, // The API is not implemented for a device
InvalidArgument, // Invalid argument passed
UnknownError, // An unknown error occurred
}
26 changes: 26 additions & 0 deletions wrappers/rust_v3/icicle-runtime/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
pub mod device;
pub mod errors;
pub mod runtime;

// Re-export the types for easier access
pub use device::{Device, DeviceProperties};
pub use errors::eIcicleError;
pub use runtime::*;

use std::ffi::CString;

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_set_device() {
// load backends to process
let backend_install_dir = env!("DEFAULT_BACKEND_INSTALL_DIR");
assert_eq!(load_backend(&backend_install_dir, true), eIcicleError::Success);

let devtype = String::from("CPU");
let dev = Device::new(&devtype, 0);
assert_eq!(set_device(&dev), eIcicleError::Success);
}
}
137 changes: 137 additions & 0 deletions wrappers/rust_v3/icicle-runtime/src/runtime.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
use std::ffi::CString;
use std::os::raw::{c_char, c_void};

use crate::device::Device;
use crate::errors::eIcicleError;

pub type IcicleStreamHandle = *mut c_void;

extern "C" {
fn icicle_nop() -> eIcicleError;
fn icicle_load_backend(path: *const c_char, is_recursive: bool) -> eIcicleError;
fn icicle_set_device(device: &Device) -> eIcicleError;
// fn icicle_malloc(ptr: *mut *mut c_void, size: usize) -> eIcicleError;
// fn icicle_malloc_async(ptr: *mut *mut c_void, size: usize, stream: IcicleStreamHandle) -> eIcicleError;
// fn icicle_free(ptr: *mut c_void) -> eIcicleError;
// fn icicle_free_async(ptr: *mut c_void, stream: IcicleStreamHandle) -> eIcicleError;
// fn icicle_get_available_memory(total: *mut usize, free: *mut usize) -> eIcicleError;
// fn icicle_copy_to_host(dst: *mut u8, src: *const u8, size: usize) -> eIcicleError;
// fn icicle_copy_to_host_async(dst: *mut u8, src: *const u8, size: usize, stream: IcicleStreamHandle)
// -> eIcicleError;
// fn icicle_copy_to_device(dst: *mut u8, src: *const u8, size: usize) -> eIcicleError;
// fn icicle_copy_to_device_async(
// dst: *mut u8,
// src: *const u8,
// size: usize,
// stream: IcicleStreamHandle,
// ) -> eIcicleError;
// fn icicle_create_stream(stream: *mut IcicleStreamHandle) -> eIcicleError;
// fn icicle_destroy_stream(stream: IcicleStreamHandle) -> eIcicleError;
// fn icicle_stream_synchronize(stream: IcicleStreamHandle) -> eIcicleError;
fn icicle_device_synchronize() -> eIcicleError;
// fn icicle_get_device_properties(properties: *mut DeviceProperties) -> eIcicleError;
}

pub fn nop() -> eIcicleError {
unsafe { icicle_nop() }
}

pub fn load_backend(path: &str, is_recursive: bool) -> eIcicleError {
let c_path = CString::new(path).unwrap();
unsafe { icicle_load_backend(c_path.as_ptr(), is_recursive) }
}

pub fn set_device(device: &Device) -> eIcicleError {
unsafe { icicle_set_device(device) }
}

// pub fn malloc(size: usize) -> Result<*mut c_void, eIcicleError> {
// let mut ptr: *mut c_void = std::ptr::null_mut();
// let result = unsafe { icicle_malloc(&mut ptr, size) };
// if result == eIcicleError::Success {
// Ok(ptr)
// } else {
// Err(result)
// }
// }

// pub fn malloc_async(size: usize, stream: IcicleStreamHandle) -> Result<*mut c_void, eIcicleError> {
// let mut ptr: *mut c_void = std::ptr::null_mut();
// let result = unsafe { icicle_malloc_async(&mut ptr, size, stream) };
// if result == eIcicleError::Success {
// Ok(ptr)
// } else {
// Err(result)
// }
// }

// pub fn free(ptr: *mut c_void) -> eIcicleError {
// unsafe { icicle_free(ptr) }
// }

// pub fn free_async(ptr: *mut c_void, stream: IcicleStreamHandle) -> eIcicleError {
// unsafe { icicle_free_async(ptr, stream) }
// }

// pub fn get_available_memory() -> Result<(usize, usize), eIcicleError> {
// let mut total: usize = 0;
// let mut free: usize = 0;
// let result = unsafe { icicle_get_available_memory(&mut total, &mut free) };
// if result == eIcicleError::Success {
// Ok((total, free))
// } else {
// Err(result)
// }
// }

// pub fn copy_to_host(dst: *mut u8, src: *const u8, size: usize) -> eIcicleError {
// unsafe { icicle_copy_to_host(dst, src, size) }
// }

// pub fn copy_to_host_async(dst: *mut u8, src: *const u8, size: usize, stream: IcicleStreamHandle) -> eIcicleError {
// unsafe { icicle_copy_to_host_async(dst, src, size, stream) }
// }

// pub fn copy_to_device(dst: *mut u8, src: *const u8, size: usize) -> eIcicleError {
// unsafe { icicle_copy_to_device(dst, src, size) }
// }

// pub fn copy_to_device_async(dst: *mut u8, src: *const u8, size: usize, stream: IcicleStreamHandle) -> eIcicleError {
// unsafe { icicle_copy_to_device_async(dst, src, size, stream) }
// }

// pub fn create_stream() -> Result<IcicleStreamHandle, eIcicleError> {
// let mut stream: IcicleStreamHandle = std::ptr::null_mut();
// let result = unsafe { icicle_create_stream(&mut stream) };
// if result == eIcicleError::Success {
// Ok(stream)
// } else {
// Err(result)
// }
// }

// pub fn destroy_stream(stream: IcicleStreamHandle) -> eIcicleError {
// unsafe { icicle_destroy_stream(stream) }
// }

// pub fn stream_synchronize(stream: IcicleStreamHandle) -> eIcicleError {
// unsafe { icicle_stream_synchronize(stream) }
// }

pub fn device_synchronize() -> eIcicleError {
unsafe { icicle_device_synchronize() }
}

// pub fn get_device_properties() -> Result<DeviceProperties, eIcicleError> {
// let mut properties = DeviceProperties {
// using_host_memory: false,
// num_memory_regions: 0,
// supports_pinned_memory: false,
// };
// let result = unsafe { icicle_get_device_properties(&mut properties) };
// if result == eIcicleError::Success {
// Ok(properties)
// } else {
// Err(result)
// }
// }

0 comments on commit 0b47758

Please sign in to comment.