1 | //===- AMDGPUArch.cpp - list AMDGPU installed ----------*- C++ -*---------===// |
---|---|
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file implements a tool for detecting name of AMDGPU installed in system |
10 | // using HIP runtime. This tool is used by AMDGPU OpenMP and HIP driver. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "llvm/Support/DynamicLibrary.h" |
15 | #include "llvm/Support/Error.h" |
16 | #include "llvm/Support/raw_ostream.h" |
17 | |
18 | using namespace llvm; |
19 | |
20 | typedef struct { |
21 | char padding[396]; |
22 | char gcnArchName[256]; |
23 | char padding2[1024]; |
24 | } hipDeviceProp_t; |
25 | |
26 | typedef enum { |
27 | hipSuccess = 0, |
28 | } hipError_t; |
29 | |
30 | typedef hipError_t (*hipGetDeviceCount_t)(int *); |
31 | typedef hipError_t (*hipDeviceGet_t)(int *, int); |
32 | typedef hipError_t (*hipGetDeviceProperties_t)(hipDeviceProp_t *, int); |
33 | |
34 | int printGPUsByHIP() { |
35 | #ifdef _WIN32 |
36 | constexpr const char *DynamicHIPPath = "amdhip64.dll"; |
37 | #else |
38 | constexpr const char *DynamicHIPPath = "libamdhip64.so"; |
39 | #endif |
40 | |
41 | std::string ErrMsg; |
42 | auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>( |
43 | args: llvm::sys::DynamicLibrary::getPermanentLibrary(filename: DynamicHIPPath, errMsg: &ErrMsg)); |
44 | if (!DynlibHandle->isValid()) { |
45 | llvm::errs() << "Failed to load "<< DynamicHIPPath << ": "<< ErrMsg |
46 | << '\n'; |
47 | return 1; |
48 | } |
49 | |
50 | #define DYNAMIC_INIT_HIP(SYMBOL) \ |
51 | { \ |
52 | void *SymbolPtr = DynlibHandle->getAddressOfSymbol(#SYMBOL); \ |
53 | if (!SymbolPtr) { \ |
54 | llvm::errs() << "Failed to find symbol " << #SYMBOL << '\n'; \ |
55 | return 1; \ |
56 | } \ |
57 | SYMBOL = reinterpret_cast<decltype(SYMBOL)>(SymbolPtr); \ |
58 | } |
59 | |
60 | hipGetDeviceCount_t hipGetDeviceCount; |
61 | hipDeviceGet_t hipDeviceGet; |
62 | hipGetDeviceProperties_t hipGetDeviceProperties; |
63 | |
64 | DYNAMIC_INIT_HIP(hipGetDeviceCount); |
65 | DYNAMIC_INIT_HIP(hipDeviceGet); |
66 | DYNAMIC_INIT_HIP(hipGetDeviceProperties); |
67 | |
68 | #undef DYNAMIC_INIT_HIP |
69 | |
70 | int deviceCount; |
71 | hipError_t err = hipGetDeviceCount(&deviceCount); |
72 | if (err != hipSuccess) { |
73 | llvm::errs() << "Failed to get device count\n"; |
74 | return 1; |
75 | } |
76 | |
77 | for (int i = 0; i < deviceCount; ++i) { |
78 | int deviceId; |
79 | err = hipDeviceGet(&deviceId, i); |
80 | if (err != hipSuccess) { |
81 | llvm::errs() << "Failed to get device id for ordinal "<< i << '\n'; |
82 | return 1; |
83 | } |
84 | |
85 | hipDeviceProp_t prop; |
86 | err = hipGetDeviceProperties(&prop, deviceId); |
87 | if (err != hipSuccess) { |
88 | llvm::errs() << "Failed to get device properties for device "<< deviceId |
89 | << '\n'; |
90 | return 1; |
91 | } |
92 | llvm::outs() << prop.gcnArchName << '\n'; |
93 | } |
94 | |
95 | return 0; |
96 | } |
97 |