Skip to content

Commit

Permalink
[CTS] Add more USM testing
Browse files Browse the repository at this point in the history
* Expand USMMemcpy2D testing to test all USM allocation types
* Add USM linked list kernel execution test

The linked list test is based on USM/smemll.cpp from the SYCL-E2E tests
and checks that USM allocations are actually usable from a kernel.
  • Loading branch information
callumfare committed Jan 16, 2024
1 parent 79c28d0 commit 4e3fdee
Show file tree
Hide file tree
Showing 9 changed files with 261 additions and 23 deletions.
1 change: 1 addition & 0 deletions test/conformance/device_code/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ add_device_binary(${CMAKE_CURRENT_SOURCE_DIR}/foo.cpp)
add_device_binary(${CMAKE_CURRENT_SOURCE_DIR}/image_copy.cpp)
add_device_binary(${CMAKE_CURRENT_SOURCE_DIR}/mean.cpp)
add_device_binary(${CMAKE_CURRENT_SOURCE_DIR}/spec_constant.cpp)
add_device_binary(${CMAKE_CURRENT_SOURCE_DIR}/usm_ll.cpp)

set(KERNEL_HEADER ${UR_CONFORMANCE_DEVICE_BINARIES_DIR}/kernel_entry_points.h)
add_custom_command(OUTPUT ${KERNEL_HEADER}
Expand Down
68 changes: 68 additions & 0 deletions test/conformance/device_code/usm_ll.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright (C) 2023 Intel Corporation
// Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions.
// See LICENSE.TXT
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <sycl/sycl.hpp>

using namespace sycl;

int numNodes = 4;

struct Node {
Node() : pNext(nullptr), Num(0xDEADBEEF) {}

Node *pNext;
uint32_t Num;
};

int main() {
queue q;
auto dev = q.get_device();
auto ctxt = q.get_context();

if (!dev.get_info<info::device::usm_shared_allocations>()) {
return 0;
}

Node *s_head =
(Node *)aligned_alloc_shared(alignof(Node), sizeof(Node), dev, ctxt);
if (s_head == nullptr) {
return -1;
}
Node *s_cur = s_head;

for (int i = 0; i < numNodes; i++) {
s_cur->Num = i * 2;

if (i != (numNodes - 1)) {
s_cur->pNext = (Node *)aligned_alloc_shared(
alignof(Node), sizeof(Node), dev, ctxt);
} else {
s_cur->pNext = nullptr;
}

s_cur = s_cur->pNext;
}

auto e1 = q.submit([=](handler &cgh) {
cgh.single_task<class linkedlist>([=]() {
Node *pHead = s_head;
while (pHead) {
pHead->Num = pHead->Num * 2 + 1;
pHead = pHead->pNext;
}
});
});

e1.wait();

s_cur = s_head;
for (int i = 0; i < numNodes; i++) {
Node *old = s_cur;
s_cur = s_cur->pNext;
free(old, ctxt);
}

return 0;
}
1 change: 1 addition & 0 deletions test/conformance/enqueue/enqueue_adapter_opencl.match
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@
{{OPT}}urEnqueueUSMMemcpy2DNegativeTest.InvalidSize/Intel_R__OpenCL___{{.*}}
{{OPT}}urEnqueueUSMMemcpy2DNegativeTest.InvalidEventWaitList/Intel_R__OpenCL___{{.*}}
{{OPT}}urEnqueueUSMPrefetchTest.InvalidSizeTooLarge/Intel_R__OpenCL___{{.*}}
{{OPT}}urEnqueueKernelLaunchUSMLinkedList.Success/Intel_R__OpenCL___{{.*}}_UsePoolEnabled
22 changes: 19 additions & 3 deletions test/conformance/enqueue/helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,33 @@ struct TestParameters2D {
size_t height;
};

inline std::string USMKindToString(USMKind kind) {
switch (kind) {
case USMKind::Device:
return "Device";
case USMKind::Host:
return "Host";
case USMKind::Shared:
default:
return "Shared";
}
}

template <typename T>
inline std::string
print2DTestString(const testing::TestParamInfo<typename T::ParamType> &info) {
const auto device_handle = std::get<0>(info.param);
const auto platform_device_name =
uur::GetPlatformAndDeviceName(device_handle);
std::stringstream test_name;
auto src_kind = std::get<1>(std::get<1>(info.param));
auto dst_kind = std::get<2>(std::get<1>(info.param));
test_name << platform_device_name << "__pitch__"
<< std::get<1>(info.param).pitch << "__width__"
<< std::get<1>(info.param).width << "__height__"
<< std::get<1>(info.param).height;
<< std::get<0>(std::get<1>(info.param)).pitch << "__width__"
<< std::get<0>(std::get<1>(info.param)).width << "__height__"
<< std::get<0>(std::get<1>(info.param)).height << "__src__"
<< USMKindToString(src_kind) << "__dst__"
<< USMKindToString(dst_kind);
return test_name.str();
}

Expand Down
99 changes: 99 additions & 0 deletions test/conformance/enqueue/urEnqueueKernelLaunch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,3 +262,102 @@ TEST_P(urEnqueueKernelLaunchMultiDeviceTest, KernelLaunchReadDifferentQueues) {
ASSERT_EQ(val, output) << "Result on queue " << i << " did not match!";
}
}

struct urEnqueueKernelLaunchUSMLinkedList
: uur::urKernelTestWithParam<uur::BoolTestParam> {
struct Node {
Node() : next(nullptr), num(0xDEADBEEF) {}

Node *next;
uint32_t num;
};

void SetUp() override {
program_name = "usm_ll";
UUR_RETURN_ON_FATAL_FAILURE(
uur::urKernelTestWithParam<uur::BoolTestParam>::SetUp());

use_pool = getParam().value;
ASSERT_SUCCESS(urQueueCreate(context, device, 0, &queue));
ur_usm_pool_desc_t pool_desc{UR_STRUCTURE_TYPE_USM_POOL_DESC, nullptr,
0};
if (use_pool) {
ASSERT_SUCCESS(urUSMPoolCreate(this->context, &pool_desc, &pool));
}
}

void TearDown() override {
auto *list_cur = list_head;
while (list_cur) {
auto *list_next = list_cur->next;
ASSERT_SUCCESS(urUSMFree(context, list_cur));
list_cur = list_next;
}

if (queue) {
ASSERT_SUCCESS(urQueueRelease(queue));
}

if (pool) {
ASSERT_SUCCESS(urUSMPoolRelease(pool));
}

UUR_RETURN_ON_FATAL_FAILURE(
uur::urKernelTestWithParam<uur::BoolTestParam>::TearDown());
}

size_t global_size = 1;
size_t global_offset = 0;
Node *list_head = nullptr;
const int num_nodes = 4;
bool use_pool = false;
ur_usm_pool_handle_t pool = nullptr;
ur_queue_handle_t queue;
};

UUR_TEST_SUITE_P(
urEnqueueKernelLaunchUSMLinkedList,
testing::ValuesIn(uur::BoolTestParam::makeBoolParam("UsePool")),
uur::deviceTestWithParamPrinter<uur::BoolTestParam>);

TEST_P(urEnqueueKernelLaunchUSMLinkedList, Success) {
ur_device_usm_access_capability_flags_t shared_usm_flags = 0;
ASSERT_SUCCESS(
uur::GetDeviceUSMSingleSharedSupport(device, shared_usm_flags));
if (!(shared_usm_flags & UR_DEVICE_USM_ACCESS_CAPABILITY_FLAG_ACCESS)) {
GTEST_SKIP() << "Shared USM is not supported.";
}

// Build linked list with USM allocations
ASSERT_SUCCESS(urUSMSharedAlloc(context, device, nullptr, pool,
sizeof(Node),
reinterpret_cast<void **>(&list_head)));
ASSERT_NE(list_head, nullptr);
Node *list_cur = list_head;
for (int i = 0; i < num_nodes; i++) {
list_cur->num = i * 2;
if (i < num_nodes - 1) {
ASSERT_SUCCESS(
urUSMSharedAlloc(context, device, nullptr, pool, sizeof(Node),
reinterpret_cast<void **>(&list_cur->next)));
ASSERT_NE(list_cur->next, nullptr);
} else {
list_cur->next = nullptr;
}
list_cur = list_cur->next;
}

// Run kernel which will iterate the list and modify the values
ASSERT_SUCCESS(urKernelSetArgPointer(kernel, 0, nullptr, &list_head));
ASSERT_SUCCESS(urEnqueueKernelLaunch(queue, kernel, 1, &global_offset,
&global_size, nullptr, 0, nullptr,
nullptr));
ASSERT_SUCCESS(urQueueFinish(queue));

// Verify values
list_cur = list_head;
for (int i = 0; i < num_nodes; i++) {
ASSERT_EQ(list_cur->num, i * 4 + 1);
list_cur = list_cur->next;
}
}
60 changes: 41 additions & 19 deletions test/conformance/enqueue/urEnqueueUSMMemcpy2D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,24 @@
#include "helpers.h"
#include <uur/fixtures.h>

using TestParametersMemcpy2D =
std::tuple<uur::TestParameters2D, uur::USMKind, uur::USMKind>;

struct urEnqueueUSMMemcpy2DTestWithParam
: uur::urQueueTestWithParam<uur::TestParameters2D> {
: uur::urQueueTestWithParam<TestParametersMemcpy2D> {
void SetUp() override {
UUR_RETURN_ON_FATAL_FAILURE(
uur::urQueueTestWithParam<uur::TestParameters2D>::SetUp());
uur::urQueueTestWithParam<TestParametersMemcpy2D>::SetUp());

const auto [in2DParams, inSrcKind, inDstKind] = getParam();
std::tie(pitch, width, height, src_kind, dst_kind) =
std::make_tuple(in2DParams.pitch, in2DParams.width,
in2DParams.height, inSrcKind, inDstKind);

ur_device_usm_access_capability_flags_t device_usm = 0;
ASSERT_SUCCESS(uur::GetDeviceUSMDeviceSupport(device, device_usm));
if (!device_usm) {
if (!device_usm && (src_kind == uur::USMKind::Device ||
dst_kind == uur::USMKind::Device)) {
GTEST_SKIP() << "Device USM is not supported";
}

Expand All @@ -25,15 +35,13 @@ struct urEnqueueUSMMemcpy2DTestWithParam
GTEST_SKIP() << "2D USM memcpy is not supported";
}

const auto [inPitch, inWidth, inHeight] = getParam();
std::tie(pitch, width, height) =
std::make_tuple(inPitch, inWidth, inHeight);

const size_t num_elements = pitch * height;
ASSERT_SUCCESS(urUSMDeviceAlloc(context, device, nullptr, nullptr,
num_elements, &pSrc));
ASSERT_SUCCESS(urUSMDeviceAlloc(context, device, nullptr, nullptr,
num_elements, &pDst));
ASSERT_SUCCESS(uur::MakeUSMAllocationByType(
src_kind, context, device, nullptr, nullptr, num_elements, &pSrc));

ASSERT_SUCCESS(uur::MakeUSMAllocationByType(
dst_kind, context, device, nullptr, nullptr, num_elements, &pDst));

ur_event_handle_t memset_event = nullptr;

ASSERT_SUCCESS(urEnqueueUSMFill(queue, pSrc, sizeof(memset_value),
Expand All @@ -52,17 +60,22 @@ struct urEnqueueUSMMemcpy2DTestWithParam
if (pDst) {
ASSERT_SUCCESS(urUSMFree(context, pDst));
}
uur::urQueueTestWithParam<uur::TestParameters2D>::TearDown();
uur::urQueueTestWithParam<TestParametersMemcpy2D>::TearDown();
}

void verifyMemcpySucceeded() {
std::vector<uint8_t> host_mem(pitch * height);
ASSERT_SUCCESS(urEnqueueUSMMemcpy2D(queue, true, host_mem.data(), pitch,
pDst, pitch, width, height, 0,
nullptr, nullptr));
const uint8_t *host_ptr = nullptr;
if (dst_kind == uur::USMKind::Device) {
ASSERT_SUCCESS(urEnqueueUSMMemcpy2D(queue, true, host_mem.data(),
pitch, pDst, pitch, width,
height, 0, nullptr, nullptr));
host_ptr = host_mem.data();
} else {
host_ptr = static_cast<const uint8_t *>(pDst);
}
for (size_t w = 0; w < width; ++w) {
for (size_t h = 0; h < height; ++h) {
const auto *host_ptr = host_mem.data();
const size_t index = (pitch * h) + w;
ASSERT_TRUE(*(host_ptr + index) == memset_value);
}
Expand All @@ -75,9 +88,11 @@ struct urEnqueueUSMMemcpy2DTestWithParam
size_t pitch = 0;
size_t width = 0;
size_t height = 0;
uur::USMKind src_kind;
uur::USMKind dst_kind;
};

static std::vector<uur::TestParameters2D> test_cases{
static std::vector<uur::TestParameters2D> test_sizes{
/* Everything set to 1 */
{1, 1, 1},
/* Height == 1 && Pitch > width */
Expand All @@ -92,7 +107,13 @@ static std::vector<uur::TestParameters2D> test_cases{
{234, 233, 1}};

UUR_TEST_SUITE_P(urEnqueueUSMMemcpy2DTestWithParam,
::testing::ValuesIn(test_cases),
::testing::Combine(::testing::ValuesIn(test_sizes),
::testing::Values(uur::USMKind::Device,
uur::USMKind::Host,
uur::USMKind::Shared),
::testing::Values(uur::USMKind::Device,
uur::USMKind::Host,
uur::USMKind::Shared)),
uur::print2DTestString<urEnqueueUSMMemcpy2DTestWithParam>);

TEST_P(urEnqueueUSMMemcpy2DTestWithParam, SuccessBlocking) {
Expand All @@ -119,7 +140,8 @@ TEST_P(urEnqueueUSMMemcpy2DTestWithParam, SuccessNonBlocking) {

using urEnqueueUSMMemcpy2DNegativeTest = urEnqueueUSMMemcpy2DTestWithParam;
UUR_TEST_SUITE_P(urEnqueueUSMMemcpy2DNegativeTest,
::testing::Values(uur::TestParameters2D{1, 1, 1}),
::testing::Values(TestParametersMemcpy2D{
{1, 1, 1}, uur::USMKind::Device, uur::USMKind::Device}),
uur::print2DTestString<urEnqueueUSMMemcpy2DTestWithParam>);

TEST_P(urEnqueueUSMMemcpy2DNegativeTest, InvalidNullHandleQueue) {
Expand Down
3 changes: 2 additions & 1 deletion test/conformance/testing/include/uur/fixtures.h
Original file line number Diff line number Diff line change
Expand Up @@ -1071,7 +1071,8 @@ struct urProgramTest : urQueueTest {
template <class T> struct urProgramTestWithParam : urContextTestWithParam<T> {
void SetUp() override {
UUR_RETURN_ON_FATAL_FAILURE(urContextTestWithParam<T>::SetUp());
uur::KernelsEnvironment::instance->LoadSource("foo", 0, il_binary);
uur::KernelsEnvironment::instance->LoadSource(program_name, 0,
il_binary);
ASSERT_SUCCESS(urProgramCreateWithIL(this->context, il_binary->data(),
il_binary->size(), nullptr,
&program));
Expand Down
12 changes: 12 additions & 0 deletions test/conformance/testing/include/uur/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,18 @@ ur_device_partition_property_t makePartitionEquallyDesc(uint32_t cu_per_device);
ur_device_partition_property_t
makePartitionByAffinityDomain(ur_device_affinity_domain_flags_t aff_domain);

enum class USMKind {
Device,
Host,
Shared,
};

ur_result_t MakeUSMAllocationByType(USMKind kind, ur_context_handle_t hContext,
ur_device_handle_t hDevice,
const ur_usm_desc_t *pUSMDesc,
ur_usm_pool_handle_t hPool, size_t size,
void **ppMem);

} // namespace uur

#endif // UR_CONFORMANCE_INCLUDE_UTILS_H_INCLUDED
18 changes: 18 additions & 0 deletions test/conformance/testing/source/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -658,4 +658,22 @@ makePartitionByAffinityDomain(ur_device_affinity_domain_flags_t aff_domain) {
return desc;
}

ur_result_t MakeUSMAllocationByType(USMKind kind, ur_context_handle_t hContext,
ur_device_handle_t hDevice,
const ur_usm_desc_t *pUSMDesc,
ur_usm_pool_handle_t hPool, size_t size,
void **ppMem) {
switch (kind) {
case USMKind::Device:
return urUSMDeviceAlloc(hContext, hDevice, pUSMDesc, hPool, size,
ppMem);
case USMKind::Host:
return urUSMHostAlloc(hContext, pUSMDesc, hPool, size, ppMem);
default:
case USMKind::Shared:
return urUSMSharedAlloc(hContext, hDevice, pUSMDesc, hPool, size,
ppMem);
}
}

} // namespace uur

0 comments on commit 4e3fdee

Please sign in to comment.