[v0.30] Add support for AMD GPUs
Adds very basic support for AMD (experimental). The only install
requirement is ROCm. Unlike NVIDIA, we don't need the CUDA equivalent
(HIP) to make gpufetch work, which reduces the installation
requirements quite significantly.
Major changes:
* CMakeLists:
- Make CUDA not compiled by default (since we now may want to target
AMD only)
- Set build flags on gpufetch cmake target instead of doing
"set(CMAKE_CXX_FLAGS". This fixes a warning coming from ROCm.
- Assumes that the ROCm CMake files are installed (should be fixed
later)
* hsa folder: AMD support is implemented via HSA (Heterogeneous System
Architecture) calls. Therefore, HSA is added as a new backend to
gpufetch. We only print basic stuff for now, so we may need more
things in the future to give full support for AMD GPUs.
NOTE: This commit will probably break AUR packages since we used to
build CUDA by default, which is no longer the case. The AUR package
should be updated and use -DENABLE_CUDA_BACKEND or -DENABLE_HSA_BACKEND
as appropriate.
This commit is contained in:
@@ -7,17 +7,18 @@ project(gpufetch CXX)
|
||||
set(SRC_DIR "src")
|
||||
set(COMMON_DIR "${SRC_DIR}/common")
|
||||
set(CUDA_DIR "${SRC_DIR}/cuda")
|
||||
set(HSA_DIR "${SRC_DIR}/hsa")
|
||||
set(INTEL_DIR "${SRC_DIR}/intel")
|
||||
|
||||
# Enable Intel backend by default
|
||||
if(NOT DEFINED ENABLE_INTEL_BACKEND)
|
||||
set(ENABLE_INTEL_BACKEND true)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED ENABLE_CUDA_BACKEND OR ENABLE_CUDA_BACKEND)
|
||||
if(ENABLE_CUDA_BACKEND)
|
||||
check_language(CUDA)
|
||||
if(CMAKE_CUDA_COMPILER)
|
||||
enable_language(CUDA)
|
||||
set(ENABLE_CUDA_BACKEND true)
|
||||
# Must link_directories early so add_executable(gpufetch ...) gets the right directories
|
||||
link_directories(cuda_backend ${CMAKE_CUDA_COMPILER_TOOLKIT_ROOT}/targets/x86_64-linux/lib)
|
||||
else()
|
||||
@@ -25,6 +26,34 @@ if(NOT DEFINED ENABLE_CUDA_BACKEND OR ENABLE_CUDA_BACKEND)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_HSA_BACKEND)
|
||||
# TODO: Needs rocm-cmake, what if its not insalled?
|
||||
find_package(ROCmCMakeBuildTools)
|
||||
if (ROCmCMakeBuildTools_FOUND)
|
||||
find_package(hsa-runtime64 1.0 REQUIRED)
|
||||
link_directories(hsa_backend hsa-runtime64::hsa-runtime64)
|
||||
|
||||
# Find HSA headers
|
||||
# ROCm does not seem to provide this, which is quite frustrating.
|
||||
find_path(HSA_INCLUDE_DIR
|
||||
NAMES hsa/hsa.h
|
||||
HINTS
|
||||
$ENV{ROCM_PATH}/include # allow users override via env variable
|
||||
/opt/rocm/include # common default path
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
)
|
||||
|
||||
if(NOT HSA_INCLUDE_DIR)
|
||||
message(STATUS "${BoldYellow}HSA not found, disabling HSA backend${ColorReset}")
|
||||
set(ENABLE_HSA_BACKEND false)
|
||||
endif()
|
||||
else()
|
||||
set(ENABLE_HSA_BACKEND false)
|
||||
message(STATUS "${BoldYellow}ROCm not found${ColorReset}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
|
||||
find_package(PCIUTILS)
|
||||
if(NOT ${PCIUTILS_FOUND})
|
||||
@@ -50,8 +79,9 @@ else()
|
||||
endif()
|
||||
|
||||
add_executable(gpufetch ${COMMON_DIR}/main.cpp ${COMMON_DIR}/args.cpp ${COMMON_DIR}/gpu.cpp ${COMMON_DIR}/pci.cpp ${COMMON_DIR}/sort.cpp ${COMMON_DIR}/global.cpp ${COMMON_DIR}/printer.cpp ${COMMON_DIR}/master.cpp ${COMMON_DIR}/uarch.cpp)
|
||||
set(SANITY_FLAGS "-Wfloat-equal -Wshadow -Wpointer-arith")
|
||||
set(CMAKE_CXX_FLAGS "${SANITY_FLAGS} -Wall -Wextra -pedantic -fstack-protector-all -pedantic -std=c++11")
|
||||
set(SANITY_FLAGS -Wfloat-equal -Wshadow -Wpointer-arith -Wall -Wextra -pedantic -fstack-protector-all -pedantic)
|
||||
target_compile_features(gpufetch PRIVATE cxx_std_11)
|
||||
target_compile_options(gpufetch PRIVATE ${SANITY_FLAGS})
|
||||
|
||||
if(ENABLE_INTEL_BACKEND)
|
||||
target_compile_definitions(gpufetch PUBLIC BACKEND_INTEL)
|
||||
@@ -94,6 +124,22 @@ if(ENABLE_CUDA_BACKEND)
|
||||
target_link_libraries(gpufetch cuda_backend)
|
||||
endif()
|
||||
|
||||
if(ENABLE_HSA_BACKEND)
|
||||
target_compile_definitions(gpufetch PUBLIC BACKEND_HSA)
|
||||
|
||||
add_library(hsa_backend STATIC ${HSA_DIR}/hsa.cpp)
|
||||
|
||||
if(NOT ${PCIUTILS_FOUND})
|
||||
add_dependencies(hsa_backend pciutils)
|
||||
endif()
|
||||
|
||||
target_include_directories(hsa_backend PRIVATE "${HSA_INCLUDE_DIR}")
|
||||
message(STATUS "Found HSA: ${HSA_INCLUDE_DIR}")
|
||||
|
||||
target_link_libraries(hsa_backend PRIVATE hsa-runtime64::hsa-runtime64)
|
||||
target_link_libraries(gpufetch hsa_backend)
|
||||
endif()
|
||||
|
||||
target_link_libraries(gpufetch pci z)
|
||||
install(TARGETS gpufetch DESTINATION bin)
|
||||
|
||||
@@ -115,6 +161,11 @@ if(ENABLE_CUDA_BACKEND)
|
||||
else()
|
||||
message(STATUS "CUDA backend: ${BoldRed}OFF${ColorReset}")
|
||||
endif()
|
||||
if(ENABLE_HSA_BACKEND)
|
||||
message(STATUS "HSA backend: ${BoldGreen}ON${ColorReset}")
|
||||
else()
|
||||
message(STATUS "HSA backend: ${BoldRed}OFF${ColorReset}")
|
||||
endif()
|
||||
if(ENABLE_INTEL_BACKEND)
|
||||
message(STATUS "Intel backend: ${BoldGreen}ON${ColorReset}")
|
||||
else()
|
||||
|
||||
24
README.md
24
README.md
@@ -33,15 +33,16 @@ gpufetch is a command-line tool written in C++ that displays the GPU information
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
|
||||
|
||||
- [1. Support](#1-support)
|
||||
- [2. Backends](#2-backends)
|
||||
- [2.1 CUDA backend is not enabled. Why?](#21-cuda-backend-is-not-enabled-why)
|
||||
- [2.2 The backend is enabled, but gpufetch is unable to detect my GPU](#22-the-backend-is-enabled-but-gpufetch-is-unable-to-detect-my-gpu)
|
||||
- [3. Installation (building from source)](#3-installation-building-from-source)
|
||||
- [4. Colors](#4-colors)
|
||||
- [4.1 Specifying a name](#41-specifying-a-name)
|
||||
- [4.2 Specifying the colors in RGB format](#42-specifying-the-colors-in-rgb-format)
|
||||
- [5. Bugs or improvements](#5-bugs-or-improvements)
|
||||
- [Table of contents](#table-of-contents)
|
||||
- [1. Support](#1-support)
|
||||
- [2. Backends](#2-backends)
|
||||
- [2.1 CUDA backend is not enabled. Why?](#21-cuda-backend-is-not-enabled-why)
|
||||
- [2.2 The backend is enabled, but gpufetch is unable to detect my GPU](#22-the-backend-is-enabled-but-gpufetch-is-unable-to-detect-my-gpu)
|
||||
- [3. Installation (building from source)](#3-installation-building-from-source)
|
||||
- [4. Colors](#4-colors)
|
||||
- [4.1 Specifying a name](#41-specifying-a-name)
|
||||
- [4.2 Specifying the colors in RGB format](#42-specifying-the-colors-in-rgb-format)
|
||||
- [5. Bugs or improvements](#5-bugs-or-improvements)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
@@ -49,14 +50,16 @@ gpufetch is a command-line tool written in C++ that displays the GPU information
|
||||
gpufetch supports the following GPUs:
|
||||
|
||||
- **NVIDIA** GPUs (Compute Capability >= 2.0)
|
||||
- **AMD** GPUs (Experimental) (RDNA 3.0, CDNA 3.0)
|
||||
- **Intel** iGPUs (Generation >= Gen6)
|
||||
|
||||
Only compilation under **Linux** is supported.
|
||||
|
||||
## 2. Backends
|
||||
gpufetch is made up of two backends:
|
||||
gpufetch is made up of three backends:
|
||||
|
||||
- CUDA backend
|
||||
- HSA backend
|
||||
- Intel backend
|
||||
|
||||
Backends are enabled and disabled at **compile time**. When compiling gpufetch, check the CMake output to see which backends are enabled.
|
||||
@@ -111,6 +114,7 @@ By default, `gpufetch` will print the GPU logo with the system color scheme. How
|
||||
By specifying a name, gpufetch will use the specific colors of each manufacture. Valid values are:
|
||||
|
||||
- intel
|
||||
- amd
|
||||
- nvidia
|
||||
|
||||
```
|
||||
|
||||
2
build.sh
2
build.sh
@@ -23,6 +23,8 @@ fi
|
||||
# In case you want to explicitely disable a backend, you can:
|
||||
# Disable CUDA backend:
|
||||
# cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DENABLE_CUDA_BACKEND=OFF ..
|
||||
# Disable HSA backend:
|
||||
# cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DENABLE_HSA_BACKEND=OFF ..
|
||||
# Disable Intel backend:
|
||||
# cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DENABLE_INTEL_BACKEND=OFF ..
|
||||
|
||||
|
||||
@@ -13,12 +13,14 @@
|
||||
#define NUM_COLORS 4
|
||||
|
||||
#define COLOR_STR_NVIDIA "nvidia"
|
||||
#define COLOR_STR_AMD "amd"
|
||||
#define COLOR_STR_INTEL "intel"
|
||||
|
||||
// +-----------------------+-----------------------+
|
||||
// | Color logo | Color text |
|
||||
// | Color 1 | Color 2 | Color 1 | Color 2 |
|
||||
#define COLOR_DEFAULT_NVIDIA "118,185,000:255,255,255:255,255,255:118,185,000"
|
||||
#define COLOR_DEFAULT_AMD "250,250,250:250,250,250:200,200,200:255,255,255"
|
||||
#define COLOR_DEFAULT_INTEL "015,125,194:230,230,230:040,150,220:230,230,230"
|
||||
|
||||
struct args_struct {
|
||||
@@ -168,6 +170,7 @@ bool parse_color(char* optarg_str, struct color*** cs) {
|
||||
bool free_ptr = true;
|
||||
|
||||
if(strcmp(optarg_str, COLOR_STR_NVIDIA) == 0) color_to_copy = COLOR_DEFAULT_NVIDIA;
|
||||
else if(strcmp(optarg_str, COLOR_STR_AMD) == 0) color_to_copy = COLOR_DEFAULT_AMD;
|
||||
else if(strcmp(optarg_str, COLOR_STR_INTEL) == 0) color_to_copy = COLOR_DEFAULT_INTEL;
|
||||
else {
|
||||
str_to_parse = optarg_str;
|
||||
|
||||
@@ -34,6 +34,23 @@ $C2## ## ## ## ## ## ## ## #: :# \
|
||||
$C2## ## ## ## ## ## ## ## ####### \
|
||||
$C2## ## ### ## ###### ## ## ## "
|
||||
|
||||
#define ASCII_AMD \
|
||||
"$C2 '############### \
|
||||
$C2 ,############# \
|
||||
$C2 .#### \
|
||||
$C2 #. .#### \
|
||||
$C2 :##. .#### \
|
||||
$C2 :###. .#### \
|
||||
$C2 #########. :## \
|
||||
$C2 #######. ; \
|
||||
$C1 \
|
||||
$C1 ### ### ### ####### \
|
||||
$C1 ## ## ##### ##### ## ## \
|
||||
$C1 ## ## ### #### ### ## ## \
|
||||
$C1 ######### ### ## ### ## ## \
|
||||
$C1## ## ### ### ## ## \
|
||||
$C1## ## ### ### ####### "
|
||||
|
||||
#define ASCII_INTEL \
|
||||
"$C1 .#################. \
|
||||
$C1 .#### ####. \
|
||||
@@ -68,6 +85,27 @@ $C1 olcc::; ,:ccloMMMMMMMMM \
|
||||
$C1 :......oMMMMMMMMMMMMMMMMMMMMMM \
|
||||
$C1 :lllMMMMMMMMMMMMMMMMMMMMMMMMMM "
|
||||
|
||||
#define ASCII_AMD_L \
|
||||
"$C1 \
|
||||
$C1 \
|
||||
$C1 \
|
||||
$C1 \
|
||||
$C1 \
|
||||
$C1 \
|
||||
$C1 @@@@ @@@ @@@ @@@@@@@@ $C2 ############ \
|
||||
$C1 @@@@@@ @@@@@ @@@@@ @@@ @@@ $C2 ########## \
|
||||
$C1 @@@ @@@ @@@@@@@@@@@@@ @@@ @@ $C2 # ##### \
|
||||
$C1 @@@ @@@ @@@ @@@ @@@ @@@ @@ $C2 ### ##### \
|
||||
$C1 @@@@@@@@@@@@ @@@ @@@ @@@ @@@ $C2######### ### \
|
||||
$C1 @@@ @@@ @@@ @@@ @@@@@@@@@ $C2######## ## \
|
||||
$C1 \
|
||||
$C1 \
|
||||
$C1 \
|
||||
$C1 \
|
||||
$C1 \
|
||||
$C1 \
|
||||
$C1 "
|
||||
|
||||
#define ASCII_INTEL_L \
|
||||
"$C1 ###############@ \
|
||||
$C1 ######@ ######@ \
|
||||
@@ -94,11 +132,13 @@ typedef struct ascii_logo asciiL;
|
||||
// ------------------------------------------------------------------------------------------
|
||||
// | LOGO | W | H | REPLACE | COLORS LOGO | COLORS TEXT |
|
||||
// ------------------------------------------------------------------------------------------
|
||||
asciiL logo_nvidia = { ASCII_NVIDIA, 45, 19, false, {C_FG_GREEN, C_FG_WHITE}, {C_FG_WHITE, C_FG_GREEN} };
|
||||
asciiL logo_intel = { ASCII_INTEL, 48, 14, false, {C_FG_CYAN}, {C_FG_CYAN, C_FG_WHITE} };
|
||||
asciiL logo_nvidia = { ASCII_NVIDIA, 45, 19, false, {C_FG_GREEN, C_FG_WHITE}, {C_FG_WHITE, C_FG_GREEN} };
|
||||
asciiL logo_amd = { ASCII_AMD, 39, 15, false, {C_FG_WHITE, C_FG_GREEN}, {C_FG_WHITE, C_FG_GREEN} };
|
||||
asciiL logo_intel = { ASCII_INTEL, 48, 14, false, {C_FG_CYAN}, {C_FG_CYAN, C_FG_WHITE} };
|
||||
// Long variants | ---------------------------------------------------------------------------------------|
|
||||
asciiL logo_nvidia_l = { ASCII_NVIDIA_L, 50, 15, false, {C_FG_GREEN, C_FG_WHITE}, {C_FG_WHITE, C_FG_GREEN} };
|
||||
asciiL logo_intel_l = { ASCII_INTEL_L, 62, 19, true, {C_BG_CYAN, C_BG_WHITE}, {C_FG_CYAN, C_FG_WHITE} };
|
||||
asciiL logo_unknown = { NULL, 0, 0, false, {C_NONE}, {C_NONE, C_NONE} };
|
||||
asciiL logo_nvidia_l = { ASCII_NVIDIA_L, 50, 15, false, {C_FG_GREEN, C_FG_WHITE}, {C_FG_WHITE, C_FG_GREEN} };
|
||||
asciiL logo_amd_l = { ASCII_AMD_L, 62, 19, true, {C_BG_WHITE, C_BG_WHITE}, {C_FG_CYAN, C_FG_B_WHITE} };
|
||||
asciiL logo_intel_l = { ASCII_INTEL_L, 62, 19, true, {C_BG_CYAN, C_BG_WHITE}, {C_FG_CYAN, C_FG_WHITE} };
|
||||
asciiL logo_unknown = { NULL, 0, 0, false, {C_NONE}, {C_NONE, C_NONE} };
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
enum {
|
||||
GPU_VENDOR_NVIDIA,
|
||||
GPU_VENDOR_AMD,
|
||||
GPU_VENDOR_INTEL
|
||||
};
|
||||
|
||||
@@ -44,6 +45,11 @@ struct topology_c {
|
||||
int32_t tensor_cores;
|
||||
};
|
||||
|
||||
// HSA topology
|
||||
struct topology_h {
|
||||
int32_t compute_units;
|
||||
};
|
||||
|
||||
// Intel topology
|
||||
struct topology_i {
|
||||
int32_t slices;
|
||||
@@ -72,6 +78,8 @@ struct gpu_info {
|
||||
struct memory* mem;
|
||||
struct cache* cach;
|
||||
struct topology_c* topo_c;
|
||||
// HSA specific
|
||||
struct topology_h* topo_h;
|
||||
// Intel specific
|
||||
struct topology_i* topo_i;
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "../cuda/cuda.hpp"
|
||||
#include "../cuda/uarch.hpp"
|
||||
|
||||
static const char* VERSION = "0.25";
|
||||
static const char* VERSION = "0.30";
|
||||
|
||||
void print_help(char *argv[]) {
|
||||
const char **t = args_str;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "master.hpp"
|
||||
#include "args.hpp"
|
||||
#include "../cuda/cuda.hpp"
|
||||
#include "../hsa/hsa.hpp"
|
||||
#include "../intel/intel.hpp"
|
||||
|
||||
#define MAX_GPUS 1000
|
||||
@@ -35,6 +36,18 @@ struct gpu_list* get_gpu_list() {
|
||||
list->num_gpus += idx;
|
||||
#endif
|
||||
|
||||
#ifdef BACKEND_HSA
|
||||
bool valid = true;
|
||||
|
||||
while(valid) {
|
||||
list->gpus[idx] = get_gpu_info_hsa(devices, idx);
|
||||
if(list->gpus[idx] != NULL) idx++;
|
||||
else valid = false;
|
||||
}
|
||||
|
||||
list->num_gpus += idx;
|
||||
#endif
|
||||
|
||||
#ifdef BACKEND_INTEL
|
||||
list->gpus[idx] = get_gpu_info_intel(devices);
|
||||
if(list->gpus[idx] != NULL) list->num_gpus++;
|
||||
@@ -51,6 +64,11 @@ bool print_gpus_list(struct gpu_list* list) {
|
||||
print_gpu_cuda(list->gpus[i]);
|
||||
#endif
|
||||
}
|
||||
else if(list->gpus[i]->vendor == GPU_VENDOR_AMD) {
|
||||
#ifdef BACKEND_AMD
|
||||
print_gpu_hsa(list->gpus[i]);
|
||||
#endif
|
||||
}
|
||||
else if(list->gpus[i]->vendor == GPU_VENDOR_INTEL) {
|
||||
#ifdef BACKEND_INTEL
|
||||
print_gpu_intel(list->gpus[i]);
|
||||
@@ -69,6 +87,13 @@ void print_enabled_backends() {
|
||||
printf("%sOFF%s\n", C_FG_RED, C_RESET);
|
||||
#endif
|
||||
|
||||
printf("- HSA backend: ");
|
||||
#ifdef BACKEND_HSA
|
||||
printf("%sON%s\n", C_FG_GREEN, C_RESET);
|
||||
#else
|
||||
printf("%sOFF%s\n", C_FG_RED, C_RESET);
|
||||
#endif
|
||||
|
||||
printf("- Intel backend: ");
|
||||
#ifdef BACKEND_INTEL
|
||||
printf("%sON%s\n", C_FG_GREEN, C_RESET);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "../intel/uarch.hpp"
|
||||
#include "../intel/intel.hpp"
|
||||
#include "../hsa/hsa.hpp"
|
||||
#include "../cuda/cuda.hpp"
|
||||
#include "../cuda/uarch.hpp"
|
||||
|
||||
@@ -233,6 +234,9 @@ void choose_ascii_art(struct ascii* art, struct color** cs, struct terminal* ter
|
||||
if(art->vendor == GPU_VENDOR_NVIDIA) {
|
||||
art->art = choose_ascii_art_aux(&logo_nvidia_l, &logo_nvidia, term, lf);
|
||||
}
|
||||
else if(art->vendor == GPU_VENDOR_AMD) {
|
||||
art->art = choose_ascii_art_aux(&logo_amd_l, &logo_amd, term, lf);
|
||||
}
|
||||
else if(art->vendor == GPU_VENDOR_INTEL) {
|
||||
art->art = choose_ascii_art_aux(&logo_intel_l, &logo_intel, term, lf);
|
||||
}
|
||||
@@ -478,6 +482,42 @@ bool print_gpufetch_cuda(struct gpu_info* gpu, STYLE s, struct color** cs, struc
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BACKEND_HSA
|
||||
bool print_gpufetch_amd(struct gpu_info* gpu, STYLE s, struct color** cs, struct terminal* term) {
|
||||
struct ascii* art = set_ascii(get_gpu_vendor(gpu), s);
|
||||
|
||||
if(art == NULL)
|
||||
return false;
|
||||
|
||||
char* gpu_name = get_str_gpu_name(gpu);
|
||||
char* sms = get_str_cu(gpu);
|
||||
char* max_frequency = get_str_freq(gpu);
|
||||
|
||||
setAttribute(art, ATTRIBUTE_NAME, gpu_name);
|
||||
setAttribute(art, ATTRIBUTE_FREQUENCY, max_frequency);
|
||||
setAttribute(art, ATTRIBUTE_STREAMINGMP, sms);
|
||||
|
||||
const char** attribute_fields = ATTRIBUTE_FIELDS;
|
||||
uint32_t longest_attribute = longest_attribute_length(art, attribute_fields);
|
||||
uint32_t longest_field = longest_field_length(art, longest_attribute);
|
||||
choose_ascii_art(art, cs, term, longest_field);
|
||||
|
||||
if(!ascii_fits_screen(term->w, *art->art, longest_field)) {
|
||||
// Despite of choosing the smallest logo, the output does not fit
|
||||
// Choose the shorter field names and recalculate the longest attr
|
||||
attribute_fields = ATTRIBUTE_FIELDS_SHORT;
|
||||
longest_attribute = longest_attribute_length(art, attribute_fields);
|
||||
}
|
||||
|
||||
print_ascii_generic(art, longest_attribute, term->w - art->art->width, attribute_fields);
|
||||
|
||||
free(art->attributes);
|
||||
free(art);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct terminal* get_terminal_size() {
|
||||
struct terminal* term = (struct terminal*) emalloc(sizeof(struct terminal));
|
||||
|
||||
@@ -517,11 +557,22 @@ bool print_gpufetch(struct gpu_info* gpu, STYLE s, struct color** cs) {
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
else if(gpu->vendor == GPU_VENDOR_AMD) {
|
||||
#ifdef BACKEND_HSA
|
||||
return print_gpufetch_amd(gpu, s, cs, term);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
else if(gpu->vendor == GPU_VENDOR_INTEL) {
|
||||
#ifdef BACKEND_INTEL
|
||||
return print_gpufetch_intel(gpu, s, cs, term);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
printErr("Invalid GPU vendor: %d", gpu->vendor);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
130
src/hsa/hsa.cpp
Normal file
130
src/hsa/hsa.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
#include <iostream>
|
||||
#include <hsa/hsa.h>
|
||||
#include <hsa/hsa_ext_amd.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <hsa/hsa.h>
|
||||
#include <hsa/hsa_ext_amd.h>
|
||||
|
||||
#include "hsa.hpp"
|
||||
#include "../common/pci.hpp"
|
||||
#include "../common/global.hpp"
|
||||
#include "../common/uarch.hpp"
|
||||
|
||||
struct agent_info {
|
||||
unsigned deviceId; // ID of the target GPU device
|
||||
char gpu_name[64];
|
||||
char vendor_name[64];
|
||||
char device_mkt_name[64];
|
||||
uint32_t max_clock_freq;
|
||||
uint32_t compute_unit;
|
||||
};
|
||||
|
||||
#define RET_IF_HSA_ERR(err) { \
|
||||
if ((err) != HSA_STATUS_SUCCESS) { \
|
||||
char err_val[12]; \
|
||||
char* err_str = NULL; \
|
||||
if (hsa_status_string(err, \
|
||||
(const char**)&err_str) != HSA_STATUS_SUCCESS) { \
|
||||
snprintf(&(err_val[0]), sizeof(err_val), "%#x", (uint32_t)err); \
|
||||
err_str = &(err_val[0]); \
|
||||
} \
|
||||
printErr("HSA failure at: %s:%d\n", \
|
||||
__FILE__, __LINE__); \
|
||||
printErr("Call returned %s\n", err_str); \
|
||||
return (err); \
|
||||
} \
|
||||
}
|
||||
|
||||
hsa_status_t agent_callback(hsa_agent_t agent, void *data) {
|
||||
struct agent_info* info = reinterpret_cast<struct agent_info *>(data);
|
||||
|
||||
hsa_device_type_t type;
|
||||
hsa_status_t err = hsa_agent_get_info(agent, HSA_AGENT_INFO_DEVICE, &type);
|
||||
RET_IF_HSA_ERR(err);
|
||||
|
||||
if (type == HSA_DEVICE_TYPE_GPU) {
|
||||
err = hsa_agent_get_info(agent, HSA_AGENT_INFO_NAME, info->gpu_name);
|
||||
RET_IF_HSA_ERR(err);
|
||||
|
||||
// TODO: What if vendor_name is not AMD?
|
||||
err = hsa_agent_get_info(agent, HSA_AGENT_INFO_VENDOR_NAME, info->vendor_name);
|
||||
RET_IF_HSA_ERR(err);
|
||||
|
||||
err = hsa_agent_get_info(agent, (hsa_agent_info_t) HSA_AMD_AGENT_INFO_PRODUCT_NAME, &info->device_mkt_name);
|
||||
RET_IF_HSA_ERR(err);
|
||||
|
||||
err = hsa_agent_get_info(agent, (hsa_agent_info_t) HSA_AMD_AGENT_INFO_MAX_CLOCK_FREQUENCY, &info->max_clock_freq);
|
||||
RET_IF_HSA_ERR(err);
|
||||
|
||||
err = hsa_agent_get_info(agent, (hsa_agent_info_t) HSA_AMD_AGENT_INFO_COMPUTE_UNIT_COUNT, &info->compute_unit);
|
||||
RET_IF_HSA_ERR(err);
|
||||
}
|
||||
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
struct topology_h* get_topology_info(struct agent_info info) {
|
||||
struct topology_h* topo = (struct topology_h*) emalloc(sizeof(struct topology_h));
|
||||
|
||||
topo->compute_units = info.compute_unit;
|
||||
|
||||
return topo;
|
||||
}
|
||||
|
||||
struct gpu_info* get_gpu_info_hsa(struct pci_dev *devices, int gpu_idx) {
|
||||
struct gpu_info* gpu = (struct gpu_info*) emalloc(sizeof(struct gpu_info));
|
||||
gpu->pci = NULL;
|
||||
gpu->idx = gpu_idx;
|
||||
|
||||
if(gpu->idx < 0) {
|
||||
printErr("GPU index must be equal or greater than zero");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(gpu->idx > 0) {
|
||||
// Currently we only support fetching GPU 0.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hsa_status_t status;
|
||||
|
||||
// Initialize the HSA runtime
|
||||
status = hsa_init();
|
||||
if (status != HSA_STATUS_SUCCESS) {
|
||||
printErr("Failed to initialize HSA runtime");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct agent_info info;
|
||||
info.deviceId = gpu_idx;
|
||||
|
||||
// Iterate over all agents in the system
|
||||
status = hsa_iterate_agents(agent_callback, &info);
|
||||
if (status != HSA_STATUS_SUCCESS) {
|
||||
printErr("Failed to iterate HSA agents");
|
||||
hsa_shut_down();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gpu->freq = info.max_clock_freq;
|
||||
gpu->vendor = GPU_VENDOR_AMD;
|
||||
gpu->name = (char *) emalloc(sizeof(char) * (strlen(info.device_mkt_name) + 1));
|
||||
strcpy(gpu->name, info.device_mkt_name);
|
||||
gpu->topo_h = get_topology_info(info);
|
||||
|
||||
// TODO: Use gpu_name for uarch detection
|
||||
|
||||
// Shut down the HSA runtime
|
||||
hsa_shut_down();
|
||||
return gpu;
|
||||
}
|
||||
|
||||
char* get_str_cu(struct gpu_info* gpu) {
|
||||
return get_str_generic(gpu->topo_h->compute_units);
|
||||
}
|
||||
9
src/hsa/hsa.hpp
Normal file
9
src/hsa/hsa.hpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef __HSA_GPU__
|
||||
#define __HSA_GPU__
|
||||
|
||||
#include "../common/gpu.hpp"
|
||||
|
||||
struct gpu_info* get_gpu_info_hsa(struct pci_dev *devices, int gpu_idx);
|
||||
char* get_str_cu(struct gpu_info* gpu);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user