Skip to content

Commit 84d656b

Browse files
Merge pull request #907 from omarahmed1111/Add-testing-for-memory-migration-across-devices-in-same-context
Add testing for memory management across multi-device contexts
2 parents 9badc83 + 4f5dc2e commit 84d656b

File tree

5 files changed

+266
-1
lines changed

5 files changed

+266
-1
lines changed

test/conformance/enqueue/urEnqueueKernelLaunch.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,49 @@ TEST_P(urEnqueueKernelLaunchWithVirtualMemory, Success) {
216216
ASSERT_EQ(fill_val, data.at(i));
217217
}
218218
}
219+
220+
struct urEnqueueKernelLaunchMultiDeviceTest : public urEnqueueKernelLaunchTest {
221+
void SetUp() override {
222+
UUR_RETURN_ON_FATAL_FAILURE(urEnqueueKernelLaunchTest::SetUp());
223+
queues.reserve(uur::DevicesEnvironment::instance->devices.size());
224+
for (const auto &device : uur::DevicesEnvironment::instance->devices) {
225+
ur_queue_handle_t queue = nullptr;
226+
ASSERT_SUCCESS(urQueueCreate(this->context, device, 0, &queue));
227+
queues.push_back(queue);
228+
}
229+
}
230+
231+
void TearDown() override {
232+
for (const auto &queue : queues) {
233+
EXPECT_SUCCESS(urQueueRelease(queue));
234+
}
235+
UUR_RETURN_ON_FATAL_FAILURE(urEnqueueKernelLaunchTest::TearDown());
236+
}
237+
238+
std::vector<ur_queue_handle_t> queues;
239+
};
240+
UUR_INSTANTIATE_DEVICE_TEST_SUITE_P(urEnqueueKernelLaunchMultiDeviceTest);
241+
242+
TEST_P(urEnqueueKernelLaunchMultiDeviceTest, KernelLaunchReadDifferentQueues) {
243+
ur_mem_handle_t buffer = nullptr;
244+
AddBuffer1DArg(sizeof(val) * global_size, &buffer);
245+
AddPodArg(val);
246+
ASSERT_SUCCESS(urEnqueueKernelLaunch(queues[0], kernel, n_dimensions,
247+
&global_offset, &global_size, nullptr,
248+
0, nullptr, nullptr));
249+
250+
// Wait for the queue to finish executing.
251+
EXPECT_SUCCESS(urEnqueueEventsWait(queues[0], 0, nullptr, nullptr));
252+
253+
// Then the remaining queues do blocking reads from the buffer. Since the
254+
// queues target different devices this checks that any devices memory has
255+
// been synchronized.
256+
for (unsigned i = 1; i < queues.size(); ++i) {
257+
const auto queue = queues[i];
258+
uint32_t output = 0;
259+
ASSERT_SUCCESS(urEnqueueMemBufferRead(queue, buffer, true, 0,
260+
sizeof(output), &output, 0,
261+
nullptr, nullptr));
262+
ASSERT_EQ(val, output) << "Result on queue " << i << " did not match!";
263+
}
264+
}

test/conformance/enqueue/urEnqueueMemBufferReadRect.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,8 @@ TEST_P(urEnqueueMemBufferReadRectTest, InvalidNullPtrEventWaitList) {
188188
using urEnqueueMemBufferReadRectMultiDeviceTest =
189189
uur::urMultiDeviceMemBufferQueueTest;
190190

191-
TEST_F(urEnqueueMemBufferReadRectMultiDeviceTest, WriteReadDifferentQueues) {
191+
TEST_F(urEnqueueMemBufferReadRectMultiDeviceTest,
192+
WriteRectReadDifferentQueues) {
192193
// First queue does a blocking write of 42 into the buffer.
193194
// Then a rectangular write the buffer as 1024x1x1 1D.
194195
std::vector<uint32_t> input(count, 42);

test/conformance/enqueue/urEnqueueMemImageCopy.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,3 +251,63 @@ TEST_P(urEnqueueMemImageCopyTest, InvalidSize) {
251251
{1, 0, 0}, size, 0, nullptr,
252252
nullptr));
253253
}
254+
255+
using urEnqueueMemImageCopyMultiDeviceTest =
256+
uur::urMultiDeviceMemImageWriteTest;
257+
258+
TEST_F(urEnqueueMemImageCopyMultiDeviceTest, CopyReadDifferentQueues) {
259+
ur_mem_handle_t dstImage1D = nullptr;
260+
ASSERT_SUCCESS(urMemImageCreate(context, UR_MEM_FLAG_READ_WRITE, &format,
261+
&desc1D, nullptr, &dstImage1D));
262+
ASSERT_SUCCESS(urEnqueueMemImageCopy(queues[0], image1D, dstImage1D, origin,
263+
origin, region1D, 0, nullptr,
264+
nullptr));
265+
266+
ur_mem_handle_t dstImage2D = nullptr;
267+
ASSERT_SUCCESS(urMemImageCreate(context, UR_MEM_FLAG_READ_WRITE, &format,
268+
&desc2D, nullptr, &dstImage2D));
269+
ASSERT_SUCCESS(urEnqueueMemImageCopy(queues[0], image2D, dstImage2D, origin,
270+
origin, region2D, 0, nullptr,
271+
nullptr));
272+
273+
ur_mem_handle_t dstImage3D = nullptr;
274+
ASSERT_SUCCESS(urMemImageCreate(context, UR_MEM_FLAG_READ_WRITE, &format,
275+
&desc3D, nullptr, &dstImage3D));
276+
ASSERT_SUCCESS(urEnqueueMemImageCopy(queues[0], image3D, dstImage3D, origin,
277+
origin, region3D, 0, nullptr,
278+
nullptr));
279+
280+
// Wait for the queue to finish executing.
281+
EXPECT_SUCCESS(urEnqueueEventsWait(queues[0], 0, nullptr, nullptr));
282+
283+
// The remaining queues do blocking reads from the image1D/2D/3D. Since the
284+
// queues target different devices this checks that any devices memory has
285+
// been synchronized.
286+
for (unsigned i = 1; i < queues.size(); ++i) {
287+
const auto queue = queues[i];
288+
289+
std::vector<uint32_t> output1D(width * 4, 42);
290+
ASSERT_SUCCESS(urEnqueueMemImageRead(queue, image1D, true, origin,
291+
region1D, 0, 0, output1D.data(), 0,
292+
nullptr, nullptr));
293+
294+
std::vector<uint32_t> output2D(width * height * 4, 42);
295+
ASSERT_SUCCESS(urEnqueueMemImageRead(queue, image2D, true, origin,
296+
region2D, 0, 0, output2D.data(), 0,
297+
nullptr, nullptr));
298+
299+
std::vector<uint32_t> output3D(width * height * depth * 4, 42);
300+
ASSERT_SUCCESS(urEnqueueMemImageRead(queue, image3D, true, origin,
301+
region3D, 0, 0, output3D.data(), 0,
302+
nullptr, nullptr));
303+
304+
ASSERT_EQ(input1D, output1D)
305+
<< "Result on queue " << i << " for 1D image did not match!";
306+
307+
ASSERT_EQ(input2D, output2D)
308+
<< "Result on queue " << i << " for 2D image did not match!";
309+
310+
ASSERT_EQ(input3D, output3D)
311+
<< "Result on queue " << i << " for 3D image did not match!";
312+
}
313+
}

test/conformance/enqueue/urEnqueueMemImageRead.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,39 @@ TEST_P(urEnqueueMemImageReadTest, InvalidRegion3D) {
130130
bad_region, 0, 0, output.data(), 0,
131131
nullptr, nullptr));
132132
}
133+
134+
using urEnqueueMemImageReadMultiDeviceTest =
135+
uur::urMultiDeviceMemImageWriteTest;
136+
137+
TEST_F(urEnqueueMemImageReadMultiDeviceTest, WriteReadDifferentQueues) {
138+
// The remaining queues do blocking reads from the image1D/2D/3D. Since the
139+
// queues target different devices this checks that any devices memory has
140+
// been synchronized.
141+
for (unsigned i = 1; i < queues.size(); ++i) {
142+
const auto queue = queues[i];
143+
144+
std::vector<uint32_t> output1D(width * 4, 42);
145+
ASSERT_SUCCESS(urEnqueueMemImageRead(queue, image1D, true, origin,
146+
region1D, 0, 0, output1D.data(), 0,
147+
nullptr, nullptr));
148+
149+
std::vector<uint32_t> output2D(width * height * 4, 42);
150+
ASSERT_SUCCESS(urEnqueueMemImageRead(queue, image2D, true, origin,
151+
region2D, 0, 0, output2D.data(), 0,
152+
nullptr, nullptr));
153+
154+
std::vector<uint32_t> output3D(width * height * depth * 4, 42);
155+
ASSERT_SUCCESS(urEnqueueMemImageRead(queue, image3D, true, origin,
156+
region3D, 0, 0, output3D.data(), 0,
157+
nullptr, nullptr));
158+
159+
ASSERT_EQ(input1D, output1D)
160+
<< "Result on queue " << i << " for 1D image did not match!";
161+
162+
ASSERT_EQ(input2D, output2D)
163+
<< "Result on queue " << i << " for 2D image did not match!";
164+
165+
ASSERT_EQ(input3D, output3D)
166+
<< "Result on queue " << i << " for 3D image did not match!";
167+
}
168+
}

test/conformance/testing/include/uur/fixtures.h

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,128 @@ struct urMemImageQueueTest : urQueueTest {
601601
0}; // num samples
602602
};
603603

604+
struct urMultiDeviceMemImageTest : urMultiDeviceContextTest {
605+
void SetUp() override {
606+
UUR_RETURN_ON_FATAL_FAILURE(urMultiDeviceContextTest::SetUp());
607+
ASSERT_SUCCESS(urMemImageCreate(context, UR_MEM_FLAG_READ_WRITE,
608+
&format, &desc1D, nullptr, &image1D));
609+
610+
ASSERT_SUCCESS(urMemImageCreate(context, UR_MEM_FLAG_READ_WRITE,
611+
&format, &desc2D, nullptr, &image2D));
612+
613+
ASSERT_SUCCESS(urMemImageCreate(context, UR_MEM_FLAG_READ_WRITE,
614+
&format, &desc3D, nullptr, &image3D));
615+
}
616+
617+
void TearDown() override {
618+
if (image1D) {
619+
EXPECT_SUCCESS(urMemRelease(image1D));
620+
}
621+
if (image2D) {
622+
EXPECT_SUCCESS(urMemRelease(image2D));
623+
}
624+
if (image3D) {
625+
EXPECT_SUCCESS(urMemRelease(image3D));
626+
}
627+
UUR_RETURN_ON_FATAL_FAILURE(urMultiDeviceContextTest::TearDown());
628+
}
629+
630+
const size_t width = 1024;
631+
const size_t height = 8;
632+
const size_t depth = 2;
633+
ur_mem_handle_t image1D = nullptr;
634+
ur_mem_handle_t image2D = nullptr;
635+
ur_mem_handle_t image3D = nullptr;
636+
ur_rect_region_t region1D{width, 1, 1};
637+
ur_rect_region_t region2D{width, height, 1};
638+
ur_rect_region_t region3D{width, height, depth};
639+
ur_rect_offset_t origin{0, 0, 0};
640+
ur_image_format_t format = {UR_IMAGE_CHANNEL_ORDER_RGBA,
641+
UR_IMAGE_CHANNEL_TYPE_FLOAT};
642+
ur_image_desc_t desc1D = {UR_STRUCTURE_TYPE_IMAGE_DESC, // stype
643+
nullptr, // pNext
644+
UR_MEM_TYPE_IMAGE1D, // mem object type
645+
width, // image width
646+
1, // image height
647+
1, // image depth
648+
1, // array size
649+
0, // row pitch
650+
0, // slice pitch
651+
0, // mip levels
652+
0}; // num samples
653+
654+
ur_image_desc_t desc2D = {UR_STRUCTURE_TYPE_IMAGE_DESC, // stype
655+
nullptr, // pNext
656+
UR_MEM_TYPE_IMAGE2D, // mem object type
657+
width, // image width
658+
height, // image height
659+
1, // image depth
660+
1, // array size
661+
0, // row pitch
662+
0, // slice pitch
663+
0, // mip levels
664+
0}; // num samples
665+
666+
ur_image_desc_t desc3D = {UR_STRUCTURE_TYPE_IMAGE_DESC, // stype
667+
nullptr, // pNext
668+
UR_MEM_TYPE_IMAGE3D, // mem object type
669+
width, // image width
670+
height, // image height
671+
depth, // image depth
672+
1, // array size
673+
0, // row pitch
674+
0, // slice pitch
675+
0, // mip levels
676+
0}; // num samples
677+
};
678+
679+
struct urMultiDeviceMemImageQueueTest : urMultiDeviceMemImageTest {
680+
void SetUp() override {
681+
UUR_RETURN_ON_FATAL_FAILURE(urMultiDeviceMemImageTest::SetUp());
682+
queues.reserve(DevicesEnvironment::instance->devices.size());
683+
for (const auto &device : DevicesEnvironment::instance->devices) {
684+
ur_queue_handle_t queue = nullptr;
685+
ASSERT_SUCCESS(urQueueCreate(context, device, 0, &queue));
686+
queues.push_back(queue);
687+
}
688+
}
689+
690+
void TearDown() override {
691+
for (const auto &queue : queues) {
692+
EXPECT_SUCCESS(urQueueRelease(queue));
693+
}
694+
UUR_RETURN_ON_FATAL_FAILURE(urMultiDeviceMemImageTest::TearDown());
695+
}
696+
697+
std::vector<ur_queue_handle_t> queues;
698+
};
699+
700+
struct urMultiDeviceMemImageWriteTest : urMultiDeviceMemImageQueueTest {
701+
void SetUp() override {
702+
UUR_RETURN_ON_FATAL_FAILURE(urMultiDeviceMemImageQueueTest::SetUp());
703+
704+
ASSERT_SUCCESS(urEnqueueMemImageWrite(queues[0], image1D, true, origin,
705+
region1D, 0, 0, input1D.data(), 0,
706+
nullptr, nullptr));
707+
ASSERT_SUCCESS(urEnqueueMemImageWrite(queues[0], image2D, true, origin,
708+
region2D, 0, 0, input2D.data(), 0,
709+
nullptr, nullptr));
710+
ASSERT_SUCCESS(urEnqueueMemImageWrite(queues[0], image3D, true, origin,
711+
region3D, 0, 0, input3D.data(), 0,
712+
nullptr, nullptr));
713+
}
714+
715+
void TearDown() override {
716+
UUR_RETURN_ON_FATAL_FAILURE(urMultiDeviceMemImageQueueTest::TearDown());
717+
}
718+
719+
std::vector<uint32_t> input1D = std::vector<uint32_t>(width * 4, 42);
720+
std::vector<uint32_t> input2D =
721+
std::vector<uint32_t>(width * height * 4, 42);
722+
std::vector<uint32_t> input3D =
723+
std::vector<uint32_t>(width * height * depth * 4, 42);
724+
};
725+
604726
struct urUSMDeviceAllocTest : urQueueTest {
605727
void SetUp() override {
606728
UUR_RETURN_ON_FATAL_FAILURE(uur::urQueueTest::SetUp());

0 commit comments

Comments
 (0)