Skip to content

Commit

Permalink
Merge pull request #11 from edgenai/feat/c-tracing
Browse files Browse the repository at this point in the history
Feat/c tracing
  • Loading branch information
pedro-devv authored Apr 11, 2024
2 parents 3142f63 + aaede68 commit a95d0c3
Show file tree
Hide file tree
Showing 18 changed files with 241 additions and 47 deletions.
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/memonitor-sys/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "memonitor-sys"
description = "Automatically generated bindings for some of memonitor's backends."
version = "0.2.3"
version = "0.2.4"
authors = ["Pedro Valente <[email protected]>"]
license = "Apache-2.0"
repository = "https://github.com/edgenai/memonitor"
Expand Down
29 changes: 29 additions & 0 deletions crates/memonitor-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,35 @@ fn main() {

let cur_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));

{
let log_dir = cur_dir.join("log");
let mut build = Config::new(log_dir.as_path());
let lib_out = build.build();
println!(
"cargo:rustc-link-search=native={}",
lib_out.join("lib").display()
);
println!("cargo:rustc-link-lib=static=memonitor-log");

let vk_bindings = Builder::default()
.header(log_dir.join("include").join("log.h").to_string_lossy())
.allowlist_function("log_.*")
.allowlist_type("log_.*")
.parse_callbacks(Box::new(PrefixRemover::new("log_")))
.default_enum_style(EnumVariation::Rust {
non_exhaustive: false,
})
.use_core()
.generate()
.expect("Failed to generate Log bindings");

let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());

vk_bindings
.write_to_file(out_path.join("log_bindings.rs"))
.expect("Couldn't write bindings");
}

#[cfg(feature = "vulkan")]
{
let vk_dir = cur_dir.join("vulkan");
Expand Down
5 changes: 4 additions & 1 deletion crates/memonitor-sys/cuda/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
cmake_minimum_required(VERSION 3.5)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED true)

project(memonitor-cuda LANGUAGES C)

add_library(memonitor-cuda STATIC "include/memonitor.h" "src/memonitor.c")
target_include_directories(memonitor-cuda PUBLIC "include")
target_include_directories(memonitor-cuda PUBLIC "include" PRIVATE "../log/include")

install(TARGETS memonitor-cuda
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
Expand Down
51 changes: 38 additions & 13 deletions crates/memonitor-sys/cuda/src/memonitor.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <stdlib.h>

#include <memonitor.h>
#include <log.h>

#ifdef _WIN32

Expand Down Expand Up @@ -45,11 +46,6 @@ typedef CUresult (*cuDeviceTotalMem_type)(size_t *, CUdevice);

typedef CUresult (*cuMemGetInfo_type)(size_t *, size_t *);

struct Device {
CUdevice handle;
CUdevice_opaque inner;
};

static mod_type module = NULL;

static cuInit_type cuInit = NULL;
Expand All @@ -69,6 +65,7 @@ int cu_init() {
#ifdef _WIN32
module = LoadLibraryA("nvcuda.dll");
if (!module) {
LOG_WARN("Could not load CUDA driver");
return -1;
}

Expand All @@ -87,7 +84,13 @@ int cu_init() {
return -1;
#else
module = dlopen("libcuda.so", RTLD_NOW | RTLD_LOCAL);

if (!module) {
module = dlopen("libcuda.so.1", RTLD_NOW | RTLD_LOCAL);
}

if (!module) {
LOG_WARN("Could not load CUDA driver.");
return -1;
}

Expand All @@ -104,8 +107,11 @@ int cu_init() {
cuMemGetInfo = (cuMemGetInfo_type) dlsym(module, "cuMemGetInfo_v2");
#endif

LOG_DEBUG("Found CUDA driver");

CUresult res = cuInit(0);
if (res != 0) {
LOG_WARN("Failed to initialise CUDA");
#ifdef _WIN32
FreeLibrary(module);
#else
Expand All @@ -115,6 +121,8 @@ int cu_init() {
return -2;
}

LOG_DEBUG("Initialised CUDA context");

return 0;
}

Expand Down Expand Up @@ -147,31 +155,40 @@ struct cu_Devices cu_list_devices() {
int count = 0;
CUresult res = cuDeviceGetCount(&count);
if (count <= 0 || res != 0) {
if (res) {
LOG_WARN("Failed to retrieve CUDA device count (error %d)", res);
} else {
LOG_WARN("No CUDA devices found");
}

return invalid_devices;
}
LOG_DEBUG("Found %d CUDA device(s)", count);

struct Device *device_handles = calloc(count, sizeof(struct Device));
CUdevice *device_handles = calloc(count, sizeof(CUdevice));
CUcontext *ctx_handles = calloc(count, sizeof(CUcontext));
for (int d = 0; d < count; 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);
// cuDeviceGet only sets the first few bytes of the CUdevice pointer, and ignores the rest.
// A nul pointer output is valid.
res = cuDeviceGet(&device_handles[d], d);
if (res != 0) {
LOG_WARN("Failed to retrieve CUDA device %d (error %d)", d, res);
free(device_handles);
free(ctx_handles);
return invalid_devices;
}

res = cuCtxCreate(&ctx_handles[d], NULL, 0, 0, device_handles[d].handle);
res = cuCtxCreate(&ctx_handles[d], NULL, 0, 0, device_handles[d]);
if (res != 0) {
LOG_WARN("Failed to create CUDA device %d (error %d)", d, res);
free(device_handles);
free(ctx_handles);
return invalid_devices;
}

res = cuCtxPopCurrent(&ctx_handles[d]);
if (res != 0) {
LOG_WARN("Failed to pop device context %d (error %d)", d, res);
free(device_handles);
free(ctx_handles);
return invalid_devices;
Expand Down Expand Up @@ -203,6 +220,7 @@ void cu_destroy_devices(struct cu_Devices *devices) {
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) {
LOG_WARN("Invalid CUDA device (index %u)", index);
return invalid_ref;
}

Expand All @@ -214,7 +232,8 @@ struct cu_DeviceRef cu_get_device(struct cu_Devices *devices, uint32_t index) {

struct cu_DeviceProperties cu_device_properties(struct cu_DeviceRef device) {
const struct cu_DeviceProperties invalid_properties = {{0}, Other, 0};
if (!device.handle) {
if (!device.ctx_handle) {
LOG_WARN("Invalid CUDA device handle");
return invalid_properties;
}

Expand All @@ -224,11 +243,13 @@ struct cu_DeviceProperties cu_device_properties(struct cu_DeviceRef device) {

CUresult res = cuDeviceGetName(props.name, sizeof(props.name), cast_device);
if (res != 0) {
LOG_WARN("Failed to get CUDA device name (error %d)", res);
return invalid_properties;
}

res = cuDeviceTotalMem(&props.total_memory, cast_device);
if (res != 0) {
LOG_WARN("Failed to get CUDA device total memory (error %d)", res);
return invalid_properties;
}

Expand All @@ -237,13 +258,15 @@ struct cu_DeviceProperties cu_device_properties(struct cu_DeviceRef device) {

struct cu_DeviceMemoryProperties cu_device_memory_properties(struct cu_DeviceRef device) {
const struct cu_DeviceMemoryProperties invalid_properties = {0};
if (!device.handle) {
if (!device.ctx_handle) {
LOG_WARN("Invalid CUDA device handle");
return invalid_properties;
}

CUcontext *cast_ctx = device.ctx_handle;
CUresult res = cuCtxPushCurrent(*cast_ctx);
if (res != 0) {
LOG_WARN("Failed to push CUDA device context (error %d)", res);
return invalid_properties;
}

Expand All @@ -252,11 +275,13 @@ struct cu_DeviceMemoryProperties cu_device_memory_properties(struct cu_DeviceRef

res = cuMemGetInfo(&free_memory, &total_memory);
if (res != 0) {
LOG_WARN("Failed to get CUDA device memory properties (error %d)", res);
return invalid_properties;
}

res = cuCtxPopCurrent(cast_ctx);
if (res != 0) {
LOG_WARN("Failed to pop CUDA device context (error %d)", res);
return invalid_properties;
}

Expand Down
15 changes: 15 additions & 0 deletions crates/memonitor-sys/log/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.5)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED true)

project(memonitor-log LANGUAGES C)

add_library(memonitor-log STATIC "include/log.h" "src/log.c")
target_include_directories(memonitor-log PUBLIC "include")

install(TARGETS memonitor-log
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
55 changes: 55 additions & 0 deletions crates/memonitor-sys/log/include/log.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#pragma once

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

#include <stdio.h>

/**
* The verbosity level of a log event.
*/
enum log_Level {
Trace, //!< Designates very low priority, often extremely verbose, information.
Debug, //!< Designates lower priority information.
Info, //!< Designates useful information.
Warn, //!< Designates hazardous situations.
Error, //!< Designates very serious errors.
};

/**
* The type of a log event function.
*
* @param level The verbosity level of the event.
* @param msg The string message to be logged.
*/
typedef void (*log_LogFn)(enum log_Level level, const char *msg);

/**
* Set the global event logging function.
*
* @param fn_ptr A pointer to the event logging function. If `NULL`, the global logger is unset.
*/
void log_set(log_LogFn fn_ptr);

/**
* The inner logging function, this should not be called directly, instead the macros defined in the same header
* should be used..
*
* @param level The verbosity level of the event.
* @param msg The string message to be logged.
*/
void inner_log(enum log_Level level, const char *msg);

#define LOG_MSG_SIZE(message, ...) sizeof(message)
#define INNER_LOG(level, ...) { char tmp[LOG_MSG_SIZE(__VA_ARGS__) + 256]; snprintf(tmp, sizeof(tmp), __VA_ARGS__); inner_log(level, tmp); }(0)

#define LOG_TRACE(...) INNER_LOG(Trace, __VA_ARGS__)
#define LOG_DEBUG(...) INNER_LOG(Debug, __VA_ARGS__)
#define LOG_INFO(...) INNER_LOG(Info, __VA_ARGS__)
#define LOG_WARN(...) INNER_LOG(Warn, __VA_ARGS__)
#define LOG_ERROR(...) INNER_LOG(Error, __VA_ARGS__)

#ifdef __cplusplus
}
#endif // __cplusplus
15 changes: 15 additions & 0 deletions crates/memonitor-sys/log/src/log.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include <stdlib.h>

#include <log.h>

static log_LogFn logger = NULL;

void log_set(log_LogFn fn_ptr) {
logger = fn_ptr;
}

void inner_log(enum log_Level level, const char *msg) {
if (logger) {
logger(level, msg);
}
}
2 changes: 2 additions & 0 deletions crates/memonitor-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#![warn(missing_docs)]

pub mod log;

#[cfg(all(feature = "cuda", not(apple)))]
pub mod cuda;
#[cfg(feature = "vulkan")]
Expand Down
7 changes: 7 additions & 0 deletions crates/memonitor-sys/src/log.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//! Automatically generated bindings for the native logger.
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]

include!(concat!(env!("OUT_DIR"), "/log_bindings.rs"));
2 changes: 1 addition & 1 deletion crates/memonitor-sys/vulkan/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ add_subdirectory(thirdparty/volk)
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_include_directories(memonitor-vk PUBLIC "include" PRIVATE "../log/include")
target_link_libraries(memonitor-vk PRIVATE volk)

if (MEMONITOR_VALIDATE)
Expand Down
Loading

0 comments on commit a95d0c3

Please sign in to comment.