Author: Joseph Huber Date: 2024-11-19T05:35:01-06:00 New Revision: 129a1a27da34eab1e358f4a403f05e8efe44c586
URL: https://github.com/llvm/llvm-project/commit/129a1a27da34eab1e358f4a403f05e8efe44c586 DIFF: https://github.com/llvm/llvm-project/commit/129a1a27da34eab1e358f4a403f05e8efe44c586.diff LOG: [amdgpu-arch] Replace use of HSA with reading sysfs directly (#116651) Summary: For Linux systems, we currently use the HSA library to determine the installed GPUs. However, this isn't really necessary and adds a dependency on the HSA runtime as well as a lot of overhead. Instead, this patch uses the `sysfs` interface exposed by `amdkfd` to do this directly. Added: clang/tools/amdgpu-arch/AMDGPUArchByKFD.cpp Modified: clang/tools/amdgpu-arch/AMDGPUArch.cpp clang/tools/amdgpu-arch/CMakeLists.txt Removed: clang/tools/amdgpu-arch/AMDGPUArchByHSA.cpp ################################################################################ diff --git a/clang/tools/amdgpu-arch/AMDGPUArch.cpp b/clang/tools/amdgpu-arch/AMDGPUArch.cpp index 7ae57b7877e1fe..6c10cbc5c46a83 100644 --- a/clang/tools/amdgpu-arch/AMDGPUArch.cpp +++ b/clang/tools/amdgpu-arch/AMDGPUArch.cpp @@ -25,7 +25,7 @@ static void PrintVersion(raw_ostream &OS) { OS << clang::getClangToolFullVersion("amdgpu-arch") << '\n'; } -int printGPUsByHSA(); +int printGPUsByKFD(); int printGPUsByHIP(); int main(int argc, char *argv[]) { @@ -45,7 +45,7 @@ int main(int argc, char *argv[]) { } #ifndef _WIN32 - if (!printGPUsByHSA()) + if (!printGPUsByKFD()) return 0; #endif diff --git a/clang/tools/amdgpu-arch/AMDGPUArchByHSA.cpp b/clang/tools/amdgpu-arch/AMDGPUArchByHSA.cpp deleted file mode 100644 index 432f2c414ed244..00000000000000 --- a/clang/tools/amdgpu-arch/AMDGPUArchByHSA.cpp +++ /dev/null @@ -1,122 +0,0 @@ -//===- AMDGPUArchByHSA.cpp - list AMDGPU installed ------*- C++ -*---------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements a tool for detecting name of AMDGPU installed in system -// using HSA on Linux. This tool is used by AMDGPU OpenMP and HIP driver. -// -//===----------------------------------------------------------------------===// - -#include "clang/Basic/Version.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/DynamicLibrary.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/raw_ostream.h" -#include <memory> -#include <string> -#include <vector> - -using namespace llvm; - -typedef enum { - HSA_STATUS_SUCCESS = 0x0, -} hsa_status_t; - -typedef enum { - HSA_DEVICE_TYPE_CPU = 0, - HSA_DEVICE_TYPE_GPU = 1, -} hsa_device_type_t; - -typedef enum { - HSA_AGENT_INFO_NAME = 0, - HSA_AGENT_INFO_DEVICE = 17, -} hsa_agent_info_t; - -typedef struct hsa_agent_s { - uint64_t handle; -} hsa_agent_t; - -hsa_status_t (*hsa_init)(); -hsa_status_t (*hsa_shut_down)(); -hsa_status_t (*hsa_agent_get_info)(hsa_agent_t, hsa_agent_info_t, void *); -hsa_status_t (*hsa_iterate_agents)(hsa_status_t (*)(hsa_agent_t, void *), - void *); - -constexpr const char *DynamicHSAPath = "libhsa-runtime64.so"; - -llvm::Error loadHSA() { - std::string ErrMsg; - auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>( - llvm::sys::DynamicLibrary::getPermanentLibrary(DynamicHSAPath, &ErrMsg)); - if (!DynlibHandle->isValid()) { - return llvm::createStringError(llvm::inconvertibleErrorCode(), - "Failed to 'dlopen' %s", DynamicHSAPath); - } -#define DYNAMIC_INIT(SYMBOL) \ - { \ - void *SymbolPtr = DynlibHandle->getAddressOfSymbol(#SYMBOL); \ - if (!SymbolPtr) \ - return llvm::createStringError(llvm::inconvertibleErrorCode(), \ - "Failed to 'dlsym' " #SYMBOL); \ - SYMBOL = reinterpret_cast<decltype(SYMBOL)>(SymbolPtr); \ - } - DYNAMIC_INIT(hsa_init); - DYNAMIC_INIT(hsa_shut_down); - DYNAMIC_INIT(hsa_agent_get_info); - DYNAMIC_INIT(hsa_iterate_agents); -#undef DYNAMIC_INIT - return llvm::Error::success(); -} - -static hsa_status_t iterateAgentsCallback(hsa_agent_t Agent, void *Data) { - hsa_device_type_t DeviceType; - hsa_status_t Status = - hsa_agent_get_info(Agent, HSA_AGENT_INFO_DEVICE, &DeviceType); - - // continue only if device type if GPU - if (Status != HSA_STATUS_SUCCESS || DeviceType != HSA_DEVICE_TYPE_GPU) { - return Status; - } - - std::vector<std::string> *GPUs = - static_cast<std::vector<std::string> *>(Data); - char GPUName[64]; - Status = hsa_agent_get_info(Agent, HSA_AGENT_INFO_NAME, GPUName); - if (Status != HSA_STATUS_SUCCESS) { - return Status; - } - GPUs->push_back(GPUName); - return HSA_STATUS_SUCCESS; -} - -int printGPUsByHSA() { - // Attempt to load the HSA runtime. - if (llvm::Error Err = loadHSA()) { - logAllUnhandledErrors(std::move(Err), llvm::errs()); - return 1; - } - - hsa_status_t Status = hsa_init(); - if (Status != HSA_STATUS_SUCCESS) { - return 1; - } - - std::vector<std::string> GPUs; - Status = hsa_iterate_agents(iterateAgentsCallback, &GPUs); - if (Status != HSA_STATUS_SUCCESS) { - return 1; - } - - for (const auto &GPU : GPUs) - llvm::outs() << GPU << '\n'; - - if (GPUs.size() < 1) - return 1; - - hsa_shut_down(); - return 0; -} diff --git a/clang/tools/amdgpu-arch/AMDGPUArchByKFD.cpp b/clang/tools/amdgpu-arch/AMDGPUArchByKFD.cpp new file mode 100644 index 00000000000000..0e169f654a4cb4 --- /dev/null +++ b/clang/tools/amdgpu-arch/AMDGPUArchByKFD.cpp @@ -0,0 +1,78 @@ +//===- AMDGPUArchByKFD.cpp - list AMDGPU installed ------*- C++ -*---------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements a tool for detecting name of AMD GPUs installed in +// system using the Linux sysfs interface for the AMD KFD driver. This file does +// not respect ROCR_VISIBLE_DEVICES like the ROCm environment would. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/LineIterator.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include <memory> +#include <string> + +using namespace llvm; + +constexpr static const char *KFD_SYSFS_NODE_PATH = + "/sys/devices/virtual/kfd/kfd/topology/nodes"; + +// See the ROCm implementation for how this is handled. +// https://github.com/ROCm/ROCT-Thunk-Interface/blob/master/src/libhsakmt.h#L126 +constexpr static long getMajor(long Ver) { return (Ver / 10000) % 100; } +constexpr static long getMinor(long Ver) { return (Ver / 100) % 100; } +constexpr static long getStep(long Ver) { return Ver % 100; } + +int printGPUsByKFD() { + SmallVector<std::pair<long, long>> Devices; + std::error_code EC; + for (sys::fs::directory_iterator Begin(KFD_SYSFS_NODE_PATH, EC), End; + Begin != End; Begin.increment(EC)) { + if (EC) + return 1; + + long Node = 0; + if (sys::path::stem(Begin->path()).consumeInteger(10, Node)) + return 1; + + SmallString<0> Path(Begin->path()); + sys::path::append(Path, "properties"); + + ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = + MemoryBuffer::getFileOrSTDIN(Path); + if (std::error_code EC = BufferOrErr.getError()) + return 1; + + long GFXVersion = 0; + for (line_iterator Lines(**BufferOrErr, false); !Lines.is_at_end(); + ++Lines) { + StringRef Line(*Lines); + if (Line.consume_front("gfx_target_version")) { + Line.drop_while([](char C) { return std::isspace(C); }); + if (Line.consumeInteger(10, GFXVersion)) + return 1; + break; + } + } + + // If this is zero the node is a CPU. + if (GFXVersion == 0) + continue; + Devices.emplace_back(Node, GFXVersion); + } + + // Sort the devices by their node to make sure it prints in order. + llvm::sort(Devices, [](auto &L, auto &R) { return L.first < R.first; }); + for (const auto &[Node, GFXVersion] : Devices) + std::fprintf(stdout, "gfx%ld%ld%lx\n", getMajor(GFXVersion), + getMinor(GFXVersion), getStep(GFXVersion)); + + return 0; +} diff --git a/clang/tools/amdgpu-arch/CMakeLists.txt b/clang/tools/amdgpu-arch/CMakeLists.txt index 1657c701251308..c4c8de614565a7 100644 --- a/clang/tools/amdgpu-arch/CMakeLists.txt +++ b/clang/tools/amdgpu-arch/CMakeLists.txt @@ -8,6 +8,6 @@ set(LLVM_LINK_COMPONENTS Support) -add_clang_tool(amdgpu-arch AMDGPUArch.cpp AMDGPUArchByHSA.cpp AMDGPUArchByHIP.cpp) +add_clang_tool(amdgpu-arch AMDGPUArch.cpp AMDGPUArchByKFD.cpp AMDGPUArchByHIP.cpp) target_link_libraries(amdgpu-arch PRIVATE clangBasic) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits