Skip to content

Conversation

@RossBrunton
Copy link
Contributor

@RossBrunton RossBrunton commented Aug 27, 2025

This is a tool similar to urinfo that simply prints properties of all
devices. The old openMP version has been ported to liboffload.

@llvmbot
Copy link
Member

llvmbot commented Aug 27, 2025

@llvm/pr-subscribers-offload

Author: Ross Brunton (RossBrunton)

Changes

This is a tool similar to llvm-offload-device-info, urinfo, etc. that
simply prints properties of all devices. The difference between this
and llvm-offload-device-info is that this uses liboffload rather than
openmp.


Full diff: https://github.com/llvm/llvm-project/pull/155626.diff

3 Files Affected:

  • (modified) offload/tools/CMakeLists.txt (+1)
  • (added) offload/tools/liboffload-deviceinfo/CMakeLists.txt (+9)
  • (added) offload/tools/liboffload-deviceinfo/llvm-liboffload-device-info.cpp (+265)
diff --git a/offload/tools/CMakeLists.txt b/offload/tools/CMakeLists.txt
index 13772a4a675e5..860eed30905f4 100644
--- a/offload/tools/CMakeLists.txt
+++ b/offload/tools/CMakeLists.txt
@@ -14,3 +14,4 @@ endmacro()
 
 add_subdirectory(deviceinfo)
 add_subdirectory(kernelreplay)
+add_subdirectory(liboffload-deviceinfo)
diff --git a/offload/tools/liboffload-deviceinfo/CMakeLists.txt b/offload/tools/liboffload-deviceinfo/CMakeLists.txt
new file mode 100644
index 0000000000000..37ce65721ca0f
--- /dev/null
+++ b/offload/tools/liboffload-deviceinfo/CMakeLists.txt
@@ -0,0 +1,9 @@
+message(STATUS "Building the llvm-liboffload-device-info tool")
+
+add_openmp_tool(llvm-liboffload-device-info llvm-liboffload-device-info.cpp)
+
+llvm_update_compile_flags(llvm-liboffload-device-info)
+
+target_link_libraries(llvm-liboffload-device-info PRIVATE
+  LLVMOffload
+)
diff --git a/offload/tools/liboffload-deviceinfo/llvm-liboffload-device-info.cpp b/offload/tools/liboffload-deviceinfo/llvm-liboffload-device-info.cpp
new file mode 100644
index 0000000000000..93c67af0ecea6
--- /dev/null
+++ b/offload/tools/liboffload-deviceinfo/llvm-liboffload-device-info.cpp
@@ -0,0 +1,265 @@
+//===- llvm-liboffload-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.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a command line utility that, by using the new liboffload API, prints
+// all devices and properties
+//
+//===----------------------------------------------------------------------===//
+
+#include <OffloadAPI.h>
+#include <iostream>
+#include <vector>
+
+#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 << " }";
+}
+
+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 = "") {
+  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));
+  }
+  S << Units << "\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_NAME, &NameSize))
+  Name.resize(NameSize);
+  OFFLOAD_ERR(olGetDeviceInfo(D, OL_DEVICE_INFO_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<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_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));
+  }
+
+  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;
+}

@RossBrunton
Copy link
Contributor Author

Output on my system:

Liboffload Version: 0.0.1
Num Devices: 2

[gfx1100]
Platform Name: AMDGPU
Platform Vendor Name: Unknown platform vendor
Platform Version: v0.0.1
Platform Backend: AMDGPU
Type: GPU
Driver Version: 1.14
Max Work Group Size: 1024
Max Work Group Size Per Dimension: {x: 1024, y: 1024, z: 1024}
Vendor ID: 4130
Num Compute Units: 80
Max Clock Frequency: 1927MHz
Memory Clock Rate: 1124MHz
Address Bits: 64
Max Mem Allocation Size: 17163091968B
Global Mem Size: 17163091968B
Single Precision Floating Point Capability: 127 { CORRECTLY_ROUNDED_DIVIDE_SQRT ROUND_TO_NEAREST ROUND_TO_ZERO ROUND_TO_INF INF_NAN DENORM FMA }
Double Precision Floating Point Capability: 127 { CORRECTLY_ROUNDED_DIVIDE_SQRT ROUND_TO_NEAREST ROUND_TO_ZERO ROUND_TO_INF INF_NAN DENORM FMA }
Half Precision Floating Point Capability: 0 { }
Native Vector Width For Char: 1
Native Vector Width For Short: 1
Native Vector Width For Int: 1
Native Vector Width For Long: 1
Native Vector Width For Float: 1
Native Vector Width For Double: 1
Native Vector Width For Half: 0

[Virtual Host Device]
Platform Name: Host
Platform Vendor Name: Unknown platform vendor
Platform Version: v0.0.1
Platform Backend: HOST
Type: HOST
Driver Version: 22.0.0git
Max Work Group Size: 1
Max Work Group Size Per Dimension: {x: 1, y: 1, z: 1}
Vendor ID: 0
Num Compute Units: 1
Max Clock Frequency: 64MHz
Memory Clock Rate: 64MHz
Address Bits: 64
Max Mem Allocation Size: 0B
Global Mem Size: 0B
Single Precision Floating Point Capability: 127 { CORRECTLY_ROUNDED_DIVIDE_SQRT ROUND_TO_NEAREST ROUND_TO_ZERO ROUND_TO_INF INF_NAN DENORM FMA }
Double Precision Floating Point Capability: 127 { CORRECTLY_ROUNDED_DIVIDE_SQRT ROUND_TO_NEAREST ROUND_TO_ZERO ROUND_TO_INF INF_NAN DENORM FMA }
Half Precision Floating Point Capability: 0 { }
Native Vector Width For Char: 1
Native Vector Width For Short: 1
Native Vector Width For Int: 1
Native Vector Width For Long: 1
Native Vector Width For Float: 1
Native Vector Width For Double: 1
Native Vector Width For Half: 0

Copy link
Contributor

@jhuber6 jhuber6 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather this one replaces the old one, unless there's some feature it's missing.

@RossBrunton
Copy link
Contributor Author

@jhuber6 I think that makes sense, but llvm-offload-device-info prints out much more information than this does since a lot of properties haven't been mapped to liboffload device infos yet.

@shiltian
Copy link
Contributor

I would rather this one replaces the old one, unless there's some feature it's missing.

I don't think it's a good idea to have them co-exist. It'd be super confusing.

@RossBrunton RossBrunton marked this pull request as draft August 28, 2025 11:11
@RossBrunton RossBrunton changed the title [Offload] Add new llvm-liboffload-device-info tool [Offload] Port llvm-offload-device-info to new offload API Aug 28, 2025
@RossBrunton RossBrunton marked this pull request as ready for review August 29, 2025 12:11
Copy link
Contributor

@jhuber6 jhuber6 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, one fewer thing in offload tied to OpenMP.

This is a tool similar to llvm-offload-device-info, urinfo, etc. that
simply prints properties of all devices. The difference between this
and llvm-offload-device-info is that this uses liboffload rather than
openmp.
@RossBrunton RossBrunton merged commit 4e8b4d6 into llvm:main Sep 4, 2025
9 checks passed
@jplehr
Copy link
Contributor

jplehr commented Sep 4, 2025

This added a few more fails to the offload staging bot: https://lab.llvm.org/staging/#/builders/64/builds/11129

Can you please take a look at that? I'm trying to get the bot clean again to move it to production.

@jplehr
Copy link
Contributor

jplehr commented Sep 4, 2025

I opened #156872 which should fix it.

@RossBrunton
Copy link
Contributor Author

@jplehr Ah, sorry about that. Thanks for fixing it.

searlmc1 pushed a commit to ROCm/llvm-project that referenced this pull request Sep 4, 2025
searlmc1 pushed a commit to ROCm/llvm-project that referenced this pull request Sep 18, 2025
…lvm#155626)"

breaks offload build, needs prior patches

This reverts commit 4e8b4d6.
searlmc1 pushed a commit to ROCm/llvm-project that referenced this pull request Oct 3, 2025
This is a tool similar to urinfo that simply prints properties of all
devices. The old openMP version has been ported to liboffload.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants