-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
228 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,53 @@ | ||
# Specify the minimum required version of CMake | ||
cmake_minimum_required(VERSION 3.16) | ||
|
||
# Include the FetchContent module | ||
include(FetchContent) | ||
# Include the ExternalProject module | ||
include(ExternalProject) | ||
|
||
# Define the project name and programming language | ||
project(nvidia-pstated C) | ||
|
||
# Find the CUDAToolkit package | ||
find_package(CUDAToolkit REQUIRED COMPONENTS nvml) | ||
|
||
# Declare the nvapi package | ||
FetchContent_Declare( | ||
nvapi | ||
|
||
# Download and set up the NvAPI | ||
ExternalProject_Add(nvapi | ||
URL https://download.nvidia.com/XFree86/nvapi-open-source-sdk/R555-OpenSource.tar | ||
URL_HASH SHA256=71339c274a6a633f19b6bd358c7f3045063c6bc106b7dc488aaa7360a6d2b9d7 | ||
|
||
CONFIGURE_COMMAND "" | ||
BUILD_COMMAND "" | ||
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory <SOURCE_DIR>/R555-OpenSource <INSTALL_DIR>/include | ||
) | ||
|
||
# Download and make the nvapi content available for use | ||
FetchContent_MakeAvailable(nvapi) | ||
# Download and set up the NVML | ||
ExternalProject_Add(nvml | ||
URL https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/cuda-nvml-dev-12-6_12.6.68-1_amd64.deb | ||
URL_HASH SHA256=fda6d4fdf26e20db4ca4950489033f4c6747c7473db3f9dc0529d56f2cc237de | ||
|
||
CONFIGURE_COMMAND "" | ||
BUILD_COMMAND ${CMAKE_COMMAND} -E tar xf <SOURCE_DIR>/data.tar.xz | ||
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory <BINARY_DIR>/usr/local/cuda-12.6/targets/x86_64-linux/include <INSTALL_DIR>/include | ||
) | ||
|
||
# Define the executable target | ||
add_executable(nvidia-pstated | ||
src/main.c | ||
src/nvapi.c | ||
src/nvml.c | ||
src/utils.c | ||
) | ||
|
||
# Include directories for the target | ||
target_include_directories(nvidia-pstated SYSTEM PRIVATE | ||
${nvapi_SOURCE_DIR}/R555-OpenSource | ||
# Set dependencies for the executable | ||
add_dependencies(nvidia-pstated | ||
nvapi | ||
nvml | ||
) | ||
|
||
# Link libraries | ||
target_link_libraries(nvidia-pstated PRIVATE | ||
CUDA::nvml | ||
# Include directories for the target | ||
target_include_directories(nvidia-pstated SYSTEM PRIVATE | ||
${CMAKE_CURRENT_BINARY_DIR}/nvapi-prefix/include | ||
${CMAKE_CURRENT_BINARY_DIR}/nvml-prefix/include | ||
) | ||
|
||
# Conditional linking for Linux platform | ||
if(UNIX AND NOT APPLE) | ||
target_link_libraries(nvidia-pstated PRIVATE | ||
dl | ||
) | ||
target_link_libraries(nvidia-pstated PRIVATE -static dl) | ||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
#include <nvml.h> | ||
|
||
#include "nvml.h" | ||
#include "utils.h" | ||
|
||
/***** ***** ***** ***** ***** TYPES ***** ***** ***** ***** *****/ | ||
|
||
typedef nvmlReturn_t (*nvmlDeviceGetHandleByIndex_v2_t)(unsigned int, nvmlDevice_t); | ||
typedef nvmlReturn_t (*nvmlDeviceGetName_t)(nvmlDevice_t, char *, unsigned int); | ||
typedef nvmlReturn_t (*nvmlDeviceGetTemperature_t)(nvmlDevice_t, nvmlTemperatureSensors_t, unsigned int); | ||
typedef nvmlReturn_t (*nvmlDeviceGetUtilizationRates_t)(nvmlDevice_t, nvmlUtilization_t); | ||
typedef char * (*nvmlErrorString_t)(nvmlReturn_t); | ||
typedef nvmlReturn_t (*nvmlInit_v2_t)(void); | ||
typedef nvmlReturn_t (*nvmlShutdown_t)(void); | ||
|
||
/***** ***** ***** ***** ***** VARIABLES ***** ***** ***** ***** *****/ | ||
|
||
static void * lib; | ||
|
||
static nvmlDeviceGetHandleByIndex_v2_t _nvmlDeviceGetHandleByIndex_v2; | ||
static nvmlDeviceGetName_t _nvmlDeviceGetName; | ||
static nvmlDeviceGetTemperature_t _nvmlDeviceGetTemperature; | ||
static nvmlDeviceGetUtilizationRates_t _nvmlDeviceGetUtilizationRates; | ||
static nvmlErrorString_t _nvmlErrorString; | ||
static nvmlInit_v2_t _nvmlInit_v2; | ||
static nvmlShutdown_t _nvmlShutdown; | ||
|
||
/***** ***** ***** ***** ***** MACROS ***** ***** ***** ***** *****/ | ||
|
||
#define NVML_POINTER(pointer) do { \ | ||
if (pointer == NULL) { \ | ||
return NVML_ERROR_UNINITIALIZED; \ | ||
} \ | ||
} while(0) | ||
|
||
/***** ***** ***** ***** ***** IMPLEMENTATION ***** ***** ***** ***** *****/ | ||
|
||
nvmlReturn_t nvmlDeviceGetHandleByIndex_v2(unsigned int index, nvmlDevice_t * device) { | ||
// Ensure the function pointer is valid | ||
NVML_POINTER(_nvmlDeviceGetHandleByIndex_v2); | ||
|
||
// Invoke the function using the provided parameters | ||
return _nvmlDeviceGetHandleByIndex_v2(index, *device); | ||
} | ||
|
||
nvmlReturn_t nvmlDeviceGetName(nvmlDevice_t device, char * name, unsigned int length) { | ||
// Ensure the function pointer is valid | ||
NVML_POINTER(_nvmlDeviceGetName); | ||
|
||
// Invoke the function using the provided parameters | ||
return _nvmlDeviceGetName(device, name, length); | ||
} | ||
|
||
nvmlReturn_t nvmlDeviceGetTemperature(nvmlDevice_t device, nvmlTemperatureSensors_t sensorType, unsigned int * temp) { | ||
// Ensure the function pointer is valid | ||
NVML_POINTER(_nvmlDeviceGetTemperature); | ||
|
||
// Invoke the function using the provided parameters | ||
return _nvmlDeviceGetTemperature(device, sensorType, *temp); | ||
} | ||
|
||
nvmlReturn_t nvmlDeviceGetUtilizationRates(nvmlDevice_t device, nvmlUtilization_t * utilization) { | ||
// Ensure the function pointer is valid | ||
NVML_POINTER(_nvmlDeviceGetUtilizationRates); | ||
|
||
// Invoke the function using the provided parameters | ||
return _nvmlDeviceGetUtilizationRates(device, *utilization); | ||
} | ||
|
||
const char * nvmlErrorString(nvmlReturn_t result) { | ||
// Ensure the function pointer is valid | ||
if (_nvmlErrorString == NULL) { | ||
return "<nvmlErrorString() call failed>"; | ||
} | ||
|
||
// Invoke the function using the provided parameters | ||
return _nvmlErrorString(result); | ||
} | ||
|
||
nvmlReturn_t nvmlInit_v2(void) { | ||
// Check the platform and load the appropriate NVML library | ||
#ifdef _WIN32 | ||
if (!lib) { | ||
lib = library_open("nvml64.dll"); | ||
} | ||
|
||
if (!lib) { | ||
lib = library_open("nvml.dll"); | ||
} | ||
#elif __linux__ | ||
if (!lib) { | ||
lib = library_open("libnvidia-ml.so.1"); | ||
} | ||
|
||
if (!lib) { | ||
lib = library_open("libnvidia-ml.so"); | ||
} | ||
#endif | ||
|
||
// If the library handle is still not initialized, loading the library failed | ||
if (!lib) { | ||
// Print an error message indicating failure to load the NVML library | ||
fprintf(stderr, "Unable to load NVML library\n"); | ||
|
||
// Return an error status indicating that the library was not found | ||
return NVML_ERROR_LIBRARY_NOT_FOUND; | ||
} | ||
|
||
// Retrieve the addresses of specific NVML functions | ||
_nvmlDeviceGetHandleByIndex_v2 = (nvmlDeviceGetHandleByIndex_v2_t) library_proc(lib, "nvmlDeviceGetHandleByIndex_v2"); | ||
_nvmlDeviceGetName = (nvmlDeviceGetName_t) library_proc(lib, "nvmlDeviceGetName"); | ||
_nvmlDeviceGetTemperature = (nvmlDeviceGetTemperature_t) library_proc(lib, "nvmlDeviceGetTemperature"); | ||
_nvmlDeviceGetUtilizationRates = (nvmlDeviceGetUtilizationRates_t) library_proc(lib, "nvmlDeviceGetUtilizationRates"); | ||
_nvmlErrorString = (nvmlErrorString_t) library_proc(lib, "nvmlErrorString"); | ||
_nvmlInit_v2 = (nvmlInit_v2_t) library_proc(lib, "nvmlInit_v2"); | ||
_nvmlShutdown = (nvmlShutdown_t) library_proc(lib, "nvmlShutdown"); | ||
|
||
// Ensure the function pointer is valid | ||
NVML_POINTER(_nvmlInit_v2); | ||
|
||
// Invoke the function using the provided parameters | ||
return _nvmlInit_v2(); | ||
} | ||
|
||
nvmlReturn_t nvmlShutdown(void) { | ||
// Ensure the function pointer is valid | ||
NVML_POINTER(_nvmlShutdown); | ||
|
||
// Invoke the function using the provided parameters | ||
nvmlReturn_t ret = _nvmlShutdown(); | ||
|
||
// If the function call was successful, proceed with cleanup | ||
if (ret == NVML_SUCCESS) { | ||
// If the library handle is initialized | ||
if (lib) { | ||
// Nullify all the function pointers to prevent further use | ||
_nvmlDeviceGetHandleByIndex_v2 = NULL; | ||
_nvmlDeviceGetName = NULL; | ||
_nvmlDeviceGetTemperature = NULL; | ||
_nvmlDeviceGetUtilizationRates = NULL; | ||
_nvmlErrorString = NULL; | ||
_nvmlInit_v2 = NULL; | ||
_nvmlShutdown = NULL; | ||
|
||
// Free the loaded library | ||
library_close(lib); | ||
} | ||
} | ||
|
||
// Return the status of the function call | ||
return ret; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters