From a0238de25590df5eae4d6dcaf7feba095957f0df Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Thu, 28 Mar 2024 16:05:02 +0000 Subject: [PATCH 01/20] basic cuda bindings --- crates/memonitor-sys/Cargo.toml | 3 +- crates/memonitor-sys/build.rs | 103 ++++++--- crates/memonitor-sys/cuda/CMakeLists.txt | 12 ++ crates/memonitor-sys/cuda/include/memonitor.h | 122 +++++++++++ crates/memonitor-sys/cuda/src/memonitor.c | 201 ++++++++++++++++++ crates/memonitor-sys/src/cuda.rs | 7 + crates/memonitor-sys/src/lib.rs | 2 + crates/memonitor-sys/vulkan/src/memonitor.c | 4 +- crates/memonitor/Cargo.toml | 2 +- crates/memonitor/src/cuda.rs | 0 crates/memonitor/src/lib.rs | 1 + 11 files changed, 421 insertions(+), 36 deletions(-) create mode 100644 crates/memonitor-sys/cuda/CMakeLists.txt create mode 100644 crates/memonitor-sys/cuda/include/memonitor.h create mode 100644 crates/memonitor-sys/cuda/src/memonitor.c create mode 100644 crates/memonitor-sys/src/cuda.rs create mode 100644 crates/memonitor/src/cuda.rs diff --git a/crates/memonitor-sys/Cargo.toml b/crates/memonitor-sys/Cargo.toml index d8b7962..fd405cf 100644 --- a/crates/memonitor-sys/Cargo.toml +++ b/crates/memonitor-sys/Cargo.toml @@ -17,5 +17,6 @@ cmake = "0.1.50" bindgen = "0.69.4" [features] -default = ["vulkan"] +default = ["vulkan", "cuda"] vulkan = [] +cuda = [] diff --git a/crates/memonitor-sys/build.rs b/crates/memonitor-sys/build.rs index f4d4267..6cd5dca 100644 --- a/crates/memonitor-sys/build.rs +++ b/crates/memonitor-sys/build.rs @@ -8,44 +8,83 @@ use std::path::PathBuf; fn main() { let cur_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - let vk_dir = cur_dir.join("vulkan"); - let submodules_dir = vk_dir.join("thirdparty"); - read_dir(submodules_dir.join("Vulkan-Headers")) - .expect("Could not find Vulkan Headers. Did you forget to initialize submodules?"); - read_dir(submodules_dir.join("volk")) - .expect("Could not find Volk. Did you forget to initialize submodules?"); - let mut build = Config::new(vk_dir.as_path()); - - #[cfg(debug_assertions)] + #[cfg(feature = "vulkan")] { - build.define("MEMONITOR_VALIDATE", "ON"); + let vk_dir = cur_dir.join("vulkan"); + let submodules_dir = vk_dir.join("thirdparty"); + read_dir(submodules_dir.join("Vulkan-Headers")) + .expect("Could not find Vulkan Headers. Did you forget to initialize submodules?"); + read_dir(submodules_dir.join("volk")) + .expect("Could not find Volk. Did you forget to initialize submodules?"); + let mut build = Config::new(vk_dir.as_path()); + + #[cfg(debug_assertions)] + { + build.define("MEMONITOR_VALIDATE", "ON"); + } + + let lib_out = build.build(); + println!( + "cargo:rustc-link-search=native={}", + lib_out.join("lib").display() + ); + println!("cargo:rustc-link-lib=static=volk"); + println!("cargo:rustc-link-lib=static=memonitor-vk"); + + let vk_bindings = Builder::default() + .header(vk_dir.join("include").join("memonitor.h").to_string_lossy()) + .allowlist_function("vk_.*") + .allowlist_type("vk_.*") + .parse_callbacks(Box::new(PrefixRemover::new("vk_"))) + .default_enum_style(EnumVariation::Rust { + non_exhaustive: true, + }) + .use_core() + .generate() + .expect("Failed to generate Vulkan bindings"); + + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + + vk_bindings + .write_to_file(out_path.join("vk_bindings.rs")) + .expect("Couldn't write bindings"); } - let lib_out = build.build(); - println!( - "cargo:rustc-link-search=native={}", - lib_out.join("lib").display() - ); - println!("cargo:rustc-link-lib=static=volk"); - println!("cargo:rustc-link-lib=static=memonitor-vk"); + #[cfg(feature = "cuda")] + { + let cuda_dir = cur_dir.join("cuda"); + let mut build = Config::new(cuda_dir.as_path()); - let vk_bindings = Builder::default() - .header(vk_dir.join("include").join("memonitor.h").to_string_lossy()) - .allowlist_function("vk_.*") - .allowlist_type("vk_.*") - .parse_callbacks(Box::new(PrefixRemover::new("vk_"))) - .default_enum_style(EnumVariation::Rust { - non_exhaustive: true, - }) - .use_core() - .generate() - .expect("Failed to generate Vulkan bindings"); + let lib_out = build.build(); + println!( + "cargo:rustc-link-search=native={}", + lib_out.join("lib").display() + ); + println!("cargo:rustc-link-lib=static=memonitor-cuda"); - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + let cuda_bindings = Builder::default() + .header( + cuda_dir + .join("include") + .join("memonitor.h") + .to_string_lossy(), + ) + .allowlist_function("cu_.*") + .allowlist_type("cu_.*") + .parse_callbacks(Box::new(PrefixRemover::new("cu_"))) + .default_enum_style(EnumVariation::Rust { + non_exhaustive: true, + }) + .use_core() + .generate() + .expect("Failed to generate Cuda bindings"); - vk_bindings - .write_to_file(out_path.join("vk_bindings.rs")) - .expect("Couldn't write bindings"); + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + + cuda_bindings + .write_to_file(out_path.join("cuda_bindings.rs")) + .expect("Couldn't write bindings"); + } } #[derive(Debug)] diff --git a/crates/memonitor-sys/cuda/CMakeLists.txt b/crates/memonitor-sys/cuda/CMakeLists.txt new file mode 100644 index 0000000..b6ec344 --- /dev/null +++ b/crates/memonitor-sys/cuda/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.5) + +project(memonitor-cuda LANGUAGES C) + +add_library(memonitor-cuda STATIC "include/memonitor.h" "src/memonitor.c") +target_include_directories(memonitor-cuda PUBLIC "include") + +install(TARGETS memonitor-cuda + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/crates/memonitor-sys/cuda/include/memonitor.h b/crates/memonitor-sys/cuda/include/memonitor.h new file mode 100644 index 0000000..181b82b --- /dev/null +++ b/crates/memonitor-sys/cuda/include/memonitor.h @@ -0,0 +1,122 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Initializes the global context. + * + * Must be called before all other functions. Must be called again after `cu_term` is called before using other + * functions. + * + * @return 0 on success, otherwise the error code. + */ +int cu_init(); + +/** + * Destroys the global context and frees all allocations. + * + * It isn't necessary to call this before program exit, but it is if the context will be created again. + */ +void cu_term(); + +/** + * A list of physical devices. + */ +struct cu_Devices { + /// Internal handle to the device list. + void *devices_handle; + /// Internal handle to the context list. + void *ctx_handle; + /// The number of devices within this list. + uint32_t count; +}; + +/** + * Creates a list containing all physical devices found within the Vulkan context. + * + * @return The list of devices found. + */ +struct cu_Devices cu_list_devices(); + +/** + * Destroys a `cu_Devices` object and frees its used memory + * + * @param devices the object to destroy + */ +void cu_destroy_devices(struct cu_Devices *devices); + +/// A reference to a physical device retrieved from a `cu_Devices` object. +struct cu_DeviceRef { + /// The internal handle to the physical device. + void *handle; + /// The internal handle to the device context. + void *ctx_handle; +}; + +/** + * Acquire a reference to a device from within a `cu_Devices` object. + * + * @param devices a `cu_Devices` handle from which to get the reference + * @param index the index of the device within `cu_Devices` + * @return A reference to the device at the index. If any of the arguments is invalid/null, return an null reference. + */ +struct cu_DeviceRef cu_get_device(struct cu_Devices *devices, uint32_t index); + +/** + * The hardware type of a device. + */ +enum cu_DeviceKind { + /// A Graphics Card physically integrated into the CPU (probably sharing the same memory). + IntegratedGPU, + /// A discrete Graphics Card, probably connected through PCIE. + DiscreteGPU, + /// Some other, unknown type. + Other, +}; + +/** + * Properties of a device. + */ +struct cu_DeviceProperties { + /// The name of this device. + char name[256U]; + /// The hardware type of this device. + enum cu_DeviceKind kind; + /// The total amount of local memory for this device. + size_t total_memory; +}; + +/** + * Get the properties of the provided device. + * + * @param device the device to get properties from + * @return The device properties. + */ +struct cu_DeviceProperties cu_device_properties(struct cu_DeviceRef device); + +/** + * Memory information of a device at one point in time. + */ +struct cu_DeviceMemoryProperties { + /// How much memory is available to this device at any given moment. + size_t budget; + /// How much memory is currently getting used from the device. + size_t used; +}; + +/** + * Query local memory information of the provided device at this point in time. + * + * @param device the device to be queried + * @return The device's memory information. + */ +struct cu_DeviceMemoryProperties cu_device_memory_properties(struct cu_DeviceRef device); + +#ifdef __cplusplus +} +#endif // __cplusplus diff --git a/crates/memonitor-sys/cuda/src/memonitor.c b/crates/memonitor-sys/cuda/src/memonitor.c new file mode 100644 index 0000000..6b917b6 --- /dev/null +++ b/crates/memonitor-sys/cuda/src/memonitor.c @@ -0,0 +1,201 @@ +#include +#include + +#include + +#include + +const char *LIB_NAME = "nvcuda.dll"; + +typedef int CUresult; +struct CUctx_st; +typedef struct CUctx_st *CUcontext; +struct CUdevice_v1; +typedef struct CUdevice_v1 *CUdevice; + +typedef CUresult(*cuInit_type)(unsigned int); + +typedef CUresult (*cuCtxCreate_type)(CUcontext *, unsigned int, CUdevice); + +typedef CUresult (*cuCtxDestroy_type)(CUcontext); + +typedef CUresult (*cuCtxSetCurrent_type)(CUcontext); + +typedef CUresult (*cuDeviceGetCount_type)(int *); + +typedef CUresult (*cuDeviceGet_type)(CUdevice *, int); + +typedef CUresult (*cuDeviceGetName_type)(char *, int, CUdevice); + +typedef CUresult (*cuDeviceTotalMem_type)(size_t *, CUdevice); + +typedef CUresult (*cuMemGetInfo_type)(size_t *, size_t *); + +HMODULE module = NULL; + +cuInit_type cuInit = NULL; +cuCtxCreate_type cuCtxCreate = NULL; +cuCtxDestroy_type cuCtxDestroy = NULL; +cuCtxSetCurrent_type cuCtxSetCurrent = NULL; +cuDeviceGetCount_type cuDeviceGetCount = NULL; +cuDeviceGet_type cuDeviceGet = NULL; +cuDeviceGetName_type cuDeviceGetName = NULL; +cuDeviceTotalMem_type cuDeviceTotalMem = NULL; +cuMemGetInfo_type cuMemGetInfo = NULL; + + +int cu_init() { + module = LoadLibraryA(LIB_NAME); + if (!module) { + return -1; + } + + cuInit = (cuInit_type) GetProcAddress(module, "cuInit"); + cuCtxCreate = (cuCtxCreate_type) GetProcAddress(module, "cuCtxCreate"); + cuCtxDestroy = (cuCtxDestroy_type) GetProcAddress(module, "cuCtxDestroy"); + cuCtxSetCurrent = (cuCtxSetCurrent_type) GetProcAddress(module, "cuCtxSetCurrent"); + cuDeviceGetCount = (cuDeviceGetCount_type) GetProcAddress(module, "cuDeviceGetCount"); + cuDeviceGet = (cuDeviceGet_type) GetProcAddress(module, "cuDeviceGet"); + cuDeviceGetName = (cuDeviceGetName_type) GetProcAddress(module, "cuDeviceGetName"); + cuDeviceTotalMem = (cuDeviceTotalMem_type) GetProcAddress(module, "cuDeviceTotalMem"); + cuMemGetInfo = (cuMemGetInfo_type) GetProcAddress(module, "cuMemGetInfo"); + + CUresult res = cuInit(0); + if (res != 0) { + return -2; + } + + return 0; +} + +void cu_term() { + FreeLibrary(module); + module = NULL; + + cuInit = NULL; + cuCtxCreate = NULL; + cuCtxDestroy = NULL; + cuCtxSetCurrent = NULL; + cuDeviceGetCount = NULL; + cuDeviceGet = NULL; + cuDeviceGetName = NULL; + cuDeviceTotalMem = NULL; + cuMemGetInfo = NULL; +} + +struct cu_Devices cu_list_devices() { + const struct cu_Devices invalid_devices = { + NULL, + NULL, + 0, + }; + + int count = 0; + CUresult res = cuDeviceGetCount(&count); + if (count <= 0 || res != 0) { + return invalid_devices; + } + + CUdevice *device_handles = malloc(sizeof(CUdevice) * count); + CUcontext *ctx_handles = malloc(sizeof(CUcontext) * count); + for (int d = 0; d < count; d++) { + res = cuDeviceGet(&device_handles[d], d); + if (res != 0) { + free(device_handles); + return invalid_devices; + } + + res = cuCtxCreate(&ctx_handles[d], 0, device_handles[d]); + if (res != 0) { + free(device_handles); + return invalid_devices; + } + } + + struct cu_Devices devices = { + device_handles, + ctx_handles, + count, + }; + return devices; +} + +void cu_destroy_devices(struct cu_Devices *devices) { + if (devices && devices->devices_handle && devices->ctx_handle && devices->count) { + CUcontext *ctx_handles = devices->ctx_handle; + for (int d = 0; d < devices->count; d++) { + cuCtxDestroy(ctx_handles[d]); + } + free(devices->devices_handle); + free(devices->ctx_handle); + devices->devices_handle = NULL; + devices->ctx_handle = NULL; + devices->count = 0; + } +} + +struct cu_DeviceRef cu_get_device(struct cu_Devices *devices, uint32_t index) { + const struct cu_DeviceRef invalid_ref = {NULL}; + if (!devices || !devices->devices_handle || !devices->ctx_handle || !devices->count || devices->count <= index) { + return invalid_ref; + } + + CUcontext *cast_devices = devices->devices_handle; + CUcontext *cast_ctxs = devices->ctx_handle; + struct cu_DeviceRef ref = {cast_devices[index], cast_ctxs[index]}; + return ref; +} + +struct cu_DeviceProperties cu_device_properties(struct cu_DeviceRef device) { + const struct cu_DeviceProperties invalid_properties = {{0}, Other, 0}; + if (!device.handle) { + return invalid_properties; + } + + CUdevice cast_device = device.handle; + char *name = NULL; + size_t total_memory = 0; + + CUresult res = cuDeviceGetName(name, 256, cast_device); + if (res != 0) { + return invalid_properties; + } + + res = cuDeviceTotalMem(&total_memory, cast_device); + if (res != 0) { + return invalid_properties; + } + + struct cu_DeviceProperties props = {0}; + strncpy_s(props.name, sizeof(props.name), name, 256U); + props.kind = DiscreteGPU; + props.total_memory = total_memory; + return props; +} + +struct cu_DeviceMemoryProperties cu_device_memory_properties(struct cu_DeviceRef device) { + const struct cu_DeviceMemoryProperties invalid_properties = {0}; + if (!device.handle) { + return invalid_properties; + } + + CUcontext cast_ctx = device.ctx_handle; + CUresult res = cuCtxSetCurrent(cast_ctx); + if (res != 0) { + return invalid_properties; + } + + size_t free_memory = 0; + size_t total_memory = 0; + + res = cuMemGetInfo(&free_memory, &total_memory); + if (res != 0) { + return invalid_properties; + } + + struct cu_DeviceMemoryProperties props = { + free_memory, + total_memory - free_memory, + }; + return props; +} diff --git a/crates/memonitor-sys/src/cuda.rs b/crates/memonitor-sys/src/cuda.rs new file mode 100644 index 0000000..aaa5f47 --- /dev/null +++ b/crates/memonitor-sys/src/cuda.rs @@ -0,0 +1,7 @@ +//! Automatically generated bindings for the Vulkan backend. + +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +include!(concat!(env!("OUT_DIR"), "/cuda_bindings.rs")); diff --git a/crates/memonitor-sys/src/lib.rs b/crates/memonitor-sys/src/lib.rs index 2066032..7847bb0 100644 --- a/crates/memonitor-sys/src/lib.rs +++ b/crates/memonitor-sys/src/lib.rs @@ -8,5 +8,7 @@ #![warn(missing_docs)] +#[cfg(feature = "cuda")] +pub mod cuda; #[cfg(feature = "vulkan")] pub mod vulkan; diff --git a/crates/memonitor-sys/vulkan/src/memonitor.c b/crates/memonitor-sys/vulkan/src/memonitor.c index e8b47a8..280354a 100644 --- a/crates/memonitor-sys/vulkan/src/memonitor.c +++ b/crates/memonitor-sys/vulkan/src/memonitor.c @@ -206,7 +206,7 @@ struct vk_DeviceRef vk_get_device(struct vk_Devices *devices, uint32_t index) { } struct vk_DeviceProperties vk_device_properties(struct vk_DeviceRef device) { - const struct vk_DeviceProperties invalid_properties = {{0}, Other}; + const struct vk_DeviceProperties invalid_properties = {{0}, Other, 0}; if (!device.handle) { return invalid_properties; } @@ -249,7 +249,7 @@ struct vk_DeviceProperties vk_device_properties(struct vk_DeviceRef device) { } struct vk_DeviceProperties ret_props = {0}; - strncpy(ret_props.name, properties.properties.deviceName, 256U); + strncpy_s(ret_props.name, sizeof(ret_props.name), properties.properties.deviceName, 256U); ret_props.kind = kind; ret_props.total_memory = memory; return ret_props; diff --git a/crates/memonitor/Cargo.toml b/crates/memonitor/Cargo.toml index bfca6e5..76fa581 100644 --- a/crates/memonitor/Cargo.toml +++ b/crates/memonitor/Cargo.toml @@ -10,7 +10,7 @@ edition = "2021" publish = true [dependencies] -memonitor-sys = { path = "../memonitor-sys", version = "0.1.1" } +memonitor-sys = { path = "../memonitor-sys", version = "0.1.1", default-features = false } sysinfo = "0.30.7" [features] diff --git a/crates/memonitor/src/cuda.rs b/crates/memonitor/src/cuda.rs new file mode 100644 index 0000000..e69de29 diff --git a/crates/memonitor/src/lib.rs b/crates/memonitor/src/lib.rs index 9cd93af..67bd4cf 100644 --- a/crates/memonitor/src/lib.rs +++ b/crates/memonitor/src/lib.rs @@ -49,6 +49,7 @@ pub const CPU_NAME: &str = "Host"; #[cfg(feature = "vulkan")] mod vulkan; +mod cuda; /// The name of the Vulkan backend. #[cfg(feature = "vulkan")] From 6443b043787831a5574c42fdd9d5c3f27932c109 Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Thu, 28 Mar 2024 16:55:16 +0000 Subject: [PATCH 02/20] windows cuda backend --- crates/memonitor-sys/cuda/include/memonitor.h | 2 +- crates/memonitor-sys/cuda/src/memonitor.c | 14 +- crates/memonitor-sys/src/cuda.rs | 2 +- crates/memonitor/Cargo.toml | 3 +- crates/memonitor/src/cuda.rs | 129 ++++++++++++++++++ crates/memonitor/src/lib.rs | 12 +- 6 files changed, 150 insertions(+), 12 deletions(-) diff --git a/crates/memonitor-sys/cuda/include/memonitor.h b/crates/memonitor-sys/cuda/include/memonitor.h index 181b82b..7e7b38c 100644 --- a/crates/memonitor-sys/cuda/include/memonitor.h +++ b/crates/memonitor-sys/cuda/include/memonitor.h @@ -103,7 +103,7 @@ struct cu_DeviceProperties cu_device_properties(struct cu_DeviceRef device); * Memory information of a device at one point in time. */ struct cu_DeviceMemoryProperties { - /// How much memory is available to this device at any given moment. + /// How much memory is available to this device at a given moment. size_t budget; /// How much memory is currently getting used from the device. size_t used; diff --git a/crates/memonitor-sys/cuda/src/memonitor.c b/crates/memonitor-sys/cuda/src/memonitor.c index 6b917b6..c43d2e9 100644 --- a/crates/memonitor-sys/cuda/src/memonitor.c +++ b/crates/memonitor-sys/cuda/src/memonitor.c @@ -102,12 +102,14 @@ struct cu_Devices cu_list_devices() { res = cuDeviceGet(&device_handles[d], d); if (res != 0) { free(device_handles); + free(ctx_handles); return invalid_devices; } res = cuCtxCreate(&ctx_handles[d], 0, device_handles[d]); if (res != 0) { free(device_handles); + free(ctx_handles); return invalid_devices; } } @@ -153,23 +155,19 @@ struct cu_DeviceProperties cu_device_properties(struct cu_DeviceRef device) { } CUdevice cast_device = device.handle; - char *name = NULL; - size_t total_memory = 0; + struct cu_DeviceProperties props = {0}; + props.kind = DiscreteGPU; - CUresult res = cuDeviceGetName(name, 256, cast_device); + CUresult res = cuDeviceGetName(props.name, sizeof(props.name), cast_device); if (res != 0) { return invalid_properties; } - res = cuDeviceTotalMem(&total_memory, cast_device); + res = cuDeviceTotalMem(&props.total_memory, cast_device); if (res != 0) { return invalid_properties; } - struct cu_DeviceProperties props = {0}; - strncpy_s(props.name, sizeof(props.name), name, 256U); - props.kind = DiscreteGPU; - props.total_memory = total_memory; return props; } diff --git a/crates/memonitor-sys/src/cuda.rs b/crates/memonitor-sys/src/cuda.rs index aaa5f47..f3b77d4 100644 --- a/crates/memonitor-sys/src/cuda.rs +++ b/crates/memonitor-sys/src/cuda.rs @@ -1,4 +1,4 @@ -//! Automatically generated bindings for the Vulkan backend. +//! Automatically generated bindings for the Cuda backend. #![allow(non_upper_case_globals)] #![allow(non_camel_case_types)] diff --git a/crates/memonitor/Cargo.toml b/crates/memonitor/Cargo.toml index 76fa581..b071a08 100644 --- a/crates/memonitor/Cargo.toml +++ b/crates/memonitor/Cargo.toml @@ -14,5 +14,6 @@ memonitor-sys = { path = "../memonitor-sys", version = "0.1.1", default-features sysinfo = "0.30.7" [features] -default = ["vulkan"] +default = ["vulkan", "cuda"] vulkan = ["memonitor-sys/vulkan"] +cuda = ["memonitor-sys/cuda"] diff --git a/crates/memonitor/src/cuda.rs b/crates/memonitor/src/cuda.rs index e69de29..cd1bb5c 100644 --- a/crates/memonitor/src/cuda.rs +++ b/crates/memonitor/src/cuda.rs @@ -0,0 +1,129 @@ +use std::ffi::CStr; +use std::ptr::addr_of_mut; + +use memonitor_sys::cuda; + +use crate::{ + BackendHandle, DeviceHandle, DeviceKind, GPUKind, MemoryStats, CUDA_NAME, VULKAN_NAME, +}; + +pub(super) struct Cuda { + handle: cuda::Devices, +} + +unsafe impl Send for Cuda {} + +unsafe impl Sync for Cuda {} + +impl Cuda { + pub(super) fn init() -> Option<(Self, Vec)> { + let res = unsafe { cuda::init() }; + if res == 0 { + let mut c_devices = unsafe { cuda::list_devices() }; + + if c_devices.count == 0 { + unsafe { + cuda::destroy_devices(addr_of_mut!(c_devices)); + cuda::term(); + } + return None; + } + + let mut devices = Vec::with_capacity(c_devices.count as usize); + for i in 0..c_devices.count { + let c_device = unsafe { cuda::get_device(addr_of_mut!(c_devices), i) }; + if c_device.handle.is_null() { + unsafe { + cuda::destroy_devices(addr_of_mut!(c_devices)); + cuda::term(); + }; + return None; + } + + let properties = unsafe { cuda::device_properties(c_device) }; + if properties.name[0] == 0 { + unsafe { + cuda::destroy_devices(addr_of_mut!(c_devices)); + cuda::term(); + }; + return None; + } + + let name = unsafe { CStr::from_ptr(properties.name.as_ptr()) }; + let kind = match properties.kind { + cuda::DeviceKind::IntegratedGPU => DeviceKind::GPU(GPUKind::Integrated), + cuda::DeviceKind::DiscreteGPU => DeviceKind::GPU(GPUKind::Discrete), + cuda::DeviceKind::Other => DeviceKind::Other, + _ => DeviceKind::Other, + }; + + if properties.total_memory == 0 { + continue; + } + + let device = CudaDevice { + handle: c_device, + name: name.to_string_lossy().to_string(), + kind, + memory: properties.total_memory, + }; + devices.push(device); + } + + let backend = Cuda { handle: c_devices }; + + Some((backend, devices)) + } else { + None + } + } +} + +impl BackendHandle for Cuda { + fn name(&self) -> &str { + CUDA_NAME + } +} + +impl Drop for Cuda { + fn drop(&mut self) { + unsafe { + cuda::destroy_devices(addr_of_mut!(self.handle)); + cuda::term(); + } + } +} + +pub(super) struct CudaDevice { + handle: cuda::DeviceRef, + name: String, + kind: DeviceKind, + memory: usize, +} + +unsafe impl Send for CudaDevice {} + +unsafe impl Sync for CudaDevice {} + +impl DeviceHandle for CudaDevice { + fn name(&self) -> &str { + &self.name + } + + fn kind(&self) -> DeviceKind { + self.kind + } + + fn backend_name(&self) -> &str { + VULKAN_NAME + } + + fn current_memory_stats(&self) -> MemoryStats { + let c_stats = unsafe { cuda::device_memory_properties(self.handle) }; + MemoryStats { + total: self.memory, + available: c_stats.budget, + used: c_stats.used, + } + } +} diff --git a/crates/memonitor/src/lib.rs b/crates/memonitor/src/lib.rs index 67bd4cf..8aceefe 100644 --- a/crates/memonitor/src/lib.rs +++ b/crates/memonitor/src/lib.rs @@ -49,12 +49,17 @@ pub const CPU_NAME: &str = "Host"; #[cfg(feature = "vulkan")] mod vulkan; -mod cuda; /// The name of the Vulkan backend. #[cfg(feature = "vulkan")] pub const VULKAN_NAME: &str = "Vulkan"; +mod cuda; + +/// The name of the Cuda backend. +#[cfg(feature = "vulkan")] +pub const CUDA_NAME: &str = "Cuda"; + static CONTEXT: RwLock = RwLock::new(Context::default()); struct Context { @@ -82,6 +87,11 @@ impl Context { if let Some((backend, devices)) = vulkan::Vulkan::init() { self.register_backend(backend, devices) } + + #[cfg(feature = "cuda")] + if let Some((backend, devices)) = cuda::Cuda::init() { + self.register_backend(backend, devices) + } } fn register_backend(&mut self, backend: B, mut devices: Vec) From 3ea0383a8474926f4619b0787c5f04b9ea31775f Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Mon, 1 Apr 2024 10:39:57 +0100 Subject: [PATCH 03/20] tracing and some corrections --- crates/memonitor-sys/cuda/src/memonitor.c | 28 +++++++++++++++------- crates/memonitor-sys/vulkan/CMakeLists.txt | 4 ---- crates/memonitor/Cargo.toml | 4 ++++ crates/memonitor/src/cuda.rs | 14 ++++++++++- crates/memonitor/src/lib.rs | 2 +- crates/memonitor/src/vulkan.rs | 4 ++++ crates/memonitor/tests/all.rs | 4 ++++ crates/memonitor/tests/common/mod.rs | 11 +++++++++ 8 files changed, 57 insertions(+), 14 deletions(-) create mode 100644 crates/memonitor/tests/common/mod.rs diff --git a/crates/memonitor-sys/cuda/src/memonitor.c b/crates/memonitor-sys/cuda/src/memonitor.c index c43d2e9..ce932be 100644 --- a/crates/memonitor-sys/cuda/src/memonitor.c +++ b/crates/memonitor-sys/cuda/src/memonitor.c @@ -1,5 +1,4 @@ #include -#include #include @@ -10,8 +9,8 @@ const char *LIB_NAME = "nvcuda.dll"; typedef int CUresult; struct CUctx_st; typedef struct CUctx_st *CUcontext; -struct CUdevice_v1; -typedef struct CUdevice_v1 *CUdevice; +typedef int CUdevice_v1; +typedef CUdevice_v1 *CUdevice; typedef CUresult(*cuInit_type)(unsigned int); @@ -31,6 +30,11 @@ typedef CUresult (*cuDeviceTotalMem_type)(size_t *, CUdevice); typedef CUresult (*cuMemGetInfo_type)(size_t *, size_t *); +struct Device { + CUdevice handle; + CUdevice_v1 inner; +}; + HMODULE module = NULL; cuInit_type cuInit = NULL; @@ -62,6 +66,8 @@ int cu_init() { CUresult res = cuInit(0); if (res != 0) { + FreeLibrary(module); + module = NULL; return -2; } @@ -96,17 +102,23 @@ struct cu_Devices cu_list_devices() { return invalid_devices; } - CUdevice *device_handles = malloc(sizeof(CUdevice) * count); - CUcontext *ctx_handles = malloc(sizeof(CUcontext) * count); + struct Device *device_handles = calloc(count, sizeof(struct Device)); + CUcontext *ctx_handles = calloc(count, sizeof(CUcontext)); for (int d = 0; d < count; d++) { - res = cuDeviceGet(&device_handles[d], d); + // This is very wrong and should never be done, but cuDeviceGet seems to be very badly documented in what it + // does, sometimes it changes the value, others it changes the pointer + device_handles[d].handle = &device_handles[d].inner; + res = cuDeviceGet(&device_handles[d].handle, d); if (res != 0) { free(device_handles); free(ctx_handles); return invalid_devices; } - res = cuCtxCreate(&ctx_handles[d], 0, device_handles[d]); + char name[256]; + cuDeviceGetName(name, sizeof(name), device_handles[d].handle); + res = cuCtxCreate(&ctx_handles[d], 0, device_handles[d].handle); + cuDeviceGetName(name, sizeof(name), device_handles[d].handle); if (res != 0) { free(device_handles); free(ctx_handles); @@ -142,7 +154,7 @@ struct cu_DeviceRef cu_get_device(struct cu_Devices *devices, uint32_t index) { return invalid_ref; } - CUcontext *cast_devices = devices->devices_handle; + CUdevice *cast_devices = devices->devices_handle; CUcontext *cast_ctxs = devices->ctx_handle; struct cu_DeviceRef ref = {cast_devices[index], cast_ctxs[index]}; return ref; diff --git a/crates/memonitor-sys/vulkan/CMakeLists.txt b/crates/memonitor-sys/vulkan/CMakeLists.txt index b17fb83..a50fedf 100644 --- a/crates/memonitor-sys/vulkan/CMakeLists.txt +++ b/crates/memonitor-sys/vulkan/CMakeLists.txt @@ -2,10 +2,6 @@ cmake_minimum_required(VERSION 3.5) project(memonitor-vk LANGUAGES C) -if (WIN32) - set(VOLK_STATIC_DEFINES VK_USE_PLATFORM_WIN32_KHR) -endif () - set(VULKAN_HEADERS_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/Vulkan-Headers") add_subdirectory(thirdparty/volk) diff --git a/crates/memonitor/Cargo.toml b/crates/memonitor/Cargo.toml index b071a08..6b59714 100644 --- a/crates/memonitor/Cargo.toml +++ b/crates/memonitor/Cargo.toml @@ -12,6 +12,10 @@ publish = true [dependencies] memonitor-sys = { path = "../memonitor-sys", version = "0.1.1", default-features = false } sysinfo = "0.30.7" +tracing = "0.1.40" + +[dev-dependencies] +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } [features] default = ["vulkan", "cuda"] diff --git a/crates/memonitor/src/cuda.rs b/crates/memonitor/src/cuda.rs index cd1bb5c..c0b7928 100644 --- a/crates/memonitor/src/cuda.rs +++ b/crates/memonitor/src/cuda.rs @@ -1,5 +1,6 @@ use std::ffi::CStr; use std::ptr::addr_of_mut; +use tracing::debug; use memonitor_sys::cuda; @@ -18,10 +19,12 @@ unsafe impl Sync for Cuda {} impl Cuda { pub(super) fn init() -> Option<(Self, Vec)> { let res = unsafe { cuda::init() }; + if res == 0 { let mut c_devices = unsafe { cuda::list_devices() }; if c_devices.count == 0 { + debug!("No Cuda devices found."); unsafe { cuda::destroy_devices(addr_of_mut!(c_devices)); cuda::term(); @@ -32,7 +35,8 @@ impl Cuda { let mut devices = Vec::with_capacity(c_devices.count as usize); for i in 0..c_devices.count { let c_device = unsafe { cuda::get_device(addr_of_mut!(c_devices), i) }; - if c_device.handle.is_null() { + if c_device.ctx_handle.is_null() { + debug!("Invalid device handle."); unsafe { cuda::destroy_devices(addr_of_mut!(c_devices)); cuda::term(); @@ -42,6 +46,7 @@ impl Cuda { let properties = unsafe { cuda::device_properties(c_device) }; if properties.name[0] == 0 { + debug!("Invalid device name."); unsafe { cuda::destroy_devices(addr_of_mut!(c_devices)); cuda::term(); @@ -58,6 +63,7 @@ impl Cuda { }; if properties.total_memory == 0 { + debug!("Invalid amount of memory."); continue; } @@ -74,6 +80,12 @@ impl Cuda { Some((backend, devices)) } else { + match res { + -1 => debug!("Could not find Cuda driver module."), + -2 => debug!("Failed to initialise Cuda context."), + _ => {} + } + None } } diff --git a/crates/memonitor/src/lib.rs b/crates/memonitor/src/lib.rs index 8aceefe..a13d8e9 100644 --- a/crates/memonitor/src/lib.rs +++ b/crates/memonitor/src/lib.rs @@ -144,7 +144,7 @@ pub fn list_backends() -> SliceGuard<'static, Backend, RangeFull> { } } -/// Returns a slice containing containing *every* [`Device`] found. +/// Returns a slice containing *every* [`Device`] found. /// Depending on the [`Backend`]s present, there may be several representations for the same hardware device. /// /// The contents should always be identical after [`init`] has been called. diff --git a/crates/memonitor/src/vulkan.rs b/crates/memonitor/src/vulkan.rs index 7367cbf..312529c 100644 --- a/crates/memonitor/src/vulkan.rs +++ b/crates/memonitor/src/vulkan.rs @@ -1,5 +1,6 @@ use std::ffi::CStr; use std::ptr::addr_of_mut; +use tracing::debug; use memonitor_sys::vulkan; @@ -29,6 +30,7 @@ impl Vulkan { let c_device = unsafe { vulkan::get_device(addr_of_mut!(c_devices), i) }; if c_device.handle.is_null() { unsafe { + debug!("Invalid device handle."); vulkan::destroy_devices(addr_of_mut!(c_devices)); vulkan::term(); }; @@ -38,6 +40,7 @@ impl Vulkan { let properties = unsafe { vulkan::device_properties(c_device) }; if properties.name[0] == 0 { unsafe { + debug!("Invalid device name."); vulkan::destroy_devices(addr_of_mut!(c_devices)); vulkan::term(); }; @@ -45,6 +48,7 @@ impl Vulkan { } if properties.total_memory == 0 { + debug!("Invalid amount of memory."); continue; } diff --git a/crates/memonitor/tests/all.rs b/crates/memonitor/tests/all.rs index c0c2971..68c616b 100644 --- a/crates/memonitor/tests/all.rs +++ b/crates/memonitor/tests/all.rs @@ -1,7 +1,11 @@ use memonitor::{init, list_all_devices, list_backends}; +mod common; + #[test] fn all() { + common::init_tracing(); + init(); for backend in list_backends().iter() { diff --git a/crates/memonitor/tests/common/mod.rs b/crates/memonitor/tests/common/mod.rs new file mode 100644 index 0000000..ff7e59d --- /dev/null +++ b/crates/memonitor/tests/common/mod.rs @@ -0,0 +1,11 @@ +use tracing_subscriber::filter::LevelFilter; +use tracing_subscriber::layer::SubscriberExt; +use tracing_subscriber::util::SubscriberInitExt; +use tracing_subscriber::{fmt, registry, EnvFilter}; + +pub fn init_tracing() { + let format = fmt::layer().pretty(); + let filter = EnvFilter::try_from_default_env() + .unwrap_or(EnvFilter::default().add_directive(LevelFilter::TRACE.into())); + registry().with(format).with(filter).init(); +} From a84ea6dbbd7715b615b4246d2916ac5eed654230 Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Mon, 1 Apr 2024 10:45:47 +0100 Subject: [PATCH 04/20] updated gitignore --- .gitignore | 4 - Cargo.lock | 639 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 639 insertions(+), 4 deletions(-) create mode 100644 Cargo.lock diff --git a/.gitignore b/.gitignore index bc1e029..00762f1 100644 --- a/.gitignore +++ b/.gitignore @@ -3,10 +3,6 @@ debug/ target/ -# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries -# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html -Cargo.lock - # These are backup files generated by rustfmt **/*.rs.bk diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..e28ebb7 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,639 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "bindgen" +version = "0.69.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", + "which", +] + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "cc" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clang-sys" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "cmake" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +dependencies = [ + "cc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "either" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libloading" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +dependencies = [ + "cfg-if", + "windows-targets", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "memonitor" +version = "0.1.1" +dependencies = [ + "memonitor-sys", + "sysinfo", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "memonitor-sys" +version = "0.1.1" +dependencies = [ + "bindgen", + "cmake", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "prettyplease" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.3", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.38.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "syn" +version = "2.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sysinfo" +version = "0.30.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c385888ef380a852a16209afc8cfad22795dd8873d69c9a14d2e2088f118d18" +dependencies = [ + "cfg-if", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "rayon", + "windows", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core", + "windows-targets", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" From 086a9396250a5f02916f9d2bf2192e42ca193859 Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Mon, 1 Apr 2024 11:24:51 +0100 Subject: [PATCH 05/20] refactor and several fixes --- .gitignore | 2 +- crates/memonitor-sys/cuda/src/memonitor.c | 3 -- crates/memonitor/src/cpu.rs | 10 ++++-- crates/memonitor/src/cuda.rs | 20 ++++++----- crates/memonitor/src/lib.rs | 43 +++++++++++++++++------ crates/memonitor/src/vulkan.rs | 22 ++++++++---- crates/memonitor/tests/all.rs | 3 +- 7 files changed, 69 insertions(+), 34 deletions(-) diff --git a/.gitignore b/.gitignore index 00762f1..215f154 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,4 @@ target/ .devenv .direnv .envrc -build +build/ diff --git a/crates/memonitor-sys/cuda/src/memonitor.c b/crates/memonitor-sys/cuda/src/memonitor.c index ce932be..1193c03 100644 --- a/crates/memonitor-sys/cuda/src/memonitor.c +++ b/crates/memonitor-sys/cuda/src/memonitor.c @@ -115,10 +115,7 @@ struct cu_Devices cu_list_devices() { return invalid_devices; } - char name[256]; - cuDeviceGetName(name, sizeof(name), device_handles[d].handle); res = cuCtxCreate(&ctx_handles[d], 0, device_handles[d].handle); - cuDeviceGetName(name, sizeof(name), device_handles[d].handle); if (res != 0) { free(device_handles); free(ctx_handles); diff --git a/crates/memonitor/src/cpu.rs b/crates/memonitor/src/cpu.rs index e7dc469..70cc5a1 100644 --- a/crates/memonitor/src/cpu.rs +++ b/crates/memonitor/src/cpu.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; use std::sync::{Arc, RwLock}; use sysinfo::{CpuRefreshKind, MemoryRefreshKind, RefreshKind, System}; -use crate::{BackendHandle, DeviceHandle, DeviceKind, MemoryStats, CPU_NAME}; +use crate::{BackendHandle, BackendId, DeviceHandle, DeviceKind, MemoryStats, CPU_NAME}; pub(super) struct Host { _system: Arc>, @@ -46,6 +46,10 @@ impl BackendHandle for Host { fn name(&self) -> &str { CPU_NAME } + + fn id(&self) -> BackendId { + BackendId::CPU + } } pub(super) struct Cpu { @@ -63,8 +67,8 @@ impl DeviceHandle for Cpu { DeviceKind::CPU } - fn backend_name(&self) -> &str { - CPU_NAME + fn backend(&self) -> BackendId { + BackendId::CPU } fn current_memory_stats(&self) -> MemoryStats { diff --git a/crates/memonitor/src/cuda.rs b/crates/memonitor/src/cuda.rs index c0b7928..9a50192 100644 --- a/crates/memonitor/src/cuda.rs +++ b/crates/memonitor/src/cuda.rs @@ -4,9 +4,7 @@ use tracing::debug; use memonitor_sys::cuda; -use crate::{ - BackendHandle, DeviceHandle, DeviceKind, GPUKind, MemoryStats, CUDA_NAME, VULKAN_NAME, -}; +use crate::{BackendHandle, BackendId, DeviceHandle, DeviceKind, GPUKind, MemoryStats, CUDA_NAME}; pub(super) struct Cuda { handle: cuda::Devices, @@ -24,7 +22,7 @@ impl Cuda { let mut c_devices = unsafe { cuda::list_devices() }; if c_devices.count == 0 { - debug!("No Cuda devices found."); + debug!("No Cuda devices found. Aborting CUDA initialisation."); unsafe { cuda::destroy_devices(addr_of_mut!(c_devices)); cuda::term(); @@ -36,7 +34,7 @@ impl Cuda { for i in 0..c_devices.count { let c_device = unsafe { cuda::get_device(addr_of_mut!(c_devices), i) }; if c_device.ctx_handle.is_null() { - debug!("Invalid device handle."); + debug!("Invalid device handle. Aborting CUDA initialisation."); unsafe { cuda::destroy_devices(addr_of_mut!(c_devices)); cuda::term(); @@ -46,7 +44,7 @@ impl Cuda { let properties = unsafe { cuda::device_properties(c_device) }; if properties.name[0] == 0 { - debug!("Invalid device name."); + debug!("Invalid device name. Aborting CUDA initialisation."); unsafe { cuda::destroy_devices(addr_of_mut!(c_devices)); cuda::term(); @@ -83,7 +81,7 @@ impl Cuda { match res { -1 => debug!("Could not find Cuda driver module."), -2 => debug!("Failed to initialise Cuda context."), - _ => {} + _ => unreachable!("Unhandled error."), } None @@ -95,6 +93,10 @@ impl BackendHandle for Cuda { fn name(&self) -> &str { CUDA_NAME } + + fn id(&self) -> BackendId { + BackendId::CUDA + } } impl Drop for Cuda { @@ -126,8 +128,8 @@ impl DeviceHandle for CudaDevice { self.kind } - fn backend_name(&self) -> &str { - VULKAN_NAME + fn backend(&self) -> BackendId { + BackendId::CUDA } fn current_memory_stats(&self) -> MemoryStats { diff --git a/crates/memonitor/src/lib.rs b/crates/memonitor/src/lib.rs index a13d8e9..4edd51d 100644 --- a/crates/memonitor/src/lib.rs +++ b/crates/memonitor/src/lib.rs @@ -44,21 +44,38 @@ use std::sync::{RwLock, RwLockReadGuard}; mod cpu; -/// The name of the always present CPU backend. -pub const CPU_NAME: &str = "Host"; - #[cfg(feature = "vulkan")] mod vulkan; +#[cfg(feature = "cuda")] +mod cuda; + +/// A backend identifier. +#[non_exhaustive] +#[derive(Debug, Eq, PartialEq)] +pub enum BackendId { + /// The CPU or host backend identifier. + CPU, + + /// The Vulkan backend identifier. + #[cfg(feature = "vulkan")] + Vulkan, + + /// The CUDA backend identifier. + #[cfg(feature = "cuda")] + CUDA, +} + +/// The name of the always present CPU backend. +pub const CPU_NAME: &str = "Host"; + /// The name of the Vulkan backend. #[cfg(feature = "vulkan")] pub const VULKAN_NAME: &str = "Vulkan"; -mod cuda; - /// The name of the Cuda backend. -#[cfg(feature = "vulkan")] -pub const CUDA_NAME: &str = "Cuda"; +#[cfg(feature = "cuda")] +pub const CUDA_NAME: &str = "CUDA"; static CONTEXT: RwLock = RwLock::new(Context::default()); @@ -134,7 +151,10 @@ pub fn init() { /// Returns a slice containing every [`Backend`] found. /// -/// The contents should always be identical after [`init`] has been called. +/// The contents should always be identical. +/// +/// If any backend is not listed, it is either because its respective feature was not enabled, or +/// because its respective library/framework was not found in the system. pub fn list_backends() -> SliceGuard<'static, Backend, RangeFull> { let guard = CONTEXT.read().unwrap(); SliceGuard { @@ -199,6 +219,9 @@ where pub trait BackendHandle: Send + Sync { /// Returns the name of this backend. fn name(&self) -> &str; + + /// Returns the identifier of this backend. + fn id(&self) -> BackendId; } /// High-level abstraction over a backend. @@ -292,8 +315,8 @@ pub trait DeviceHandle: Send + Sync { /// Return the hardware type of this device. fn kind(&self) -> DeviceKind; - /// Return the name of the [`Backend`] that owns this device handle. - fn backend_name(&self) -> &str; + /// Return the identifier of the [`Backend`] that owns this device handle. + fn backend(&self) -> BackendId; /// Return the memory statistics of this device at this point in time. fn current_memory_stats(&self) -> MemoryStats; diff --git a/crates/memonitor/src/vulkan.rs b/crates/memonitor/src/vulkan.rs index 312529c..429f8d1 100644 --- a/crates/memonitor/src/vulkan.rs +++ b/crates/memonitor/src/vulkan.rs @@ -1,10 +1,12 @@ use std::ffi::CStr; use std::ptr::addr_of_mut; -use tracing::debug; +use tracing::{debug, info}; use memonitor_sys::vulkan; -use crate::{BackendHandle, DeviceHandle, DeviceKind, GPUKind, MemoryStats, VULKAN_NAME}; +use crate::{ + BackendHandle, BackendId, DeviceHandle, DeviceKind, GPUKind, MemoryStats, VULKAN_NAME, +}; pub(super) struct Vulkan { handle: vulkan::Devices, @@ -21,6 +23,7 @@ impl Vulkan { let mut c_devices = unsafe { vulkan::list_devices() }; if c_devices.handle.is_null() { + debug!("No Vulkan devices found. Aborting Vulkan initialisation."); unsafe { vulkan::term() }; return None; } @@ -29,8 +32,8 @@ impl Vulkan { for i in 0..c_devices.count { let c_device = unsafe { vulkan::get_device(addr_of_mut!(c_devices), i) }; if c_device.handle.is_null() { + debug!("Invalid device handle. Aborting Vulkan initialisation."); unsafe { - debug!("Invalid device handle."); vulkan::destroy_devices(addr_of_mut!(c_devices)); vulkan::term(); }; @@ -39,8 +42,8 @@ impl Vulkan { let properties = unsafe { vulkan::device_properties(c_device) }; if properties.name[0] == 0 { + debug!("Invalid device name. Aborting Vulkan initialisation."); unsafe { - debug!("Invalid device name."); vulkan::destroy_devices(addr_of_mut!(c_devices)); vulkan::term(); }; @@ -48,7 +51,7 @@ impl Vulkan { } if properties.total_memory == 0 { - debug!("Invalid amount of memory."); + debug!("Invalid amount of memory. Skipping this device."); continue; } @@ -75,6 +78,7 @@ impl Vulkan { Some((backend, devices)) } else { + info!("Vulkan runtime not found."); None } } @@ -84,6 +88,10 @@ impl BackendHandle for Vulkan { fn name(&self) -> &str { VULKAN_NAME } + + fn id(&self) -> BackendId { + BackendId::Vulkan + } } impl Drop for Vulkan { @@ -115,8 +123,8 @@ impl DeviceHandle for VulkanDevice { self.kind } - fn backend_name(&self) -> &str { - VULKAN_NAME + fn backend(&self) -> BackendId { + BackendId::Vulkan } fn current_memory_stats(&self) -> MemoryStats { diff --git a/crates/memonitor/tests/all.rs b/crates/memonitor/tests/all.rs index 68c616b..550f5f9 100644 --- a/crates/memonitor/tests/all.rs +++ b/crates/memonitor/tests/all.rs @@ -15,8 +15,9 @@ fn all() { for device in list_all_devices().iter() { let stats = device.current_memory_stats(); println!( - "Device found: {} ({}) - Memory stats: {} bytes used out of {}, {} are free", + "Device found: {} @ {:?} ({}) - Memory stats: {} bytes used out of {}, {} are free", device.name(), + device.backend(), device.kind(), stats.used, stats.total, From 907d875d4b0721812501648dce33f124021563c1 Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Mon, 1 Apr 2024 12:08:35 +0100 Subject: [PATCH 06/20] use once_cell instead of init function --- Cargo.lock | 1 + crates/memonitor/Cargo.toml | 1 + crates/memonitor/src/lib.rs | 20 +++++++------------- crates/memonitor/tests/all.rs | 4 +--- crates/memonitor/tests/cpu.rs | 6 ++++-- crates/memonitor/tests/vulkan.rs | 6 ++++-- 6 files changed, 18 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e28ebb7..3f7e67d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -212,6 +212,7 @@ name = "memonitor" version = "0.1.1" dependencies = [ "memonitor-sys", + "once_cell", "sysinfo", "tracing", "tracing-subscriber", diff --git a/crates/memonitor/Cargo.toml b/crates/memonitor/Cargo.toml index 6b59714..d94d4ec 100644 --- a/crates/memonitor/Cargo.toml +++ b/crates/memonitor/Cargo.toml @@ -11,6 +11,7 @@ publish = true [dependencies] memonitor-sys = { path = "../memonitor-sys", version = "0.1.1", default-features = false } +once_cell = "1.19.0" sysinfo = "0.30.7" tracing = "0.1.40" diff --git a/crates/memonitor/src/lib.rs b/crates/memonitor/src/lib.rs index 4edd51d..46839b0 100644 --- a/crates/memonitor/src/lib.rs +++ b/crates/memonitor/src/lib.rs @@ -8,10 +8,7 @@ //! # Example //! //! ``` -//! use memonitor::{init, list_all_devices, list_backends}; -//! -//! // Initialise global context -//! init(); +//! use memonitor::{list_all_devices, list_backends}; //! //! // Print every backend that has been found //! for backend in list_backends().iter() { @@ -38,6 +35,7 @@ #![warn(missing_docs)] +use once_cell::sync::Lazy; use std::fmt::{Display, Formatter}; use std::ops::{Deref, RangeBounds, RangeFull}; use std::sync::{RwLock, RwLockReadGuard}; @@ -77,7 +75,11 @@ pub const VULKAN_NAME: &str = "Vulkan"; #[cfg(feature = "cuda")] pub const CUDA_NAME: &str = "CUDA"; -static CONTEXT: RwLock = RwLock::new(Context::default()); +static CONTEXT: Lazy> = Lazy::new(|| { + let ctx = RwLock::new(Context::default()); + ctx.write().unwrap().init(); + ctx +}); struct Context { backends: Vec, @@ -141,14 +143,6 @@ impl Context { } } -// TODO use OnceLock/OnceCell instead of forcing users to call this -/// Initialize the context. This **MUST** be called before any other functions. -/// -/// This function is ideally called at the start of execution. If already called at least once, does nothing. -pub fn init() { - CONTEXT.write().unwrap().init(); -} - /// Returns a slice containing every [`Backend`] found. /// /// The contents should always be identical. diff --git a/crates/memonitor/tests/all.rs b/crates/memonitor/tests/all.rs index 550f5f9..c748dff 100644 --- a/crates/memonitor/tests/all.rs +++ b/crates/memonitor/tests/all.rs @@ -1,4 +1,4 @@ -use memonitor::{init, list_all_devices, list_backends}; +use memonitor::{list_all_devices, list_backends}; mod common; @@ -6,8 +6,6 @@ mod common; fn all() { common::init_tracing(); - init(); - for backend in list_backends().iter() { println!("Backend found: {}", backend.name()); } diff --git a/crates/memonitor/tests/cpu.rs b/crates/memonitor/tests/cpu.rs index 4d051e7..e76a63b 100644 --- a/crates/memonitor/tests/cpu.rs +++ b/crates/memonitor/tests/cpu.rs @@ -1,8 +1,10 @@ -use memonitor::{init, list_all_devices, list_backends}; +use memonitor::{list_all_devices, list_backends}; + +mod common; #[test] fn cpu() { - init(); + common::init_tracing(); let device_ids = { let backends = list_backends(); diff --git a/crates/memonitor/tests/vulkan.rs b/crates/memonitor/tests/vulkan.rs index a9c9c4c..9569bcb 100644 --- a/crates/memonitor/tests/vulkan.rs +++ b/crates/memonitor/tests/vulkan.rs @@ -1,8 +1,10 @@ -use memonitor::{init, list_all_devices, list_backends}; +use memonitor::{list_all_devices, list_backends}; + +mod common; #[test] fn vulkan() { - init(); + common::init_tracing(); let device_ids = { let backends = list_backends(); From e97c1e08e3aff95517df3a8693aa1e1ac035379d Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Mon, 1 Apr 2024 12:49:04 +0100 Subject: [PATCH 07/20] multi platform build --- crates/memonitor-sys/cuda/src/memonitor.c | 23 +++++++++++++++++---- crates/memonitor-sys/vulkan/src/memonitor.c | 2 ++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/crates/memonitor-sys/cuda/src/memonitor.c b/crates/memonitor-sys/cuda/src/memonitor.c index 1193c03..990cd23 100644 --- a/crates/memonitor-sys/cuda/src/memonitor.c +++ b/crates/memonitor-sys/cuda/src/memonitor.c @@ -1,10 +1,16 @@ #include -#include - #include -const char *LIB_NAME = "nvcuda.dll"; +#ifdef _WIN32 + +#include + +#elif defined(__APPLE__) +// nothing +#else +include +#endif typedef int CUresult; struct CUctx_st; @@ -49,10 +55,19 @@ cuMemGetInfo_type cuMemGetInfo = NULL; int cu_init() { - module = LoadLibraryA(LIB_NAME); +#ifdef _WIN32 + module = LoadLibraryA("nvcuda.dll"); + if (!module) { + return -1; + } +#elif defined(__APPLE__) + return -1; +#else + module = dlopen("libcuda.so", RTLD_NOW | RTLD_LOCAL); if (!module) { return -1; } +#endif cuInit = (cuInit_type) GetProcAddress(module, "cuInit"); cuCtxCreate = (cuCtxCreate_type) GetProcAddress(module, "cuCtxCreate"); diff --git a/crates/memonitor-sys/vulkan/src/memonitor.c b/crates/memonitor-sys/vulkan/src/memonitor.c index 280354a..e551c47 100644 --- a/crates/memonitor-sys/vulkan/src/memonitor.c +++ b/crates/memonitor-sys/vulkan/src/memonitor.c @@ -1,3 +1,5 @@ +#define __STDC_WANT_LIB_EXT1__ 1 + #include #include From 551579636b10bf503268ce1f9b2572edaa58506b Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Mon, 1 Apr 2024 12:53:19 +0100 Subject: [PATCH 08/20] set C standard to 11 for Vulkan backend --- crates/memonitor-sys/vulkan/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/memonitor-sys/vulkan/CMakeLists.txt b/crates/memonitor-sys/vulkan/CMakeLists.txt index a50fedf..7932b73 100644 --- a/crates/memonitor-sys/vulkan/CMakeLists.txt +++ b/crates/memonitor-sys/vulkan/CMakeLists.txt @@ -10,6 +10,7 @@ option(MEMONITOR_VALIDATE "Use Vulkan validation layers" OFF) add_library(memonitor-vk STATIC "include/memonitor.h" "src/memonitor.c") target_include_directories(memonitor-vk PUBLIC "include") target_link_libraries(memonitor-vk PRIVATE volk) +set_property(TARGET memonitor-vk PROPERTY C_STANDARD 11) if (MEMONITOR_VALIDATE) target_compile_definitions(memonitor-vk PUBLIC USE_VALIDATION_LAYERS) From 943a8fcca4eee1ff5a97a34f7fd7dbf9e0921382 Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Mon, 1 Apr 2024 12:59:47 +0100 Subject: [PATCH 09/20] set C standard to 11 for Vulkan backend 2 --- crates/memonitor-sys/vulkan/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/memonitor-sys/vulkan/CMakeLists.txt b/crates/memonitor-sys/vulkan/CMakeLists.txt index 7932b73..211d50a 100644 --- a/crates/memonitor-sys/vulkan/CMakeLists.txt +++ b/crates/memonitor-sys/vulkan/CMakeLists.txt @@ -1,5 +1,8 @@ cmake_minimum_required(VERSION 3.5) +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED true) + project(memonitor-vk LANGUAGES C) set(VULKAN_HEADERS_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/Vulkan-Headers") @@ -10,7 +13,6 @@ option(MEMONITOR_VALIDATE "Use Vulkan validation layers" OFF) add_library(memonitor-vk STATIC "include/memonitor.h" "src/memonitor.c") target_include_directories(memonitor-vk PUBLIC "include") target_link_libraries(memonitor-vk PRIVATE volk) -set_property(TARGET memonitor-vk PROPERTY C_STANDARD 11) if (MEMONITOR_VALIDATE) target_compile_definitions(memonitor-vk PUBLIC USE_VALIDATION_LAYERS) From bb5a756d1c169ed07a1635394fdb4473f5a7b777 Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Mon, 1 Apr 2024 13:31:59 +0100 Subject: [PATCH 10/20] set C standard to 11 for Vulkan backend 3 --- crates/memonitor-sys/build.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/memonitor-sys/build.rs b/crates/memonitor-sys/build.rs index 6cd5dca..8fa8317 100644 --- a/crates/memonitor-sys/build.rs +++ b/crates/memonitor-sys/build.rs @@ -23,7 +23,8 @@ fn main() { build.define("MEMONITOR_VALIDATE", "ON"); } - let lib_out = build.build(); + // cmake-rs overrides the standard configured inside CMakeLists for some reason + let lib_out = build.cflag("-std=c11").build(); println!( "cargo:rustc-link-search=native={}", lib_out.join("lib").display() From 65943340beb357403a9f4b7a321750a2cadea3b4 Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Mon, 1 Apr 2024 13:42:38 +0100 Subject: [PATCH 11/20] use strncpy on every platform --- crates/memonitor-sys/build.rs | 2 +- crates/memonitor-sys/vulkan/src/memonitor.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/memonitor-sys/build.rs b/crates/memonitor-sys/build.rs index 8fa8317..411cc80 100644 --- a/crates/memonitor-sys/build.rs +++ b/crates/memonitor-sys/build.rs @@ -24,7 +24,7 @@ fn main() { } // cmake-rs overrides the standard configured inside CMakeLists for some reason - let lib_out = build.cflag("-std=c11").build(); + let lib_out = build.build(); println!( "cargo:rustc-link-search=native={}", lib_out.join("lib").display() diff --git a/crates/memonitor-sys/vulkan/src/memonitor.c b/crates/memonitor-sys/vulkan/src/memonitor.c index e551c47..62d011e 100644 --- a/crates/memonitor-sys/vulkan/src/memonitor.c +++ b/crates/memonitor-sys/vulkan/src/memonitor.c @@ -1,5 +1,3 @@ -#define __STDC_WANT_LIB_EXT1__ 1 - #include #include @@ -251,7 +249,9 @@ struct vk_DeviceProperties vk_device_properties(struct vk_DeviceRef device) { } struct vk_DeviceProperties ret_props = {0}; - strncpy_s(ret_props.name, sizeof(ret_props.name), properties.properties.deviceName, 256U); + // strncpy is unsafe, but should never fail here + // not using strncpy_s because can't set C standard with cmake-rs as of 4/1/2024 + strncpy(ret_props.name, properties.properties.deviceName, 256U); ret_props.kind = kind; ret_props.total_memory = memory; return ret_props; From c1aacf76e1c6076a5d4cfdea5ed0700557260e8e Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Mon, 1 Apr 2024 13:45:04 +0100 Subject: [PATCH 12/20] fix typo in include --- crates/memonitor-sys/cuda/src/memonitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/memonitor-sys/cuda/src/memonitor.c b/crates/memonitor-sys/cuda/src/memonitor.c index 990cd23..bffc12c 100644 --- a/crates/memonitor-sys/cuda/src/memonitor.c +++ b/crates/memonitor-sys/cuda/src/memonitor.c @@ -9,7 +9,7 @@ #elif defined(__APPLE__) // nothing #else -include +#include #endif typedef int CUresult; From 9b827952c7af96594df1ecf9670035899228d7fb Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Mon, 1 Apr 2024 13:51:27 +0100 Subject: [PATCH 13/20] multi-platform build fixes --- crates/memonitor-sys/cuda/src/memonitor.c | 31 ++++++++++++++++------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/crates/memonitor-sys/cuda/src/memonitor.c b/crates/memonitor-sys/cuda/src/memonitor.c index bffc12c..6ad5e2c 100644 --- a/crates/memonitor-sys/cuda/src/memonitor.c +++ b/crates/memonitor-sys/cuda/src/memonitor.c @@ -6,10 +6,13 @@ #include +typedef HMODULE mod_type; #elif defined(__APPLE__) // nothing #else #include + +typedef void* mod_type; #endif typedef int CUresult; @@ -41,7 +44,7 @@ struct Device { CUdevice_v1 inner; }; -HMODULE module = NULL; +mod_type module = NULL; cuInit_type cuInit = NULL; cuCtxCreate_type cuCtxCreate = NULL; @@ -60,14 +63,6 @@ int cu_init() { if (!module) { return -1; } -#elif defined(__APPLE__) - return -1; -#else - module = dlopen("libcuda.so", RTLD_NOW | RTLD_LOCAL); - if (!module) { - return -1; - } -#endif cuInit = (cuInit_type) GetProcAddress(module, "cuInit"); cuCtxCreate = (cuCtxCreate_type) GetProcAddress(module, "cuCtxCreate"); @@ -78,6 +73,24 @@ int cu_init() { cuDeviceGetName = (cuDeviceGetName_type) GetProcAddress(module, "cuDeviceGetName"); cuDeviceTotalMem = (cuDeviceTotalMem_type) GetProcAddress(module, "cuDeviceTotalMem"); cuMemGetInfo = (cuMemGetInfo_type) GetProcAddress(module, "cuMemGetInfo"); +#elif defined(__APPLE__) + return -1; +#else + module = dlopen("libcuda.so", RTLD_NOW | RTLD_LOCAL); + if (!module) { + return -1; + } + + cuInit = (cuInit_type) dlsym(module, "cuInit"); + cuCtxCreate = (cuCtxCreate_type) dlsym(module, "cuCtxCreate"); + cuCtxDestroy = (cuCtxDestroy_type) dlsym(module, "cuCtxDestroy"); + cuCtxSetCurrent = (cuCtxSetCurrent_type) dlsym(module, "cuCtxSetCurrent"); + cuDeviceGetCount = (cuDeviceGetCount_type) dlsym(module, "cuDeviceGetCount"); + cuDeviceGet = (cuDeviceGet_type) dlsym(module, "cuDeviceGet"); + cuDeviceGetName = (cuDeviceGetName_type) dlsym(module, "cuDeviceGetName"); + cuDeviceTotalMem = (cuDeviceTotalMem_type) dlsym(module, "cuDeviceTotalMem"); + cuMemGetInfo = (cuMemGetInfo_type) dlsym(module, "cuMemGetInfo"); +#endif CUresult res = cuInit(0); if (res != 0) { From 3de34d327768ef86a8d6f3f01aa880365fd2a3be Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Mon, 1 Apr 2024 13:54:51 +0100 Subject: [PATCH 14/20] multi-platform build fixes 2 --- crates/memonitor-sys/cuda/src/memonitor.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/memonitor-sys/cuda/src/memonitor.c b/crates/memonitor-sys/cuda/src/memonitor.c index 6ad5e2c..cb8db26 100644 --- a/crates/memonitor-sys/cuda/src/memonitor.c +++ b/crates/memonitor-sys/cuda/src/memonitor.c @@ -94,7 +94,11 @@ int cu_init() { CUresult res = cuInit(0); if (res != 0) { +#ifdef _WIN32 FreeLibrary(module); +#else + dlclose(module); +#endif module = NULL; return -2; } @@ -103,7 +107,11 @@ int cu_init() { } void cu_term() { +#ifdef _WIN32 FreeLibrary(module); +#else + dlclose(module); +#endif module = NULL; cuInit = NULL; From b551fb3adee9d829d27df6e8f4bb01e380ce51a2 Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Mon, 1 Apr 2024 13:57:43 +0100 Subject: [PATCH 15/20] multi-platform build fixes 3 --- crates/memonitor-sys/cuda/src/memonitor.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/memonitor-sys/cuda/src/memonitor.c b/crates/memonitor-sys/cuda/src/memonitor.c index cb8db26..f062c90 100644 --- a/crates/memonitor-sys/cuda/src/memonitor.c +++ b/crates/memonitor-sys/cuda/src/memonitor.c @@ -7,8 +7,6 @@ #include typedef HMODULE mod_type; -#elif defined(__APPLE__) -// nothing #else #include From d4e137574f8fc8e5607e55be8c2325d020185518 Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Mon, 1 Apr 2024 14:53:59 +0100 Subject: [PATCH 16/20] update README.md and disable cuda on macOS --- Cargo.lock | 8 ++++++++ Cargo.toml | 1 + README.md | 2 +- crates/memonitor-sys/Cargo.toml | 2 +- crates/memonitor-sys/build.rs | 7 ++++++- crates/memonitor-sys/src/lib.rs | 2 +- crates/memonitor/Cargo.toml | 3 +++ crates/memonitor/build.rs | 7 +++++++ crates/memonitor/src/lib.rs | 6 +++--- 9 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 crates/memonitor/build.rs diff --git a/Cargo.lock b/Cargo.lock index 3f7e67d..2fc31d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,6 +61,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e53693616d3075149f4ead59bdeecd204ac6b8192d8969757601b74bddf00f" + [[package]] name = "clang-sys" version = "1.7.0" @@ -211,6 +217,7 @@ checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" name = "memonitor" version = "0.1.1" dependencies = [ + "cfg_aliases", "memonitor-sys", "once_cell", "sysinfo", @@ -223,6 +230,7 @@ name = "memonitor-sys" version = "0.1.1" dependencies = [ "bindgen", + "cfg_aliases", "cmake", ] diff --git a/Cargo.toml b/Cargo.toml index 36c51e3..1148ec3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,4 @@ members = [ ] [workspace.dependencies] +cfg_aliases = "0.2.0" diff --git a/README.md b/README.md index 6f0ff96..1b963da 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ At the moment, the following backends are supported: - [x] [sysinfo](https://crates.io/crates/sysinfo) (CPU only) - [x] Vulkan -- [ ] ~~CUDA (NVIDIA devices only)~~ (planned [#1](https://github.com/edgenai/memonitor/issues/1)) +- [x] CUDA (NVIDIA devices only) - [ ] ~~Metal (macOS only)~~ (planned [#2](https://github.com/edgenai/memonitor/issues/2)) ## Platforms diff --git a/crates/memonitor-sys/Cargo.toml b/crates/memonitor-sys/Cargo.toml index fd405cf..8e47205 100644 --- a/crates/memonitor-sys/Cargo.toml +++ b/crates/memonitor-sys/Cargo.toml @@ -11,8 +11,8 @@ publish = true [dependencies] - [build-dependencies] +cfg_aliases = { workspace = true } cmake = "0.1.50" bindgen = "0.69.4" diff --git a/crates/memonitor-sys/build.rs b/crates/memonitor-sys/build.rs index 411cc80..5c5e8e4 100644 --- a/crates/memonitor-sys/build.rs +++ b/crates/memonitor-sys/build.rs @@ -1,11 +1,16 @@ use bindgen::callbacks::ParseCallbacks; use bindgen::{Builder, EnumVariation}; +use cfg_aliases::cfg_aliases; use cmake::Config; use std::env; use std::fs::read_dir; use std::path::PathBuf; fn main() { + cfg_aliases! { + apple: { any(target_os = "macos", target_os = "ios", target_os = "dragonfly") }, + } + let cur_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); #[cfg(feature = "vulkan")] @@ -51,7 +56,7 @@ fn main() { .expect("Couldn't write bindings"); } - #[cfg(feature = "cuda")] + #[cfg(all(feature = "cuda", not(apple)))] { let cuda_dir = cur_dir.join("cuda"); let mut build = Config::new(cuda_dir.as_path()); diff --git a/crates/memonitor-sys/src/lib.rs b/crates/memonitor-sys/src/lib.rs index 7847bb0..ec4d885 100644 --- a/crates/memonitor-sys/src/lib.rs +++ b/crates/memonitor-sys/src/lib.rs @@ -10,5 +10,5 @@ #[cfg(feature = "cuda")] pub mod cuda; -#[cfg(feature = "vulkan")] +#[cfg(all(feature = "vulkan", not(apple)))] pub mod vulkan; diff --git a/crates/memonitor/Cargo.toml b/crates/memonitor/Cargo.toml index d94d4ec..8e3e552 100644 --- a/crates/memonitor/Cargo.toml +++ b/crates/memonitor/Cargo.toml @@ -15,6 +15,9 @@ once_cell = "1.19.0" sysinfo = "0.30.7" tracing = "0.1.40" +[build-dependencies] +cfg_aliases = { workspace = true } + [dev-dependencies] tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } diff --git a/crates/memonitor/build.rs b/crates/memonitor/build.rs new file mode 100644 index 0000000..9c01beb --- /dev/null +++ b/crates/memonitor/build.rs @@ -0,0 +1,7 @@ +use cfg_aliases::cfg_aliases; + +fn main() { + cfg_aliases! { + apple: { any(target_os = "macos", target_os = "ios", target_os = "dragonfly") }, + } +} diff --git a/crates/memonitor/src/lib.rs b/crates/memonitor/src/lib.rs index 46839b0..7ac04f1 100644 --- a/crates/memonitor/src/lib.rs +++ b/crates/memonitor/src/lib.rs @@ -45,7 +45,7 @@ mod cpu; #[cfg(feature = "vulkan")] mod vulkan; -#[cfg(feature = "cuda")] +#[cfg(all(feature = "cuda", not(apple)))] mod cuda; /// A backend identifier. @@ -60,7 +60,7 @@ pub enum BackendId { Vulkan, /// The CUDA backend identifier. - #[cfg(feature = "cuda")] + #[cfg(all(feature = "cuda", not(apple)))] CUDA, } @@ -72,7 +72,7 @@ pub const CPU_NAME: &str = "Host"; pub const VULKAN_NAME: &str = "Vulkan"; /// The name of the Cuda backend. -#[cfg(feature = "cuda")] +#[cfg(all(feature = "cuda", not(apple)))] pub const CUDA_NAME: &str = "CUDA"; static CONTEXT: Lazy> = Lazy::new(|| { From a8e476d89be03b025c13a1dadf03594780e89d84 Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Mon, 1 Apr 2024 14:57:32 +0100 Subject: [PATCH 17/20] fixed cfg errors --- crates/memonitor-sys/src/lib.rs | 4 ++-- crates/memonitor/src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/memonitor-sys/src/lib.rs b/crates/memonitor-sys/src/lib.rs index ec4d885..8092760 100644 --- a/crates/memonitor-sys/src/lib.rs +++ b/crates/memonitor-sys/src/lib.rs @@ -8,7 +8,7 @@ #![warn(missing_docs)] -#[cfg(feature = "cuda")] +#[cfg(all(feature = "cuda", not(apple)))] pub mod cuda; -#[cfg(all(feature = "vulkan", not(apple)))] +#[cfg(feature = "vulkan")] pub mod vulkan; diff --git a/crates/memonitor/src/lib.rs b/crates/memonitor/src/lib.rs index 7ac04f1..5128459 100644 --- a/crates/memonitor/src/lib.rs +++ b/crates/memonitor/src/lib.rs @@ -107,7 +107,7 @@ impl Context { self.register_backend(backend, devices) } - #[cfg(feature = "cuda")] + #[cfg(all(feature = "cuda", not(apple)))] if let Some((backend, devices)) = cuda::Cuda::init() { self.register_backend(backend, devices) } From 79d8f580dfe823bf1a41ef95abaf955e73942936 Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Mon, 1 Apr 2024 15:30:08 +0100 Subject: [PATCH 18/20] name clarifications and test improvements --- Cargo.lock | 8 +++---- crates/memonitor/src/lib.rs | 16 +++++++------- crates/memonitor/tests/common/mod.rs | 2 +- crates/memonitor/tests/cpu.rs | 6 ++--- crates/memonitor/tests/cuda.rs | 33 ++++++++++++++++++++++++++++ crates/memonitor/tests/vulkan.rs | 6 ++--- 6 files changed, 52 insertions(+), 19 deletions(-) create mode 100644 crates/memonitor/tests/cuda.rs diff --git a/Cargo.lock b/Cargo.lock index 2fc31d3..cb5fed5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -283,9 +283,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "prettyplease" @@ -421,9 +421,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "syn" -version = "2.0.55" +version = "2.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" +checksum = "11a6ae1e52eb25aab8f3fb9fca13be982a373b8f1157ca14b897a825ba4a2d35" dependencies = [ "proc-macro2", "quote", diff --git a/crates/memonitor/src/lib.rs b/crates/memonitor/src/lib.rs index 5128459..b39a35d 100644 --- a/crates/memonitor/src/lib.rs +++ b/crates/memonitor/src/lib.rs @@ -234,17 +234,17 @@ impl PartialEq for Backend { impl Eq for Backend {} impl Backend { - /// Return the *id* of this backend within the context. + /// Return the index of this backend within the context. /// /// Used for indexing into slices returned by [`list_backends`]. - pub fn id(&self) -> usize { + pub fn index(&self) -> usize { self.id } - /// Return the *id*s of [Device]s owned by this backend. + /// Return the indexes of [Device]s owned by this backend. /// /// Used for indexing into slices returned by [`list_all_devices`]. - pub fn device_ids(&self) -> &[usize] { + pub fn device_indexes(&self) -> &[usize] { &self.device_ids } } @@ -325,10 +325,10 @@ pub struct Device { } impl Device { - /// Return the *id* of this device within the global context. + /// Return the index of this device within the global context. /// /// Used for indexing into slices returned by [`list_all_devices`]. - pub fn global_id(&self) -> usize { + pub fn global_index(&self) -> usize { self.global_id } @@ -339,10 +339,10 @@ impl Device { self.local_id } - /// Return the *id* of this device's owning [`Backend`]. + /// Return the index of this device's owning [`Backend`]. /// /// Used for indexing into slices returned by [`list_backends`]. - pub fn backend_id(&self) -> usize { + pub fn backend_index(&self) -> usize { self.backend_id } } diff --git a/crates/memonitor/tests/common/mod.rs b/crates/memonitor/tests/common/mod.rs index ff7e59d..26377f2 100644 --- a/crates/memonitor/tests/common/mod.rs +++ b/crates/memonitor/tests/common/mod.rs @@ -1,7 +1,7 @@ use tracing_subscriber::filter::LevelFilter; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; -use tracing_subscriber::{fmt, registry, EnvFilter}; +use tracing_subscriber::{EnvFilter, fmt, registry}; pub fn init_tracing() { let format = fmt::layer().pretty(); diff --git a/crates/memonitor/tests/cpu.rs b/crates/memonitor/tests/cpu.rs index e76a63b..f4de2d6 100644 --- a/crates/memonitor/tests/cpu.rs +++ b/crates/memonitor/tests/cpu.rs @@ -1,4 +1,4 @@ -use memonitor::{list_all_devices, list_backends}; +use memonitor::{list_all_devices, list_backends, BackendId}; mod common; @@ -10,9 +10,9 @@ fn cpu() { let backends = list_backends(); backends .iter() - .find(|b| b.name() == "Host") + .find(|b| b.id() == BackendId::CPU) .unwrap() - .device_ids() + .device_indexes() .to_vec() }; diff --git a/crates/memonitor/tests/cuda.rs b/crates/memonitor/tests/cuda.rs new file mode 100644 index 0000000..4b2472d --- /dev/null +++ b/crates/memonitor/tests/cuda.rs @@ -0,0 +1,33 @@ +use memonitor::{list_all_devices, list_backends, BackendId}; + +mod common; + +#[test] +fn cuda() { + common::init_tracing(); + + let device_ids = { + let backends = list_backends(); + backends + .iter() + .find(|b| b.id() == BackendId::CUDA) + .unwrap() + .device_indexes() + .to_vec() + }; + + { + let devices = list_all_devices(); + for id in device_ids { + let stats = devices[id].current_memory_stats(); + println!( + "Device found: {} ({}) - Memory stats: {} bytes used out of {}, {} are free", + devices[id].name(), + devices[id].kind(), + stats.used, + stats.total, + stats.available + ); + } + } +} diff --git a/crates/memonitor/tests/vulkan.rs b/crates/memonitor/tests/vulkan.rs index 9569bcb..6892aa4 100644 --- a/crates/memonitor/tests/vulkan.rs +++ b/crates/memonitor/tests/vulkan.rs @@ -1,4 +1,4 @@ -use memonitor::{list_all_devices, list_backends}; +use memonitor::{list_all_devices, list_backends, BackendId}; mod common; @@ -10,9 +10,9 @@ fn vulkan() { let backends = list_backends(); backends .iter() - .find(|b| b.name() == "Vulkan") + .find(|b| b.id() == BackendId::Vulkan) .unwrap() - .device_ids() + .device_indexes() .to_vec() }; From 32623bad78d89f0f32592059cdf57fb69866af43 Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Mon, 1 Apr 2024 15:31:03 +0100 Subject: [PATCH 19/20] bump crate versions --- crates/memonitor-sys/Cargo.toml | 2 +- crates/memonitor/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/memonitor-sys/Cargo.toml b/crates/memonitor-sys/Cargo.toml index 8e47205..8090b1a 100644 --- a/crates/memonitor-sys/Cargo.toml +++ b/crates/memonitor-sys/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "memonitor-sys" description = "Automatically generated bindings for some of memonitor's backends." -version = "0.1.1" +version = "0.2.0" authors = ["Pedro Valente "] license = "Apache-2.0" repository = "https://github.com/edgenai/memonitor" diff --git a/crates/memonitor/Cargo.toml b/crates/memonitor/Cargo.toml index 8e3e552..6705aca 100644 --- a/crates/memonitor/Cargo.toml +++ b/crates/memonitor/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "memonitor" description = "Query CPU and GPU memory information in a portable way." -version = "0.1.1" +version = "0.2.0" authors = ["Pedro Valente "] license = "Apache-2.0" repository = "https://github.com/edgenai/memonitor" From 79d17bbf04bf5b056d9ef05a2f117a3ad1451264 Mon Sep 17 00:00:00 2001 From: Pedro Valente Date: Mon, 1 Apr 2024 15:32:39 +0100 Subject: [PATCH 20/20] bump crate versions 2 --- crates/memonitor/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/memonitor/Cargo.toml b/crates/memonitor/Cargo.toml index 6705aca..0648680 100644 --- a/crates/memonitor/Cargo.toml +++ b/crates/memonitor/Cargo.toml @@ -10,7 +10,7 @@ edition = "2021" publish = true [dependencies] -memonitor-sys = { path = "../memonitor-sys", version = "0.1.1", default-features = false } +memonitor-sys = { path = "../memonitor-sys", version = "0.2.0", default-features = false } once_cell = "1.19.0" sysinfo = "0.30.7" tracing = "0.1.40"