|
1 | | -//===- llvm-offload-device-info.cpp - Print liboffload properties ---------===// |
| 1 | +//===- llvm-offload-device-info.cpp - Device info as seen by LLVM/Offload -===// |
2 | 2 | // |
3 | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | 4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | 6 | // |
7 | 7 | //===----------------------------------------------------------------------===// |
8 | 8 | // |
9 | | -// This is a command line utility that, by using the new liboffload API, prints |
10 | | -// all devices and properties |
| 9 | +// This is a command line utility that, by using LLVM/Offload, and the device |
| 10 | +// plugins, list devices information as seen by the runtime. |
11 | 11 | // |
12 | 12 | //===----------------------------------------------------------------------===// |
13 | 13 |
|
14 | | -#include <OffloadAPI.h> |
15 | | -#include <iostream> |
16 | | -#include <vector> |
17 | | - |
18 | | -#define OFFLOAD_ERR(X) \ |
19 | | - if (auto Err = X) { \ |
20 | | - return Err; \ |
21 | | - } |
22 | | - |
23 | | -enum class PrintKind { |
24 | | - NORMAL, |
25 | | - FP_FLAGS, |
26 | | -}; |
27 | | - |
28 | | -template <typename T, PrintKind PK = PrintKind::NORMAL> |
29 | | -void doWrite(std::ostream &S, T &&Val) { |
30 | | - S << Val; |
31 | | -} |
32 | | - |
33 | | -template <> |
34 | | -void doWrite<ol_platform_backend_t>(std::ostream &S, |
35 | | - ol_platform_backend_t &&Val) { |
36 | | - switch (Val) { |
37 | | - case OL_PLATFORM_BACKEND_UNKNOWN: |
38 | | - S << "UNKNOWN"; |
39 | | - break; |
40 | | - case OL_PLATFORM_BACKEND_CUDA: |
41 | | - S << "CUDA"; |
42 | | - break; |
43 | | - case OL_PLATFORM_BACKEND_AMDGPU: |
44 | | - S << "AMDGPU"; |
45 | | - break; |
46 | | - case OL_PLATFORM_BACKEND_HOST: |
47 | | - S << "HOST"; |
48 | | - break; |
49 | | - default: |
50 | | - S << "<< INVALID >>"; |
51 | | - break; |
52 | | - } |
53 | | -} |
54 | | -template <> |
55 | | -void doWrite<ol_device_type_t>(std::ostream &S, ol_device_type_t &&Val) { |
56 | | - switch (Val) { |
57 | | - case OL_DEVICE_TYPE_GPU: |
58 | | - S << "GPU"; |
59 | | - break; |
60 | | - case OL_DEVICE_TYPE_CPU: |
61 | | - S << "CPU"; |
62 | | - break; |
63 | | - case OL_DEVICE_TYPE_HOST: |
64 | | - S << "HOST"; |
65 | | - break; |
66 | | - default: |
67 | | - S << "<< INVALID >>"; |
68 | | - break; |
69 | | - } |
70 | | -} |
71 | | -template <> |
72 | | -void doWrite<ol_dimensions_t>(std::ostream &S, ol_dimensions_t &&Val) { |
73 | | - S << "{x: " << Val.x << ", y: " << Val.y << ", z: " << Val.z << "}"; |
74 | | -} |
75 | | -template <> |
76 | | -void doWrite<ol_device_fp_capability_flags_t, PrintKind::FP_FLAGS>( |
77 | | - std::ostream &S, ol_device_fp_capability_flags_t &&Val) { |
78 | | - S << Val << " {"; |
79 | | - |
80 | | - if (Val & OL_DEVICE_FP_CAPABILITY_FLAG_CORRECTLY_ROUNDED_DIVIDE_SQRT) { |
81 | | - S << " CORRECTLY_ROUNDED_DIVIDE_SQRT"; |
82 | | - } |
83 | | - if (Val & OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_NEAREST) { |
84 | | - S << " ROUND_TO_NEAREST"; |
85 | | - } |
86 | | - if (Val & OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_ZERO) { |
87 | | - S << " ROUND_TO_ZERO"; |
88 | | - } |
89 | | - if (Val & OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_INF) { |
90 | | - S << " ROUND_TO_INF"; |
91 | | - } |
92 | | - if (Val & OL_DEVICE_FP_CAPABILITY_FLAG_INF_NAN) { |
93 | | - S << " INF_NAN"; |
94 | | - } |
95 | | - if (Val & OL_DEVICE_FP_CAPABILITY_FLAG_DENORM) { |
96 | | - S << " DENORM"; |
97 | | - } |
98 | | - if (Val & OL_DEVICE_FP_CAPABILITY_FLAG_FMA) { |
99 | | - S << " FMA"; |
100 | | - } |
101 | | - if (Val & OL_DEVICE_FP_CAPABILITY_FLAG_SOFT_FLOAT) { |
102 | | - S << " SOFT_FLOAT"; |
103 | | - } |
104 | | - |
105 | | - S << " }"; |
106 | | -} |
107 | | - |
108 | | -template <typename T> |
109 | | -ol_result_t printPlatformValue(std::ostream &S, ol_platform_handle_t Plat, |
110 | | - ol_platform_info_t Info, const char *Desc) { |
111 | | - S << Desc << ": "; |
112 | | - |
113 | | - if constexpr (std::is_pointer_v<T>) { |
114 | | - std::vector<uint8_t> Val; |
115 | | - size_t Size; |
116 | | - OFFLOAD_ERR(olGetPlatformInfoSize(Plat, Info, &Size)); |
117 | | - Val.resize(Size); |
118 | | - OFFLOAD_ERR(olGetPlatformInfo(Plat, Info, sizeof(Val), Val.data())); |
119 | | - doWrite(S, reinterpret_cast<T>(Val.data())); |
120 | | - } else { |
121 | | - T Val; |
122 | | - OFFLOAD_ERR(olGetPlatformInfo(Plat, Info, sizeof(Val), &Val)); |
123 | | - doWrite(S, std::move(Val)); |
124 | | - } |
125 | | - S << "\n"; |
126 | | - return OL_SUCCESS; |
127 | | -} |
128 | | - |
129 | | -template <typename T, PrintKind PK = PrintKind::NORMAL> |
130 | | -ol_result_t printDeviceValue(std::ostream &S, ol_device_handle_t Dev, |
131 | | - ol_device_info_t Info, const char *Desc, |
132 | | - const char *Units = nullptr) { |
133 | | - S << Desc << ": "; |
134 | | - |
135 | | - if constexpr (std::is_pointer_v<T>) { |
136 | | - std::vector<uint8_t> Val; |
137 | | - size_t Size; |
138 | | - OFFLOAD_ERR(olGetDeviceInfoSize(Dev, Info, &Size)); |
139 | | - Val.resize(Size); |
140 | | - OFFLOAD_ERR(olGetDeviceInfo(Dev, Info, sizeof(Val), Val.data())); |
141 | | - doWrite<T, PK>(S, reinterpret_cast<T>(Val.data())); |
142 | | - } else { |
143 | | - T Val; |
144 | | - OFFLOAD_ERR(olGetDeviceInfo(Dev, Info, sizeof(Val), &Val)); |
145 | | - doWrite<T, PK>(S, std::move(Val)); |
146 | | - } |
147 | | - if (Units) |
148 | | - S << " " << Units; |
149 | | - S << "\n"; |
150 | | - return OL_SUCCESS; |
151 | | -} |
152 | | - |
153 | | -ol_result_t printDevice(std::ostream &S, ol_device_handle_t D) { |
154 | | - ol_platform_handle_t Platform; |
155 | | - OFFLOAD_ERR( |
156 | | - olGetDeviceInfo(D, OL_DEVICE_INFO_PLATFORM, sizeof(Platform), &Platform)); |
157 | | - |
158 | | - std::vector<char> Name; |
159 | | - size_t NameSize; |
160 | | - OFFLOAD_ERR(olGetDeviceInfoSize(D, OL_DEVICE_INFO_PRODUCT_NAME, &NameSize)) |
161 | | - Name.resize(NameSize); |
162 | | - OFFLOAD_ERR( |
163 | | - olGetDeviceInfo(D, OL_DEVICE_INFO_PRODUCT_NAME, NameSize, Name.data())); |
164 | | - S << "[" << Name.data() << "]\n"; |
165 | | - |
166 | | - OFFLOAD_ERR(printPlatformValue<const char *>( |
167 | | - S, Platform, OL_PLATFORM_INFO_NAME, "Platform Name")); |
168 | | - OFFLOAD_ERR(printPlatformValue<const char *>( |
169 | | - S, Platform, OL_PLATFORM_INFO_VENDOR_NAME, "Platform Vendor Name")); |
170 | | - OFFLOAD_ERR(printPlatformValue<const char *>( |
171 | | - S, Platform, OL_PLATFORM_INFO_VERSION, "Platform Version")); |
172 | | - OFFLOAD_ERR(printPlatformValue<ol_platform_backend_t>( |
173 | | - S, Platform, OL_PLATFORM_INFO_BACKEND, "Platform Backend")); |
174 | | - |
175 | | - OFFLOAD_ERR( |
176 | | - printDeviceValue<const char *>(S, D, OL_DEVICE_INFO_NAME, "Name")); |
177 | | - OFFLOAD_ERR( |
178 | | - printDeviceValue<ol_device_type_t>(S, D, OL_DEVICE_INFO_TYPE, "Type")); |
179 | | - OFFLOAD_ERR(printDeviceValue<const char *>( |
180 | | - S, D, OL_DEVICE_INFO_DRIVER_VERSION, "Driver Version")); |
181 | | - OFFLOAD_ERR(printDeviceValue<uint32_t>( |
182 | | - S, D, OL_DEVICE_INFO_MAX_WORK_GROUP_SIZE, "Max Work Group Size")); |
183 | | - OFFLOAD_ERR(printDeviceValue<ol_dimensions_t>( |
184 | | - S, D, OL_DEVICE_INFO_MAX_WORK_GROUP_SIZE_PER_DIMENSION, |
185 | | - "Max Work Group Size Per Dimension")); |
186 | | - OFFLOAD_ERR(printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_MAX_WORK_SIZE, |
187 | | - "Max Work Size")); |
188 | | - OFFLOAD_ERR(printDeviceValue<ol_dimensions_t>( |
189 | | - S, D, OL_DEVICE_INFO_MAX_WORK_SIZE_PER_DIMENSION, |
190 | | - "Max Work Size Per Dimension")); |
191 | | - OFFLOAD_ERR( |
192 | | - printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_VENDOR_ID, "Vendor ID")); |
193 | | - OFFLOAD_ERR(printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_NUM_COMPUTE_UNITS, |
194 | | - "Num Compute Units")); |
195 | | - OFFLOAD_ERR(printDeviceValue<uint32_t>( |
196 | | - S, D, OL_DEVICE_INFO_MAX_CLOCK_FREQUENCY, "Max Clock Frequency", "MHz")); |
197 | | - OFFLOAD_ERR(printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_MEMORY_CLOCK_RATE, |
198 | | - "Memory Clock Rate", "MHz")); |
199 | | - OFFLOAD_ERR(printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_ADDRESS_BITS, |
200 | | - "Address Bits")); |
201 | | - OFFLOAD_ERR(printDeviceValue<uint64_t>( |
202 | | - S, D, OL_DEVICE_INFO_MAX_MEM_ALLOC_SIZE, "Max Mem Allocation Size", "B")); |
203 | | - OFFLOAD_ERR(printDeviceValue<uint64_t>(S, D, OL_DEVICE_INFO_GLOBAL_MEM_SIZE, |
204 | | - "Global Mem Size", "B")); |
205 | | - OFFLOAD_ERR( |
206 | | - (printDeviceValue<ol_device_fp_capability_flags_t, PrintKind::FP_FLAGS>( |
207 | | - S, D, OL_DEVICE_INFO_SINGLE_FP_CONFIG, |
208 | | - "Single Precision Floating Point Capability"))); |
209 | | - OFFLOAD_ERR( |
210 | | - (printDeviceValue<ol_device_fp_capability_flags_t, PrintKind::FP_FLAGS>( |
211 | | - S, D, OL_DEVICE_INFO_DOUBLE_FP_CONFIG, |
212 | | - "Double Precision Floating Point Capability"))); |
213 | | - OFFLOAD_ERR( |
214 | | - (printDeviceValue<ol_device_fp_capability_flags_t, PrintKind::FP_FLAGS>( |
215 | | - S, D, OL_DEVICE_INFO_HALF_FP_CONFIG, |
216 | | - "Half Precision Floating Point Capability"))); |
217 | | - OFFLOAD_ERR( |
218 | | - printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_CHAR, |
219 | | - "Native Vector Width For Char")); |
220 | | - OFFLOAD_ERR( |
221 | | - printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_SHORT, |
222 | | - "Native Vector Width For Short")); |
223 | | - OFFLOAD_ERR(printDeviceValue<uint32_t>(S, D, |
224 | | - OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_INT, |
225 | | - "Native Vector Width For Int")); |
226 | | - OFFLOAD_ERR( |
227 | | - printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_LONG, |
228 | | - "Native Vector Width For Long")); |
229 | | - OFFLOAD_ERR( |
230 | | - printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_FLOAT, |
231 | | - "Native Vector Width For Float")); |
232 | | - OFFLOAD_ERR(printDeviceValue<uint32_t>( |
233 | | - S, D, OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_DOUBLE, |
234 | | - "Native Vector Width For Double")); |
235 | | - OFFLOAD_ERR( |
236 | | - printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_HALF, |
237 | | - "Native Vector Width For Half")); |
238 | | - |
239 | | - return OL_SUCCESS; |
240 | | -} |
241 | | - |
242 | | -ol_result_t printRoot(std::ostream &S) { |
243 | | - OFFLOAD_ERR(olInit()); |
244 | | - S << "Liboffload Version: " << OL_VERSION_MAJOR << "." << OL_VERSION_MINOR |
245 | | - << "." << OL_VERSION_PATCH << "\n"; |
246 | | - |
247 | | - std::vector<ol_device_handle_t> Devices; |
248 | | - OFFLOAD_ERR(olIterateDevices( |
249 | | - [](ol_device_handle_t Device, void *UserData) { |
250 | | - reinterpret_cast<decltype(Devices) *>(UserData)->push_back(Device); |
251 | | - return true; |
252 | | - }, |
253 | | - &Devices)); |
254 | | - |
255 | | - S << "Num Devices: " << Devices.size() << "\n"; |
256 | | - |
257 | | - for (auto &D : Devices) { |
258 | | - S << "\n"; |
259 | | - OFFLOAD_ERR(printDevice(S, D)); |
260 | | - } |
261 | | - |
262 | | - OFFLOAD_ERR(olShutDown()); |
263 | | - return OL_SUCCESS; |
264 | | -} |
| 14 | +#include "omptarget.h" |
| 15 | +#include <cstdio> |
265 | 16 |
|
266 | 17 | int main(int argc, char **argv) { |
267 | | - auto Err = printRoot(std::cout); |
| 18 | + __tgt_bin_desc EmptyDesc = {0, nullptr, nullptr, nullptr}; |
| 19 | + __tgt_register_lib(&EmptyDesc); |
| 20 | + __tgt_init_all_rtls(); |
268 | 21 |
|
269 | | - if (Err) { |
270 | | - std::cerr << "[Liboffload error " << Err->Code << "]: " << Err->Details |
271 | | - << "\n"; |
272 | | - return 1; |
| 22 | + printf("Found %d devices:\n", omp_get_num_devices()); |
| 23 | + for (int Dev = 0; Dev < omp_get_num_devices(); Dev++) { |
| 24 | + printf(" Device %d:\n", Dev); |
| 25 | + if (!__tgt_print_device_info(Dev)) |
| 26 | + printf(" print_device_info not implemented\n"); |
| 27 | + printf("\n"); |
273 | 28 | } |
| 29 | + |
| 30 | + __tgt_unregister_lib(&EmptyDesc); |
274 | 31 | return 0; |
275 | 32 | } |
0 commit comments