diff options
Diffstat (limited to 'offload/tools/deviceinfo/llvm-offload-device-info.cpp')
| -rw-r--r-- | offload/tools/deviceinfo/llvm-offload-device-info.cpp | 275 |
1 files changed, 259 insertions, 16 deletions
diff --git a/offload/tools/deviceinfo/llvm-offload-device-info.cpp b/offload/tools/deviceinfo/llvm-offload-device-info.cpp index 2228fbf3ec17..a2955d49d396 100644 --- a/offload/tools/deviceinfo/llvm-offload-device-info.cpp +++ b/offload/tools/deviceinfo/llvm-offload-device-info.cpp @@ -1,4 +1,4 @@ -//===- llvm-offload-device-info.cpp - Device info as seen by LLVM/Offload -===// +//===- llvm-offload-device-info.cpp - Print liboffload properties ---------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,27 +6,270 @@ // //===----------------------------------------------------------------------===// // -// This is a command line utility that, by using LLVM/Offload, and the device -// plugins, list devices information as seen by the runtime. +// This is a command line utility that, by using the new liboffload API, prints +// all devices and properties // //===----------------------------------------------------------------------===// -#include "omptarget.h" -#include <cstdio> +#include <OffloadAPI.h> +#include <iostream> +#include <vector> -int main(int argc, char **argv) { - __tgt_bin_desc EmptyDesc = {0, nullptr, nullptr, nullptr}; - __tgt_register_lib(&EmptyDesc); - __tgt_init_all_rtls(); +#define OFFLOAD_ERR(X) \ + if (auto Err = X) { \ + return Err; \ + } + +enum class PrintKind { + NORMAL, + FP_FLAGS, +}; + +template <typename T, PrintKind PK = PrintKind::NORMAL> +void doWrite(std::ostream &S, T &&Val) { + S << Val; +} + +template <> +void doWrite<ol_platform_backend_t>(std::ostream &S, + ol_platform_backend_t &&Val) { + switch (Val) { + case OL_PLATFORM_BACKEND_UNKNOWN: + S << "UNKNOWN"; + break; + case OL_PLATFORM_BACKEND_CUDA: + S << "CUDA"; + break; + case OL_PLATFORM_BACKEND_AMDGPU: + S << "AMDGPU"; + break; + case OL_PLATFORM_BACKEND_HOST: + S << "HOST"; + break; + default: + S << "<< INVALID >>"; + break; + } +} +template <> +void doWrite<ol_device_type_t>(std::ostream &S, ol_device_type_t &&Val) { + switch (Val) { + case OL_DEVICE_TYPE_GPU: + S << "GPU"; + break; + case OL_DEVICE_TYPE_CPU: + S << "CPU"; + break; + case OL_DEVICE_TYPE_HOST: + S << "HOST"; + break; + default: + S << "<< INVALID >>"; + break; + } +} +template <> +void doWrite<ol_dimensions_t>(std::ostream &S, ol_dimensions_t &&Val) { + S << "{x: " << Val.x << ", y: " << Val.y << ", z: " << Val.z << "}"; +} +template <> +void doWrite<ol_device_fp_capability_flags_t, PrintKind::FP_FLAGS>( + std::ostream &S, ol_device_fp_capability_flags_t &&Val) { + S << Val << " {"; + + if (Val & OL_DEVICE_FP_CAPABILITY_FLAG_CORRECTLY_ROUNDED_DIVIDE_SQRT) { + S << " CORRECTLY_ROUNDED_DIVIDE_SQRT"; + } + if (Val & OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_NEAREST) { + S << " ROUND_TO_NEAREST"; + } + if (Val & OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_ZERO) { + S << " ROUND_TO_ZERO"; + } + if (Val & OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_INF) { + S << " ROUND_TO_INF"; + } + if (Val & OL_DEVICE_FP_CAPABILITY_FLAG_INF_NAN) { + S << " INF_NAN"; + } + if (Val & OL_DEVICE_FP_CAPABILITY_FLAG_DENORM) { + S << " DENORM"; + } + if (Val & OL_DEVICE_FP_CAPABILITY_FLAG_FMA) { + S << " FMA"; + } + if (Val & OL_DEVICE_FP_CAPABILITY_FLAG_SOFT_FLOAT) { + S << " SOFT_FLOAT"; + } + + S << " }"; +} - printf("Found %d devices:\n", omp_get_num_devices()); - for (int Dev = 0; Dev < omp_get_num_devices(); Dev++) { - printf(" Device %d:\n", Dev); - if (!__tgt_print_device_info(Dev)) - printf(" print_device_info not implemented\n"); - printf("\n"); +template <typename T> +ol_result_t printPlatformValue(std::ostream &S, ol_platform_handle_t Plat, + ol_platform_info_t Info, const char *Desc) { + S << Desc << ": "; + + if constexpr (std::is_pointer_v<T>) { + std::vector<uint8_t> Val; + size_t Size; + OFFLOAD_ERR(olGetPlatformInfoSize(Plat, Info, &Size)); + Val.resize(Size); + OFFLOAD_ERR(olGetPlatformInfo(Plat, Info, sizeof(Val), Val.data())); + doWrite(S, reinterpret_cast<T>(Val.data())); + } else { + T Val; + OFFLOAD_ERR(olGetPlatformInfo(Plat, Info, sizeof(Val), &Val)); + doWrite(S, std::move(Val)); + } + S << "\n"; + return OL_SUCCESS; +} + +template <typename T, PrintKind PK = PrintKind::NORMAL> +ol_result_t printDeviceValue(std::ostream &S, ol_device_handle_t Dev, + ol_device_info_t Info, const char *Desc, + const char *Units = nullptr) { + S << Desc << ": "; + + if constexpr (std::is_pointer_v<T>) { + std::vector<uint8_t> Val; + size_t Size; + OFFLOAD_ERR(olGetDeviceInfoSize(Dev, Info, &Size)); + Val.resize(Size); + OFFLOAD_ERR(olGetDeviceInfo(Dev, Info, sizeof(Val), Val.data())); + doWrite<T, PK>(S, reinterpret_cast<T>(Val.data())); + } else { + T Val; + OFFLOAD_ERR(olGetDeviceInfo(Dev, Info, sizeof(Val), &Val)); + doWrite<T, PK>(S, std::move(Val)); + } + if (Units) + S << " " << Units; + S << "\n"; + return OL_SUCCESS; +} + +ol_result_t printDevice(std::ostream &S, ol_device_handle_t D) { + ol_platform_handle_t Platform; + OFFLOAD_ERR( + olGetDeviceInfo(D, OL_DEVICE_INFO_PLATFORM, sizeof(Platform), &Platform)); + + std::vector<char> Name; + size_t NameSize; + OFFLOAD_ERR(olGetDeviceInfoSize(D, OL_DEVICE_INFO_PRODUCT_NAME, &NameSize)) + Name.resize(NameSize); + OFFLOAD_ERR( + olGetDeviceInfo(D, OL_DEVICE_INFO_PRODUCT_NAME, NameSize, Name.data())); + S << "[" << Name.data() << "]\n"; + + OFFLOAD_ERR(printPlatformValue<const char *>( + S, Platform, OL_PLATFORM_INFO_NAME, "Platform Name")); + OFFLOAD_ERR(printPlatformValue<const char *>( + S, Platform, OL_PLATFORM_INFO_VENDOR_NAME, "Platform Vendor Name")); + OFFLOAD_ERR(printPlatformValue<const char *>( + S, Platform, OL_PLATFORM_INFO_VERSION, "Platform Version")); + OFFLOAD_ERR(printPlatformValue<ol_platform_backend_t>( + S, Platform, OL_PLATFORM_INFO_BACKEND, "Platform Backend")); + + OFFLOAD_ERR( + printDeviceValue<const char *>(S, D, OL_DEVICE_INFO_NAME, "Name")); + OFFLOAD_ERR( + printDeviceValue<ol_device_type_t>(S, D, OL_DEVICE_INFO_TYPE, "Type")); + OFFLOAD_ERR(printDeviceValue<const char *>( + S, D, OL_DEVICE_INFO_DRIVER_VERSION, "Driver Version")); + OFFLOAD_ERR(printDeviceValue<uint32_t>( + S, D, OL_DEVICE_INFO_MAX_WORK_GROUP_SIZE, "Max Work Group Size")); + OFFLOAD_ERR(printDeviceValue<ol_dimensions_t>( + S, D, OL_DEVICE_INFO_MAX_WORK_GROUP_SIZE_PER_DIMENSION, + "Max Work Group Size Per Dimension")); + OFFLOAD_ERR(printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_MAX_WORK_SIZE, + "Max Work Size")); + OFFLOAD_ERR(printDeviceValue<ol_dimensions_t>( + S, D, OL_DEVICE_INFO_MAX_WORK_SIZE_PER_DIMENSION, + "Max Work Size Per Dimension")); + OFFLOAD_ERR( + printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_VENDOR_ID, "Vendor ID")); + OFFLOAD_ERR(printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_NUM_COMPUTE_UNITS, + "Num Compute Units")); + OFFLOAD_ERR(printDeviceValue<uint32_t>( + S, D, OL_DEVICE_INFO_MAX_CLOCK_FREQUENCY, "Max Clock Frequency", "MHz")); + OFFLOAD_ERR(printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_MEMORY_CLOCK_RATE, + "Memory Clock Rate", "MHz")); + OFFLOAD_ERR(printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_ADDRESS_BITS, + "Address Bits")); + OFFLOAD_ERR(printDeviceValue<uint64_t>( + S, D, OL_DEVICE_INFO_MAX_MEM_ALLOC_SIZE, "Max Mem Allocation Size", "B")); + OFFLOAD_ERR(printDeviceValue<uint64_t>(S, D, OL_DEVICE_INFO_GLOBAL_MEM_SIZE, + "Global Mem Size", "B")); + OFFLOAD_ERR( + (printDeviceValue<ol_device_fp_capability_flags_t, PrintKind::FP_FLAGS>( + S, D, OL_DEVICE_INFO_SINGLE_FP_CONFIG, + "Single Precision Floating Point Capability"))); + OFFLOAD_ERR( + (printDeviceValue<ol_device_fp_capability_flags_t, PrintKind::FP_FLAGS>( + S, D, OL_DEVICE_INFO_DOUBLE_FP_CONFIG, + "Double Precision Floating Point Capability"))); + OFFLOAD_ERR( + (printDeviceValue<ol_device_fp_capability_flags_t, PrintKind::FP_FLAGS>( + S, D, OL_DEVICE_INFO_HALF_FP_CONFIG, + "Half Precision Floating Point Capability"))); + OFFLOAD_ERR( + printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_CHAR, + "Native Vector Width For Char")); + OFFLOAD_ERR( + printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_SHORT, + "Native Vector Width For Short")); + OFFLOAD_ERR(printDeviceValue<uint32_t>(S, D, + OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_INT, + "Native Vector Width For Int")); + OFFLOAD_ERR( + printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_LONG, + "Native Vector Width For Long")); + OFFLOAD_ERR( + printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_FLOAT, + "Native Vector Width For Float")); + OFFLOAD_ERR(printDeviceValue<uint32_t>( + S, D, OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_DOUBLE, + "Native Vector Width For Double")); + OFFLOAD_ERR( + printDeviceValue<uint32_t>(S, D, OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_HALF, + "Native Vector Width For Half")); + + return OL_SUCCESS; +} + +ol_result_t printRoot(std::ostream &S) { + OFFLOAD_ERR(olInit()); + S << "Liboffload Version: " << OL_VERSION_MAJOR << "." << OL_VERSION_MINOR + << "." << OL_VERSION_PATCH << "\n"; + + std::vector<ol_device_handle_t> Devices; + OFFLOAD_ERR(olIterateDevices( + [](ol_device_handle_t Device, void *UserData) { + reinterpret_cast<decltype(Devices) *>(UserData)->push_back(Device); + return true; + }, + &Devices)); + + S << "Num Devices: " << Devices.size() << "\n"; + + for (auto &D : Devices) { + S << "\n"; + OFFLOAD_ERR(printDevice(S, D)); } - __tgt_unregister_lib(&EmptyDesc); + OFFLOAD_ERR(olShutDown()); + return OL_SUCCESS; +} + +int main(int argc, char **argv) { + auto Err = printRoot(std::cout); + + if (Err) { + std::cerr << "[Liboffload error " << Err->Code << "]: " << Err->Details + << "\n"; + return 1; + } return 0; } |
