7 Commits

Author SHA1 Message Date
Dr-Noob
bc6e3b35e9 Fixes 2025-10-16 08:25:38 +02:00
Dr-Noob
8c81067577 Fix 2025-10-16 08:22:10 +02:00
Dr-Noob
462f61ce40 Fixes 2025-10-16 08:18:02 +02:00
Dr-Noob
7c361ee879 Not sure this is what we want 2025-10-16 08:14:46 +02:00
Dr-Noob
e0b0a6913c Build pciutils only if neccesary 2025-10-16 07:52:58 +02:00
Dr-Noob
8794cd322d [v0.30] Add support for building on AMD where rocm-cmake is not installed 2025-10-16 07:24:45 +02:00
Dr-Noob
5df85aea2c [v0.30] Add uarch detection to AMD GPUs
Similarly to NVIDIA and Intel GPUs, we now detect microarchitecture,
also with manufacturing process and specific chip name. We infer all
of this from the gfx name (in the code we use the term llvm_target),
altough it's not clear yet that this method is completely reliable (see
comments for more details). In the future we might want to replace that
with a better way. Once we have the gfx name, we *should* be able to
infer the specific chip, and from the chip we can easily infer the
microarchitecture.

This commit also includes some refactorings and code improvements on
the HSA backend.
2025-10-15 08:23:28 +02:00
10 changed files with 103 additions and 43 deletions

View File

@@ -10,9 +10,10 @@ set(CUDA_DIR "${SRC_DIR}/cuda")
set(HSA_DIR "${SRC_DIR}/hsa") set(HSA_DIR "${SRC_DIR}/hsa")
set(INTEL_DIR "${SRC_DIR}/intel") set(INTEL_DIR "${SRC_DIR}/intel")
# Enable Intel backend by default # Make sure that at least one backend is enabled.
if(NOT DEFINED ENABLE_INTEL_BACKEND) # It does not make sense that the user has not specified any backend.
set(ENABLE_INTEL_BACKEND true) if(NOT ENABLE_INTEL_BACKEND AND NOT ENABLE_CUDA_BACKEND AND NOT ENABLE_HSA_BACKEND)
message(FATAL_ERROR "No backend was enabled! Please enable at least one backend with -DENABLE_XXX_BACKEND")
endif() endif()
if(ENABLE_CUDA_BACKEND) if(ENABLE_CUDA_BACKEND)
@@ -27,8 +28,7 @@ if(ENABLE_CUDA_BACKEND)
endif() endif()
if(ENABLE_HSA_BACKEND) if(ENABLE_HSA_BACKEND)
# TODO: Needs rocm-cmake, what if its not insalled? find_package(ROCmCMakeBuildTools QUIET)
find_package(ROCmCMakeBuildTools)
if (ROCmCMakeBuildTools_FOUND) if (ROCmCMakeBuildTools_FOUND)
find_package(hsa-runtime64 1.0 REQUIRED) find_package(hsa-runtime64 1.0 REQUIRED)
link_directories(hsa_backend hsa-runtime64::hsa-runtime64) link_directories(hsa_backend hsa-runtime64::hsa-runtime64)
@@ -48,15 +48,51 @@ if(ENABLE_HSA_BACKEND)
message(STATUS "${BoldYellow}HSA not found, disabling HSA backend${ColorReset}") message(STATUS "${BoldYellow}HSA not found, disabling HSA backend${ColorReset}")
set(ENABLE_HSA_BACKEND false) set(ENABLE_HSA_BACKEND false)
endif() endif()
else()
# rocm-cmake is not installed, try to manually find neccesary files.
message(STATUS "${BoldYellow}Could NOT find HSA automatically, running manual search...${ColorReset}")
if (NOT DEFINED ROCM_PATH)
set(ROCM_PATH "/opt/rocm" CACHE PATH "Path to ROCm")
endif()
find_path(HSA_INCLUDE_DIR hsa/hsa.h HINTS ${ROCM_PATH}/include)
find_library(HSA_LIBRARY hsa-runtime64 HINTS ${ROCM_PATH}/lib ${ROCM_PATH}/lib64)
if (HSA_INCLUDE_DIR AND HSA_LIBRARY)
message(STATUS "${BoldYellow}HSA was found manually${ColorReset}")
else() else()
set(ENABLE_HSA_BACKEND false) set(ENABLE_HSA_BACKEND false)
message(STATUS "${BoldYellow}ROCm not found${ColorReset}") message(STATUS "${BoldYellow}HSA was not found manually${ColorReset}")
endif()
endif() endif()
endif() endif()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(GPUFECH_COMMON
find_package(PCIUTILS) ${COMMON_DIR}/main.cpp
if(NOT ${PCIUTILS_FOUND}) ${COMMON_DIR}/args.cpp
${COMMON_DIR}/gpu.cpp
${COMMON_DIR}/global.cpp
${COMMON_DIR}/printer.cpp
${COMMON_DIR}/master.cpp
${COMMON_DIR}/uarch.cpp
)
set(GPUFETCH_LINK_TARGETS z)
if(NOT(ENABLE_HSA_BACKEND AND NOT ENABLE_CUDA_BACKEND AND NOT ENABLE_INTEL_BACKEND))
# Look for pciutils only if not building HSA only.
#
# This has the (intented) secondary effect that if only HSA backend is enabled
# by the user, but ROCm cannot be found, pciutils will still be compiled in
# order to show the list of GPUs available on the system, so that the user will
# get at least some feedback even if HSA is not found.
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
list(APPEND GPUFECH_COMMON ${COMMON_DIR}/pci.cpp ${COMMON_DIR}/sort.cpp)
list(APPEND GPUFETCH_LINK_TARGETS pci)
set(CMAKE_ENABLE_PCIUTILS ON)
find_package(PCIUTILS)
if(NOT ${PCIUTILS_FOUND})
message(STATUS "${BoldYellow}pciutils not found, downloading and building a local copy...${ColorReset}") message(STATUS "${BoldYellow}pciutils not found, downloading and building a local copy...${ColorReset}")
# Download and build pciutils # Download and build pciutils
@@ -71,18 +107,23 @@ if(NOT ${PCIUTILS_FOUND})
include_directories(${PCIUTILS_INSTALL_LOCATION}/include) include_directories(${PCIUTILS_INSTALL_LOCATION}/include)
link_directories(${PCIUTILS_INSTALL_LOCATION}/lib) link_directories(${PCIUTILS_INSTALL_LOCATION}/lib)
else() else()
include_directories(${PCIUTILS_INCLUDE_DIR}) include_directories(${PCIUTILS_INCLUDE_DIR})
link_libraries(${PCIUTILS_LIBRARIES}) link_libraries(${PCIUTILS_LIBRARIES})
# Needed for linking libpci in FreeBSD # Needed for linking libpci in FreeBSD
link_directories(/usr/local/lib/) link_directories(/usr/local/lib/)
endif()
endif() 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) add_executable(gpufetch ${GPUFECH_COMMON})
set(SANITY_FLAGS -Wfloat-equal -Wshadow -Wpointer-arith -Wall -Wextra -pedantic -fstack-protector-all -pedantic) 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_features(gpufetch PRIVATE cxx_std_11)
target_compile_options(gpufetch PRIVATE ${SANITY_FLAGS}) target_compile_options(gpufetch PRIVATE ${SANITY_FLAGS})
if (CMAKE_ENABLE_PCIUTILS)
target_compile_definitions(gpufetch PUBLIC BACKEND_USE_PCI)
endif()
if(ENABLE_INTEL_BACKEND) if(ENABLE_INTEL_BACKEND)
target_compile_definitions(gpufetch PUBLIC BACKEND_INTEL) target_compile_definitions(gpufetch PUBLIC BACKEND_INTEL)
@@ -134,13 +175,17 @@ if(ENABLE_HSA_BACKEND)
endif() endif()
target_include_directories(hsa_backend PRIVATE "${HSA_INCLUDE_DIR}") target_include_directories(hsa_backend PRIVATE "${HSA_INCLUDE_DIR}")
message(STATUS "Found HSA: ${HSA_INCLUDE_DIR}")
if (HSA_LIBRARY)
target_link_libraries(hsa_backend PRIVATE ${HSA_LIBRARY})
else()
target_link_libraries(hsa_backend PRIVATE hsa-runtime64::hsa-runtime64) target_link_libraries(hsa_backend PRIVATE hsa-runtime64::hsa-runtime64)
endif()
target_link_libraries(gpufetch hsa_backend) target_link_libraries(gpufetch hsa_backend)
endif() endif()
target_link_libraries(gpufetch pci z) target_link_libraries(gpufetch ${GPUFETCH_LINK_TARGETS})
install(TARGETS gpufetch DESTINATION bin) install(TARGETS gpufetch DESTINATION bin)
if(NOT WIN32) if(NOT WIN32)

View File

@@ -3,8 +3,6 @@
#include <cstdint> #include <cstdint>
#include "../cuda/pci.hpp"
#define UNKNOWN_FREQ -1 #define UNKNOWN_FREQ -1
enum { enum {

View File

@@ -8,6 +8,10 @@
#include "../cuda/cuda.hpp" #include "../cuda/cuda.hpp"
#include "../cuda/uarch.hpp" #include "../cuda/uarch.hpp"
#ifdef BACKEND_USE_PCI
#include "pci.hpp"
#endif
static const char* VERSION = "0.30"; static const char* VERSION = "0.30";
void print_help(char *argv[]) { void print_help(char *argv[]) {
@@ -79,8 +83,12 @@ int main(int argc, char* argv[]) {
} }
if(get_num_gpus_available(list) == 0) { if(get_num_gpus_available(list) == 0) {
#ifdef BACKEND_USE_PCI
printErr("No GPU was detected! Available GPUs are:"); printErr("No GPU was detected! Available GPUs are:");
print_gpus_list_pci(); print_gpus_list_pci();
#else
printErr("No GPU was detected!");
#endif
printf("Please, make sure that the appropiate backend is enabled:\n"); printf("Please, make sure that the appropiate backend is enabled:\n");
print_enabled_backends(); print_enabled_backends();
printf("Visit https://github.com/Dr-Noob/gpufetch#2-backends for more information\n"); printf("Visit https://github.com/Dr-Noob/gpufetch#2-backends for more information\n");

View File

@@ -1,7 +1,10 @@
#include <cstdlib> #include <cstdlib>
#include <cstdio> #include <cstdio>
#include "pci.hpp" #ifdef BACKEND_USE_PCI
#include "pci.hpp"
#endif
#include "global.hpp" #include "global.hpp"
#include "colors.hpp" #include "colors.hpp"
#include "master.hpp" #include "master.hpp"
@@ -19,7 +22,9 @@ struct gpu_list {
struct gpu_list* get_gpu_list() { struct gpu_list* get_gpu_list() {
int idx = 0; int idx = 0;
#ifdef BACKEND_USE_PCI
struct pci_dev *devices = get_pci_devices_from_pciutils(); struct pci_dev *devices = get_pci_devices_from_pciutils();
#endif
struct gpu_list* list = (struct gpu_list*) malloc(sizeof(struct gpu_list)); struct gpu_list* list = (struct gpu_list*) malloc(sizeof(struct gpu_list));
list->num_gpus = 0; list->num_gpus = 0;
list->gpus = (struct gpu_info**) malloc(sizeof(struct info*) * MAX_GPUS); list->gpus = (struct gpu_info**) malloc(sizeof(struct info*) * MAX_GPUS);
@@ -40,7 +45,7 @@ struct gpu_list* get_gpu_list() {
bool valid = true; bool valid = true;
while(valid) { while(valid) {
list->gpus[idx] = get_gpu_info_hsa(devices, idx); list->gpus[idx] = get_gpu_info_hsa(idx);
if(list->gpus[idx] != NULL) idx++; if(list->gpus[idx] != NULL) idx++;
else valid = false; else valid = false;
} }

View File

@@ -5,8 +5,8 @@
#include "cuda.hpp" #include "cuda.hpp"
#include "uarch.hpp" #include "uarch.hpp"
#include "pci.hpp"
#include "gpufetch_helper_cuda.hpp" #include "gpufetch_helper_cuda.hpp"
#include "../common/pci.hpp"
#include "../common/global.hpp" #include "../common/global.hpp"
#include "../common/uarch.hpp" #include "../common/uarch.hpp"
@@ -33,10 +33,8 @@ int get_tensor_cores(struct uarch* arch, int sm, int major) {
if(major == 7) { if(major == 7) {
// TU116 does not have tensor cores! // TU116 does not have tensor cores!
// https://www.anandtech.com/show/13973/nvidia-gtx-1660-ti-review-feat-evga-xc-gaming/2 // https://www.anandtech.com/show/13973/nvidia-gtx-1660-ti-review-feat-evga-xc-gaming/2
if(arch->chip == CHIP_TU116 || arch->chip == CHIP_TU116BM || if (is_chip_TU116(arch))
arch->chip == CHIP_TU116GL || arch->chip == CHIP_TU116M) {
return 0; return 0;
}
return sm * 8; return sm * 8;
} }
else if(major == 8) return sm * 4; else if(major == 8) return sm * 4;

View File

@@ -8,6 +8,7 @@
#include "../common/uarch.hpp" #include "../common/uarch.hpp"
#include "../common/global.hpp" #include "../common/global.hpp"
#include "../common/gpu.hpp" #include "../common/gpu.hpp"
#include "pci.hpp"
#include "chips.hpp" #include "chips.hpp"
// Any clock multiplier // Any clock multiplier
@@ -361,3 +362,8 @@ void free_uarch_struct(struct uarch* arch) {
free(arch->chip_str); free(arch->chip_str);
free(arch); free(arch);
} }
bool is_chip_TU116(struct uarch* arch) {
return arch->chip == CHIP_TU116 || arch->chip == CHIP_TU116BM ||
arch->chip == CHIP_TU116GL || arch->chip == CHIP_TU116M;
}

View File

@@ -13,5 +13,6 @@ char* get_str_cc(struct uarch* arch);
char* get_str_chip(struct uarch* arch); char* get_str_chip(struct uarch* arch);
char* get_str_process(struct uarch* arch); char* get_str_process(struct uarch* arch);
void free_uarch_struct(struct uarch* arch); void free_uarch_struct(struct uarch* arch);
bool is_chip_TU116(struct uarch* arch);
#endif #endif

View File

@@ -13,7 +13,6 @@
#include "hsa.hpp" #include "hsa.hpp"
#include "uarch.hpp" #include "uarch.hpp"
#include "../common/pci.hpp"
#include "../common/global.hpp" #include "../common/global.hpp"
#include "../common/uarch.hpp" #include "../common/uarch.hpp"
@@ -76,7 +75,7 @@ struct topology_h* get_topology_info(struct agent_info info) {
return topo; return topo;
} }
struct gpu_info* get_gpu_info_hsa(struct pci_dev *devices, int gpu_idx) { struct gpu_info* get_gpu_info_hsa(int gpu_idx) {
struct gpu_info* gpu = (struct gpu_info*) emalloc(sizeof(struct gpu_info)); struct gpu_info* gpu = (struct gpu_info*) emalloc(sizeof(struct gpu_info));
gpu->pci = NULL; gpu->pci = NULL;
gpu->idx = gpu_idx; gpu->idx = gpu_idx;

View File

@@ -3,7 +3,7 @@
#include "../common/gpu.hpp" #include "../common/gpu.hpp"
struct gpu_info* get_gpu_info_hsa(struct pci_dev *devices, int gpu_idx); struct gpu_info* get_gpu_info_hsa(int gpu_idx);
char* get_str_cu(struct gpu_info* gpu); char* get_str_cu(struct gpu_info* gpu);
#endif #endif

View File

@@ -127,7 +127,7 @@ enum {
#define CHECK_UARCH_START if (false) {} #define CHECK_UARCH_START if (false) {}
#define CHECK_UARCH(arch, chip_, str, uarch, process) \ #define CHECK_UARCH(arch, chip_, str, uarch, process) \
else if (arch->chip == chip_) fill_uarch(arch, str, uarch, process); else if (arch->chip == chip_) fill_uarch(arch, str, uarch, process);
#define CHECK_UARCH_END else { if(arch->chip != CHIP_UNKNOWN_CUDA) printBug("map_chip_to_uarch_hsa: Unknown chip id: %d", arch->chip); fill_uarch(arch, STRING_UNKNOWN, UARCH_UNKNOWN, UNK); } #define CHECK_UARCH_END else { if(arch->chip != CHIP_UNKNOWN_HSA) printBug("map_chip_to_uarch_hsa: Unknown chip id: %d", arch->chip); fill_uarch(arch, STRING_UNKNOWN, UARCH_UNKNOWN, UNK); }
void fill_uarch(struct uarch* arch, char const *str, MICROARCH u, uint32_t process) { void fill_uarch(struct uarch* arch, char const *str, MICROARCH u, uint32_t process) {
arch->chip_str = (char *) emalloc(sizeof(char) * (strlen(str)+1)); arch->chip_str = (char *) emalloc(sizeof(char) * (strlen(str)+1));