282 lines · cpp
1//===- llvm-offload-device-info.cpp - Print liboffload properties ---------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This is a command line utility that, by using the new liboffload API, prints10// all devices and properties11//12//===----------------------------------------------------------------------===//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 23enum class PrintKind {24 NORMAL,25 FP_FLAGS,26};27 28template <typename T, PrintKind PK = PrintKind::NORMAL>29void doWrite(std::ostream &S, T &&Val) {30 S << Val;31}32 33template <>34void 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}54template <>55void 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}71template <>72void doWrite<ol_dimensions_t>(std::ostream &S, ol_dimensions_t &&Val) {73 S << "{x: " << Val.x << ", y: " << Val.y << ", z: " << Val.z << "}";74}75template <>76void 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 108template <typename T>109ol_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 129template <typename T, PrintKind PK = PrintKind::NORMAL>130ol_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, Size, 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 153ol_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(printDeviceValue<const char *>(S, D, OL_DEVICE_INFO_PRODUCT_NAME,178 "Product Name"));179 OFFLOAD_ERR(printDeviceValue<const char *>(S, D, OL_DEVICE_INFO_UID, "UID"));180 OFFLOAD_ERR(181 printDeviceValue<ol_device_type_t>(S, D, OL_DEVICE_INFO_TYPE, "Type"));182 OFFLOAD_ERR(printDeviceValue<const char *>(183 S, D, OL_DEVICE_INFO_DRIVER_VERSION, "Driver Version"));184 OFFLOAD_ERR(printDeviceValue<uint32_t>(185 S, D, OL_DEVICE_INFO_MAX_WORK_GROUP_SIZE, "Max Work Group Size"));186 OFFLOAD_ERR(printDeviceValue<ol_dimensions_t>(187 S, D, OL_DEVICE_INFO_MAX_WORK_GROUP_SIZE_PER_DIMENSION,188 "Max Work Group Size Per Dimension"));189 OFFLOAD_ERR(printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_MAX_WORK_SIZE,190 "Max Work Size"));191 OFFLOAD_ERR(printDeviceValue<ol_dimensions_t>(192 S, D, OL_DEVICE_INFO_MAX_WORK_SIZE_PER_DIMENSION,193 "Max Work Size Per Dimension"));194 OFFLOAD_ERR(195 printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_VENDOR_ID, "Vendor ID"));196 OFFLOAD_ERR(printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_NUM_COMPUTE_UNITS,197 "Num Compute Units"));198 OFFLOAD_ERR(printDeviceValue<uint32_t>(199 S, D, OL_DEVICE_INFO_MAX_CLOCK_FREQUENCY, "Max Clock Frequency", "MHz"));200 OFFLOAD_ERR(printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_MEMORY_CLOCK_RATE,201 "Memory Clock Rate", "MHz"));202 OFFLOAD_ERR(printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_ADDRESS_BITS,203 "Address Bits"));204 OFFLOAD_ERR(printDeviceValue<uint64_t>(205 S, D, OL_DEVICE_INFO_MAX_MEM_ALLOC_SIZE, "Max Mem Allocation Size", "B"));206 OFFLOAD_ERR(printDeviceValue<uint64_t>(S, D, OL_DEVICE_INFO_GLOBAL_MEM_SIZE,207 "Global Mem Size", "B"));208 OFFLOAD_ERR(209 printDeviceValue<uint64_t>(S, D, OL_DEVICE_INFO_WORK_GROUP_LOCAL_MEM_SIZE,210 "Work Group Shared Mem Size", "B"));211 OFFLOAD_ERR(212 (printDeviceValue<ol_device_fp_capability_flags_t, PrintKind::FP_FLAGS>(213 S, D, OL_DEVICE_INFO_SINGLE_FP_CONFIG,214 "Single Precision Floating Point Capability")));215 OFFLOAD_ERR(216 (printDeviceValue<ol_device_fp_capability_flags_t, PrintKind::FP_FLAGS>(217 S, D, OL_DEVICE_INFO_DOUBLE_FP_CONFIG,218 "Double Precision Floating Point Capability")));219 OFFLOAD_ERR(220 (printDeviceValue<ol_device_fp_capability_flags_t, PrintKind::FP_FLAGS>(221 S, D, OL_DEVICE_INFO_HALF_FP_CONFIG,222 "Half Precision Floating Point Capability")));223 OFFLOAD_ERR(224 printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_CHAR,225 "Native Vector Width For Char"));226 OFFLOAD_ERR(227 printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_SHORT,228 "Native Vector Width For Short"));229 OFFLOAD_ERR(printDeviceValue<uint32_t>(S, D,230 OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_INT,231 "Native Vector Width For Int"));232 OFFLOAD_ERR(233 printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_LONG,234 "Native Vector Width For Long"));235 OFFLOAD_ERR(236 printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_FLOAT,237 "Native Vector Width For Float"));238 OFFLOAD_ERR(printDeviceValue<uint32_t>(239 S, D, OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_DOUBLE,240 "Native Vector Width For Double"));241 OFFLOAD_ERR(242 printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_HALF,243 "Native Vector Width For Half"));244 245 return OL_SUCCESS;246}247 248ol_result_t printRoot(std::ostream &S) {249 OFFLOAD_ERR(olInit());250 S << "Liboffload Version: " << OL_VERSION_MAJOR << "." << OL_VERSION_MINOR251 << "." << OL_VERSION_PATCH << "\n";252 253 std::vector<ol_device_handle_t> Devices;254 OFFLOAD_ERR(olIterateDevices(255 [](ol_device_handle_t Device, void *UserData) {256 reinterpret_cast<decltype(Devices) *>(UserData)->push_back(Device);257 return true;258 },259 &Devices));260 261 S << "Num Devices: " << Devices.size() << "\n";262 263 for (auto &D : Devices) {264 S << "\n";265 OFFLOAD_ERR(printDevice(S, D));266 }267 268 OFFLOAD_ERR(olShutDown());269 return OL_SUCCESS;270}271 272int main(int argc, char **argv) {273 auto Err = printRoot(std::cout);274 275 if (Err) {276 std::cerr << "[Liboffload error " << Err->Code << "]: " << Err->Details277 << "\n";278 return 1;279 }280 return 0;281}282