1 | //===------- unittests/Plugins/NextgenPluginsTest.cpp - Plugin tests ------===// |
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-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "Shared/PluginAPI.h" |
10 | #include "omptarget.h" |
11 | #include "gtest/gtest.h" |
12 | |
13 | #include <unordered_set> |
14 | |
15 | const int DEVICE_ID = 0; |
16 | std::unordered_set<int> setup_map; |
17 | |
18 | int init_test_device(int ID) { |
19 | if (setup_map.find(x: ID) != setup_map.end()) { |
20 | return OFFLOAD_SUCCESS; |
21 | } |
22 | if (__tgt_rtl_init_plugin() == OFFLOAD_FAIL || |
23 | __tgt_rtl_init_device(ID) == OFFLOAD_FAIL) { |
24 | return OFFLOAD_FAIL; |
25 | } |
26 | setup_map.insert(x: ID); |
27 | return OFFLOAD_SUCCESS; |
28 | } |
29 | |
30 | // Test plugin initialization |
31 | TEST(NextgenPluginsTest, PluginInit) { |
32 | EXPECT_EQ(OFFLOAD_SUCCESS, init_test_device(ID: DEVICE_ID)); |
33 | } |
34 | |
35 | // Test GPU allocation and R/W |
36 | TEST(NextgenPluginsTest, PluginAlloc) { |
37 | int32_t test_value = 23; |
38 | int32_t host_value = -1; |
39 | int64_t var_size = sizeof(int32_t); |
40 | |
41 | // Init plugin and device |
42 | EXPECT_EQ(OFFLOAD_SUCCESS, init_test_device(ID: DEVICE_ID)); |
43 | |
44 | // Allocate memory |
45 | void *device_ptr = |
46 | __tgt_rtl_data_alloc(DEVICE_ID, var_size, nullptr, TARGET_ALLOC_DEFAULT); |
47 | |
48 | // Check that the result is not null |
49 | EXPECT_NE(device_ptr, nullptr); |
50 | |
51 | // Submit data to device |
52 | EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_submit(DEVICE_ID, device_ptr, |
53 | &test_value, var_size)); |
54 | |
55 | // Read data from device |
56 | EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_retrieve(DEVICE_ID, &host_value, |
57 | device_ptr, var_size)); |
58 | |
59 | // Compare values |
60 | EXPECT_EQ(host_value, test_value); |
61 | |
62 | // Cleanup data |
63 | EXPECT_EQ(OFFLOAD_SUCCESS, |
64 | __tgt_rtl_data_delete(DEVICE_ID, device_ptr, TARGET_ALLOC_DEFAULT)); |
65 | } |
66 | |
67 | // Test async GPU allocation and R/W |
68 | TEST(NextgenPluginsTest, PluginAsyncAlloc) { |
69 | int32_t test_value = 47; |
70 | int32_t host_value = -1; |
71 | int64_t var_size = sizeof(int32_t); |
72 | __tgt_async_info *info; |
73 | |
74 | // Init plugin and device |
75 | EXPECT_EQ(OFFLOAD_SUCCESS, init_test_device(ID: DEVICE_ID)); |
76 | |
77 | // Check if device supports async |
78 | // Platforms like x86_64 don't support it |
79 | if (__tgt_rtl_init_async_info(DEVICE_ID, &info) == OFFLOAD_SUCCESS) { |
80 | // Allocate memory |
81 | void *device_ptr = __tgt_rtl_data_alloc(DEVICE_ID, var_size, nullptr, |
82 | TARGET_ALLOC_DEFAULT); |
83 | |
84 | // Check that the result is not null |
85 | EXPECT_NE(device_ptr, nullptr); |
86 | |
87 | // Submit data to device asynchronously |
88 | EXPECT_EQ(OFFLOAD_SUCCESS, |
89 | __tgt_rtl_data_submit_async(DEVICE_ID, device_ptr, &test_value, |
90 | var_size, info)); |
91 | |
92 | // Wait for async request to process |
93 | EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_synchronize(DEVICE_ID, info)); |
94 | |
95 | // Read data from device |
96 | EXPECT_EQ(OFFLOAD_SUCCESS, |
97 | __tgt_rtl_data_retrieve_async(DEVICE_ID, &host_value, device_ptr, |
98 | var_size, info)); |
99 | |
100 | // Wait for async request to process |
101 | EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_synchronize(DEVICE_ID, info)); |
102 | |
103 | // Compare values |
104 | EXPECT_EQ(host_value, test_value); |
105 | |
106 | // Cleanup data |
107 | EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_delete(DEVICE_ID, device_ptr, |
108 | TARGET_ALLOC_DEFAULT)); |
109 | } |
110 | } |
111 | |
112 | // Test GPU data exchange |
113 | TEST(NextgenPluginsTest, PluginDataSwap) { |
114 | int32_t test_value = 23; |
115 | int32_t host_value = -1; |
116 | int64_t var_size = sizeof(int32_t); |
117 | |
118 | // Look for compatible device |
119 | int DEVICE_TWO = -1; |
120 | for (int i = 1; i < __tgt_rtl_number_of_devices(); i++) { |
121 | if (__tgt_rtl_is_data_exchangable(DEVICE_ID, i)) { |
122 | DEVICE_TWO = i; |
123 | break; |
124 | } |
125 | } |
126 | |
127 | // Only run test if we have multiple GPUs to test |
128 | // GPUs must be compatible for test to work |
129 | if (DEVICE_TWO >= 1) { |
130 | // Init both GPUs |
131 | EXPECT_EQ(OFFLOAD_SUCCESS, init_test_device(ID: DEVICE_ID)); |
132 | EXPECT_EQ(OFFLOAD_SUCCESS, init_test_device(DEVICE_TWO)); |
133 | |
134 | // Allocate memory on both GPUs |
135 | // DEVICE_ID will be the source |
136 | // DEVICE_TWO will be the destination |
137 | void *source_ptr = __tgt_rtl_data_alloc(DEVICE_ID, var_size, nullptr, |
138 | TARGET_ALLOC_DEFAULT); |
139 | void *dest_ptr = __tgt_rtl_data_alloc(DEVICE_TWO, var_size, nullptr, |
140 | TARGET_ALLOC_DEFAULT); |
141 | |
142 | // Check for success in allocation |
143 | EXPECT_NE(source_ptr, nullptr); |
144 | EXPECT_NE(dest_ptr, nullptr); |
145 | |
146 | // Write data to source |
147 | EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_submit(DEVICE_ID, source_ptr, |
148 | &test_value, var_size)); |
149 | |
150 | // Transfer data between devices |
151 | EXPECT_EQ(OFFLOAD_SUCCESS, |
152 | __tgt_rtl_data_exchange(DEVICE_ID, source_ptr, DEVICE_TWO, |
153 | dest_ptr, var_size)); |
154 | |
155 | // Read from destination device (DEVICE_TWO) memory |
156 | EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_retrieve(DEVICE_TWO, &host_value, |
157 | dest_ptr, var_size)); |
158 | |
159 | // Ensure match |
160 | EXPECT_EQ(host_value, test_value); |
161 | |
162 | // Cleanup |
163 | EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_delete(DEVICE_ID, source_ptr, |
164 | TARGET_ALLOC_DEFAULT)); |
165 | EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_delete(DEVICE_TWO, dest_ptr, |
166 | TARGET_ALLOC_DEFAULT)); |
167 | } |
168 | } |
169 | |