[Openmp-commits] [openmp] [WIP] [OpenMP] Add unit tests for nextgen plugins (PR #74398)

Ethan Luis McDonough via Openmp-commits openmp-commits at lists.llvm.org
Mon Dec 4 17:23:30 PST 2023


https://github.com/EthanLuisMcDonough created https://github.com/llvm/llvm-project/pull/74398

This patch add three GTest unit tests that test plugin read and write operations. Tests can be compiled with `ninja -C runtimes/runtimes-bins LibomptUnitTests`.

>From 2bb2d4b8906539462dd5885aa31c636ee1382118 Mon Sep 17 00:00:00 2001
From: Ethan Luis McDonough <ethanluismcdonough at gmail.com>
Date: Sat, 2 Dec 2023 02:23:04 -0600
Subject: [PATCH 1/2] Add unit testing to libomptarget

---
 openmp/libomptarget/CMakeLists.txt            |  6 +++++
 openmp/libomptarget/unittests/CMakeLists.txt  |  8 +++++++
 .../unittests/Plugins/CMakeLists.txt          | 23 +++++++++++++++++++
 .../unittests/Plugins/NextgenPluginsTest.cpp  |  9 ++++++++
 4 files changed, 46 insertions(+)
 create mode 100644 openmp/libomptarget/unittests/CMakeLists.txt
 create mode 100644 openmp/libomptarget/unittests/Plugins/CMakeLists.txt
 create mode 100644 openmp/libomptarget/unittests/Plugins/NextgenPluginsTest.cpp

diff --git a/openmp/libomptarget/CMakeLists.txt b/openmp/libomptarget/CMakeLists.txt
index 5f592f46c8ffa..ab56156cbf5b3 100644
--- a/openmp/libomptarget/CMakeLists.txt
+++ b/openmp/libomptarget/CMakeLists.txt
@@ -123,3 +123,9 @@ add_subdirectory(tools)
 
 # Add tests.
 add_subdirectory(test)
+
+# Add unit tests if GMock/GTest is present
+if (EXISTS ${CMAKE_CURRENT_BINARY_DIR}/third-party/unittest AND EXISTS ${LLVM_THIRD_PARTY_DIR}/unittest)
+  add_subdirectory(${LLVM_THIRD_PARTY_DIR}/unittest ${CMAKE_CURRENT_BINARY_DIR}/third-party/unittest)
+  add_subdirectory(unittests)
+endif()
diff --git a/openmp/libomptarget/unittests/CMakeLists.txt b/openmp/libomptarget/unittests/CMakeLists.txt
new file mode 100644
index 0000000000000..0a29afd68569a
--- /dev/null
+++ b/openmp/libomptarget/unittests/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_custom_target(LibomptUnitTests)
+set_target_properties(LibomptUnitTests PROPERTIES FOLDER "Libomptarget tests")
+
+function(add_libompt_unittest test_dirname)
+  add_unittest(LibomptUnitTests ${test_dirname} ${ARGN})
+endfunction()
+
+add_subdirectory(Plugins)
diff --git a/openmp/libomptarget/unittests/Plugins/CMakeLists.txt b/openmp/libomptarget/unittests/Plugins/CMakeLists.txt
new file mode 100644
index 0000000000000..a755506574c1d
--- /dev/null
+++ b/openmp/libomptarget/unittests/Plugins/CMakeLists.txt
@@ -0,0 +1,23 @@
+set(LIBOMPTARGET_BUILD_AMDGPU_PLUGIN TRUE CACHE BOOL
+  "Whether to build AMDGPU plugin")
+set(LIBOMPTARGET_BUILD_CUDA_PLUGIN TRUE CACHE BOOL
+  "Whether to build CUDA plugin")
+
+set(PLUGINS_TEST_COMMON omptarget OMPT omptarget.devicertl)
+set(PLUGINS_TEST_SOURCES NextgenPluginsTest.cpp)
+
+if (LIBOMPTARGET_BUILD_AMDGPU_PLUGIN)
+  libomptarget_say("Building plugin unit tests for AMDGPU")
+  add_libompt_unittest(PluginsTestAmd ${PLUGINS_TEST_SOURCES})
+  add_dependencies(PluginsTestAmd ${PLUGINS_TEST_COMMON} omptarget.rtl.amdgpu)
+  target_link_libraries(PluginsTestAmd PRIVATE ${PLUGINS_TEST_COMMON} omptarget.rtl.amdgpu)
+  target_include_directories(PluginsTestAmd PRIVATE ${LIBOMPTARGET_INCLUDE_DIR})
+endif()
+
+if (LIBOMPTARGET_BUILD_CUDA_PLUGIN)
+  libomptarget_say("Building plugin unit tests for Cuda")
+  add_libompt_unittest(PluginsTestCu ${PLUGINS_TEST_SOURCES})
+  add_dependencies(PluginsTestCu ${PLUGINS_TEST_COMMON} omptarget.rtl.cuda)
+  target_link_libraries(PluginsTestCu PRIVATE ${PLUGINS_TEST_COMMON} omptarget.rtl.cuda)
+  target_include_directories(PluginsTestCu PRIVATE ${LIBOMPTARGET_INCLUDE_DIR})
+endif()
diff --git a/openmp/libomptarget/unittests/Plugins/NextgenPluginsTest.cpp b/openmp/libomptarget/unittests/Plugins/NextgenPluginsTest.cpp
new file mode 100644
index 0000000000000..d60ead6d3e945
--- /dev/null
+++ b/openmp/libomptarget/unittests/Plugins/NextgenPluginsTest.cpp
@@ -0,0 +1,9 @@
+#include "Shared/PluginAPI.h"
+#include "omptarget.h"
+#include "gtest/gtest.h"
+
+namespace {
+TEST(NextgenPluginsTest, PluginInit) {
+  EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_init_plugin());
+}
+} // namespace

>From 148f8c9296c235f56dae712edd70564134ea184e Mon Sep 17 00:00:00 2001
From: Ethan Luis McDonough <ethanluismcdonough at gmail.com>
Date: Mon, 4 Dec 2023 19:18:37 -0600
Subject: [PATCH 2/2] Add tests

---
 openmp/libomptarget/CMakeLists.txt            |   2 +-
 .../unittests/Plugins/CMakeLists.txt          |   7 +-
 .../unittests/Plugins/NextgenPluginsTest.cpp  | 143 +++++++++++++++++-
 3 files changed, 146 insertions(+), 6 deletions(-)

diff --git a/openmp/libomptarget/CMakeLists.txt b/openmp/libomptarget/CMakeLists.txt
index ab56156cbf5b3..6a474469ab87a 100644
--- a/openmp/libomptarget/CMakeLists.txt
+++ b/openmp/libomptarget/CMakeLists.txt
@@ -125,7 +125,7 @@ add_subdirectory(tools)
 add_subdirectory(test)
 
 # Add unit tests if GMock/GTest is present
-if (EXISTS ${CMAKE_CURRENT_BINARY_DIR}/third-party/unittest AND EXISTS ${LLVM_THIRD_PARTY_DIR}/unittest)
+if (EXISTS ${LLVM_THIRD_PARTY_DIR}/unittest)
   add_subdirectory(${LLVM_THIRD_PARTY_DIR}/unittest ${CMAKE_CURRENT_BINARY_DIR}/third-party/unittest)
   add_subdirectory(unittests)
 endif()
diff --git a/openmp/libomptarget/unittests/Plugins/CMakeLists.txt b/openmp/libomptarget/unittests/Plugins/CMakeLists.txt
index a755506574c1d..234ba699c4834 100644
--- a/openmp/libomptarget/unittests/Plugins/CMakeLists.txt
+++ b/openmp/libomptarget/unittests/Plugins/CMakeLists.txt
@@ -5,13 +5,16 @@ set(LIBOMPTARGET_BUILD_CUDA_PLUGIN TRUE CACHE BOOL
 
 set(PLUGINS_TEST_COMMON omptarget OMPT omptarget.devicertl)
 set(PLUGINS_TEST_SOURCES NextgenPluginsTest.cpp)
+set(PLUGINS_TEST_INCLUDE ${LIBOMPTARGET_INCLUDE_DIR})
 
 if (LIBOMPTARGET_BUILD_AMDGPU_PLUGIN)
   libomptarget_say("Building plugin unit tests for AMDGPU")
   add_libompt_unittest(PluginsTestAmd ${PLUGINS_TEST_SOURCES})
   add_dependencies(PluginsTestAmd ${PLUGINS_TEST_COMMON} omptarget.rtl.amdgpu)
   target_link_libraries(PluginsTestAmd PRIVATE ${PLUGINS_TEST_COMMON} omptarget.rtl.amdgpu)
-  target_include_directories(PluginsTestAmd PRIVATE ${LIBOMPTARGET_INCLUDE_DIR})
+  target_include_directories(PluginsTestAmd PRIVATE ${PLUGINS_TEST_INCLUDE})
+else()
+  libomptarget_say("Skipping AMDGPU plugin unit tests")
 endif()
 
 if (LIBOMPTARGET_BUILD_CUDA_PLUGIN)
@@ -19,5 +22,5 @@ if (LIBOMPTARGET_BUILD_CUDA_PLUGIN)
   add_libompt_unittest(PluginsTestCu ${PLUGINS_TEST_SOURCES})
   add_dependencies(PluginsTestCu ${PLUGINS_TEST_COMMON} omptarget.rtl.cuda)
   target_link_libraries(PluginsTestCu PRIVATE ${PLUGINS_TEST_COMMON} omptarget.rtl.cuda)
-  target_include_directories(PluginsTestCu PRIVATE ${LIBOMPTARGET_INCLUDE_DIR})
+  target_include_directories(PluginsTestCu PRIVATE ${PLUGINS_TEST_INCLUDE})
 endif()
diff --git a/openmp/libomptarget/unittests/Plugins/NextgenPluginsTest.cpp b/openmp/libomptarget/unittests/Plugins/NextgenPluginsTest.cpp
index d60ead6d3e945..24311076e8acd 100644
--- a/openmp/libomptarget/unittests/Plugins/NextgenPluginsTest.cpp
+++ b/openmp/libomptarget/unittests/Plugins/NextgenPluginsTest.cpp
@@ -2,8 +2,145 @@
 #include "omptarget.h"
 #include "gtest/gtest.h"
 
-namespace {
+const int DEVICE_ID = 0, DEVICE_TWO = 1;
+bool setup_map[DEVICE_TWO + 1];
+
+int init_test_device(int ID) {
+  if (setup_map[ID]) {
+    return OFFLOAD_SUCCESS;
+  }
+  if (__tgt_rtl_init_plugin() == OFFLOAD_FAIL ||
+      __tgt_rtl_init_device(ID) == OFFLOAD_FAIL) {
+    return OFFLOAD_FAIL;
+  }
+  setup_map[ID] = true;
+  return OFFLOAD_SUCCESS;
+}
+
+// Test plugin initialization
 TEST(NextgenPluginsTest, PluginInit) {
-  EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_init_plugin());
+  EXPECT_EQ(OFFLOAD_SUCCESS, init_test_device(DEVICE_ID));
+}
+
+// Test GPU allocation and R/W
+TEST(NextgenPluginsTest, PluginAlloc) {
+  int32_t test_value = 23;
+  int32_t host_value = -1;
+  int64_t var_size = sizeof(int32_t);
+
+  // Init plugin and device
+  EXPECT_EQ(OFFLOAD_SUCCESS, init_test_device(DEVICE_ID));
+
+  // Allocate memory
+  void *device_ptr =
+      __tgt_rtl_data_alloc(DEVICE_ID, var_size, nullptr, TARGET_ALLOC_DEFAULT);
+
+  // Check that the result is not null
+  EXPECT_NE(device_ptr, nullptr);
+
+  // Submit data to device
+  EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_submit(DEVICE_ID, device_ptr,
+                                                   &test_value, var_size));
+
+  // Read data from device
+  EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_retrieve(DEVICE_ID, &host_value,
+                                                     device_ptr, var_size));
+
+  // Compare values
+  EXPECT_EQ(host_value, test_value);
+
+  // Cleanup data
+  EXPECT_EQ(OFFLOAD_SUCCESS,
+            __tgt_rtl_data_delete(DEVICE_ID, device_ptr, TARGET_ALLOC_DEFAULT));
+}
+
+// Test async GPU allocation and R/W
+TEST(NextgenPluginsTest, PluginAsyncAlloc) {
+  int32_t test_value = 47;
+  int32_t host_value = -1;
+  int64_t var_size = sizeof(int32_t);
+  __tgt_async_info info;
+
+  // Init plugin and device
+  EXPECT_EQ(OFFLOAD_SUCCESS, init_test_device(DEVICE_ID));
+
+  // Allocate memory
+  void *device_ptr =
+      __tgt_rtl_data_alloc(DEVICE_ID, var_size, nullptr, TARGET_ALLOC_DEFAULT);
+
+  // Check that the result is not null
+  EXPECT_NE(device_ptr, nullptr);
+
+  // Submit data to device asynchronously
+  EXPECT_EQ(OFFLOAD_SUCCESS,
+            __tgt_rtl_data_submit_async(DEVICE_ID, device_ptr, &test_value,
+                                        var_size, &info));
+
+  // Wait for async request to process
+  EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_synchronize(DEVICE_ID, &info));
+
+  // Read data from device
+  EXPECT_EQ(OFFLOAD_SUCCESS,
+            __tgt_rtl_data_retrieve_async(DEVICE_ID, &host_value, device_ptr,
+                                          var_size, &info));
+
+  // Wait for async request to process
+  EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_synchronize(DEVICE_ID, &info));
+
+  // Compare values
+  EXPECT_EQ(host_value, test_value);
+
+  // Cleanup data
+  EXPECT_EQ(OFFLOAD_SUCCESS,
+            __tgt_rtl_data_delete(DEVICE_ID, device_ptr, TARGET_ALLOC_DEFAULT));
+}
+
+// Test GPU data exchange
+TEST(NextgenPluginsTest, PluginDataSwap) {
+  int32_t test_value = 23;
+  int32_t host_value = -1;
+  int64_t var_size = sizeof(int32_t);
+
+  // Only run test if we have multiple GPUs to test
+  // GPUs must be compatible for test to work
+  if (__tgt_rtl_number_of_devices() > 1 &&
+      __tgt_rtl_is_data_exchangable(DEVICE_ID, DEVICE_TWO)) {
+    // Init both GPUs
+    EXPECT_EQ(OFFLOAD_SUCCESS, init_test_device(DEVICE_ID));
+    EXPECT_EQ(OFFLOAD_SUCCESS, init_test_device(DEVICE_TWO));
+
+    // Allocate memory on both GPUs
+    // DEVICE_ID will be the source
+    // DEVICE_TWO will be the destination
+    void *source_ptr = __tgt_rtl_data_alloc(DEVICE_ID, var_size, nullptr,
+                                            TARGET_ALLOC_DEFAULT);
+    void *dest_ptr = __tgt_rtl_data_alloc(DEVICE_TWO, var_size, nullptr,
+                                          TARGET_ALLOC_DEFAULT);
+
+    // Check for success in allocation
+    EXPECT_NE(source_ptr, nullptr);
+    EXPECT_NE(dest_ptr, nullptr);
+
+    // Write data to source
+    EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_submit(DEVICE_ID, source_ptr,
+                                                     &test_value, var_size));
+
+    // Transfer data between devices
+    EXPECT_EQ(OFFLOAD_SUCCESS,
+              __tgt_rtl_data_exchange(DEVICE_ID, source_ptr, DEVICE_TWO,
+                                      dest_ptr, var_size));
+
+    // Read from destination device (DEVICE_TWO) memory
+    EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_retrieve(DEVICE_TWO, &host_value,
+                                                       dest_ptr, var_size));
+
+    // Ensure match
+    EXPECT_EQ(host_value, test_value);
+
+    // Cleanup
+    EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_delete(DEVICE_ID, source_ptr,
+                                                     TARGET_ALLOC_DEFAULT));
+    EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_delete(DEVICE_TWO, dest_ptr,
+                                                     TARGET_ALLOC_DEFAULT));
+  }
 }
-} // namespace



More information about the Openmp-commits mailing list