From bf5de8ede55823002329ee74861a54f6ea6427e4 Mon Sep 17 00:00:00 2001 From: Diptorup Deb Date: Mon, 21 Jun 2021 21:51:45 -0500 Subject: [PATCH 1/3] Add missing extra checks to ensure unwrapped pointer is not Null. --- .../source/dpctl_sycl_queue_interface.cpp | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/dpctl-capi/source/dpctl_sycl_queue_interface.cpp b/dpctl-capi/source/dpctl_sycl_queue_interface.cpp index 8a93b31f4f..3ccaca7511 100644 --- a/dpctl-capi/source/dpctl_sycl_queue_interface.cpp +++ b/dpctl-capi/source/dpctl_sycl_queue_interface.cpp @@ -294,14 +294,18 @@ bool DPCTLQueue_AreEq(__dpctl_keep const DPCTLSyclQueueRef QRef1, DPCTLSyclBackendType DPCTLQueue_GetBackend(__dpctl_keep DPCTLSyclQueueRef QRef) { auto Q = unwrap(QRef); - try { - auto C = Q->get_context(); - return DPCTLContext_GetBackend(wrap(&C)); - } catch (runtime_error &re) { - std::cerr << re.what() << '\n'; - // store error message - return DPCTL_UNKNOWN_BACKEND; + if (Q) { + try { + auto C = Q->get_context(); + return DPCTLContext_GetBackend(wrap(&C)); + } catch (runtime_error &re) { + std::cerr << re.what() << '\n'; + // store error message + return DPCTL_UNKNOWN_BACKEND; + } } + else + return DPCTL_UNKNOWN_BACKEND; } __dpctl_give DPCTLSyclDeviceRef @@ -327,8 +331,13 @@ __dpctl_give DPCTLSyclContextRef DPCTLQueue_GetContext(__dpctl_keep const DPCTLSyclQueueRef QRef) { auto Q = unwrap(QRef); - auto Context = new context(Q->get_context()); - return wrap(Context); + DPCTLSyclContextRef CRef = nullptr; + if (Q) + CRef = wrap(new context(Q->get_context())); + else { + std::cerr << "Could not get the context for this queue.\n"; + } + return CRef; } __dpctl_give DPCTLSyclEventRef From 9b05b4e65e6c2c540a49293b08884cff51a14106 Mon Sep 17 00:00:00 2001 From: Diptorup Deb Date: Tue, 22 Jun 2021 17:42:41 -0500 Subject: [PATCH 2/3] Add error messages to L0 program creation routine. --- dpctl-capi/source/dpctl_sycl_program_interface.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dpctl-capi/source/dpctl_sycl_program_interface.cpp b/dpctl-capi/source/dpctl_sycl_program_interface.cpp index 850185627e..8cbbd0dfc6 100644 --- a/dpctl-capi/source/dpctl_sycl_program_interface.cpp +++ b/dpctl-capi/source/dpctl_sycl_program_interface.cpp @@ -164,13 +164,16 @@ createLevelZeroInterOpProgram(const context &SyclCtx, auto stZeModuleCreateF = getZeModuleCreateFn(); - if (!stZeModuleCreateF) + if (!stZeModuleCreateF) { + std::cerr << "ZeModuleCreateFn is invalid.\n"; return nullptr; + } auto ret = stZeModuleCreateF(ZeCtx, ZeDevice, &ZeModuleDesc, &ZeModule, nullptr); if (ret != ZE_RESULT_SUCCESS) { // TODO: handle error + std::cerr << "ZeModule creation failed.\n"; return nullptr; } @@ -199,6 +202,8 @@ DPCTLProgram_CreateFromSpirv(__dpctl_keep const DPCTLSyclContextRef CtxRef, context *SyclCtx = nullptr; if (!CtxRef) { // \todo handle error + std::cerr << "Cannot create program from SPIR-V as the supplied SYCL " + "context is NULL.\n"; return Pref; } SyclCtx = unwrap(CtxRef); From 57488e171f9b4b75acd2f26ff4e22979eb4720c5 Mon Sep 17 00:00:00 2001 From: Diptorup Deb Date: Mon, 21 Jun 2021 21:52:30 -0500 Subject: [PATCH 3/3] Refactored tests. --- .../tests/test_sycl_queue_interface.cpp | 376 +++++++----------- dpctl-capi/tests/test_sycl_queue_submit.cpp | 125 ++++++ 2 files changed, 272 insertions(+), 229 deletions(-) create mode 100644 dpctl-capi/tests/test_sycl_queue_submit.cpp diff --git a/dpctl-capi/tests/test_sycl_queue_interface.cpp b/dpctl-capi/tests/test_sycl_queue_interface.cpp index d2f3504f3d..8c2c7b4127 100644 --- a/dpctl-capi/tests/test_sycl_queue_interface.cpp +++ b/dpctl-capi/tests/test_sycl_queue_interface.cpp @@ -30,11 +30,8 @@ #include "dpctl_sycl_device_manager.h" #include "dpctl_sycl_device_selector_interface.h" #include "dpctl_sycl_event_interface.h" -#include "dpctl_sycl_kernel_interface.h" -#include "dpctl_sycl_program_interface.h" #include "dpctl_sycl_queue_interface.h" #include "dpctl_sycl_queue_manager.h" -#include "dpctl_sycl_usm_interface.h" #include #include @@ -42,71 +39,25 @@ using namespace cl::sycl; namespace { -constexpr size_t SIZE = 1024; - -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(void, DPCTLSyclUSMRef); DEFINE_SIMPLE_CONVERSION_FUNCTIONS(queue, DPCTLSyclQueueRef); -void add_kernel_checker(const float *a, const float *b, const float *c) -{ - // Validate the data - for (auto i = 0ul; i < SIZE; ++i) { - EXPECT_EQ(c[i], a[i] + b[i]); - } -} - -void axpy_kernel_checker(const float *a, - const float *b, - const float *c, - float d) -{ - for (auto i = 0ul; i < SIZE; ++i) { - EXPECT_EQ(c[i], a[i] + d * b[i]); - } -} - -} /* End of anonymous namespace */ - -struct TestDPCTLSyclQueueInterface : public ::testing::Test -{ - const char *CLProgramStr = R"CLC( - kernel void init_arr (global float *a) { - size_t index = get_global_id(0); - a[index] = (float)index; - } - - kernel void add (global float* a, global float* b, global float* c) { - size_t index = get_global_id(0); - c[index] = a[index] + b[index]; - } - - kernel void axpy (global float* a, global float* b, - global float* c, float d) { - size_t index = get_global_id(0); - c[index] = a[index] + d*b[index]; - } - )CLC"; - const char *CompileOpts = "-cl-fast-relaxed-math"; - - TestDPCTLSyclQueueInterface() {} - - ~TestDPCTLSyclQueueInterface() {} -}; - struct TestDPCTLQueueMemberFunctions : public ::testing::TestWithParam { protected: - DPCTLSyclDeviceSelectorRef DSRef = nullptr; - DPCTLSyclDeviceRef DRef = nullptr; DPCTLSyclQueueRef QRef = nullptr; TestDPCTLQueueMemberFunctions() { - DSRef = DPCTLFilterSelector_Create(GetParam()); - DRef = DPCTLDevice_CreateFromSelector(DSRef); - QRef = - DPCTLQueue_CreateForDevice(DRef, nullptr, DPCTL_DEFAULT_PROPERTY); + auto DS = DPCTLFilterSelector_Create(GetParam()); + DPCTLSyclDeviceRef DRef = nullptr; + if (DS) { + EXPECT_NO_FATAL_FAILURE(DRef = DPCTLDevice_CreateFromSelector(DS)); + EXPECT_NO_FATAL_FAILURE(QRef = DPCTLQueue_CreateForDevice( + DRef, nullptr, DPCTL_DEFAULT_PROPERTY)); + } + DPCTLDevice_Delete(DRef); + DPCTLDeviceSelector_Delete(DS); } void SetUp() @@ -120,15 +71,15 @@ struct TestDPCTLQueueMemberFunctions ~TestDPCTLQueueMemberFunctions() { - DPCTLQueue_Delete(QRef); - DPCTLDeviceSelector_Delete(DSRef); - DPCTLDevice_Delete(DRef); + EXPECT_NO_FATAL_FAILURE(DPCTLQueue_Delete(QRef)); } }; -TEST_F(TestDPCTLSyclQueueInterface, CheckCreateForDevice) +} /* End of anonymous namespace */ + +TEST(TestDPCTLSyclQueueInterface, CheckCreateForDevice) { - /* We are testing that we do not crash even when input is garbage. */ + /* We are testing that we do not crash even when input is NULL. */ DPCTLSyclQueueRef QRef = nullptr; EXPECT_NO_FATAL_FAILURE( @@ -136,88 +87,164 @@ TEST_F(TestDPCTLSyclQueueInterface, CheckCreateForDevice) ASSERT_TRUE(QRef == nullptr); } -TEST_F(TestDPCTLSyclQueueInterface, CheckCopy) +TEST(TestDPCTLSyclQueueInterface, CheckCopy) { DPCTLSyclQueueRef Q1 = nullptr; DPCTLSyclQueueRef Q2 = nullptr; - EXPECT_NO_FATAL_FAILURE(Q1 = DPCTLQueueMgr_GetCurrentQueue()); + DPCTLSyclDeviceRef DRef = nullptr; + + EXPECT_NO_FATAL_FAILURE(DRef = DPCTLDevice_Create()); + EXPECT_NO_FATAL_FAILURE( + Q1 = DPCTLQueue_CreateForDevice(DRef, nullptr, DPCTL_DEFAULT_PROPERTY)); ASSERT_TRUE(Q1); EXPECT_NO_FATAL_FAILURE(Q2 = DPCTLQueue_Copy(Q1)); EXPECT_TRUE(bool(Q2)); EXPECT_NO_FATAL_FAILURE(DPCTLQueue_Delete(Q1)); EXPECT_NO_FATAL_FAILURE(DPCTLQueue_Delete(Q2)); + EXPECT_NO_FATAL_FAILURE(DPCTLDevice_Delete(DRef)); } -TEST_F(TestDPCTLSyclQueueInterface, CheckAreEq) +TEST(TestDPCTLSyclQueueInterface, CheckCopy_Invalid) { - auto FSRef = DPCTLFilterSelector_Create("opencl:gpu:0"); - auto DRef = DPCTLDevice_CreateFromSelector(FSRef); - if (!DRef) - GTEST_SKIP_("Skipping: No OpenCL GPUs available.\n"); + DPCTLSyclQueueRef Q1 = nullptr; + DPCTLSyclQueueRef Q2 = nullptr; - auto Q1 = DPCTLQueueMgr_GetCurrentQueue(); - auto Q2 = DPCTLQueueMgr_GetCurrentQueue(); + EXPECT_NO_FATAL_FAILURE(Q2 = DPCTLQueue_Copy(Q1)); + EXPECT_NO_FATAL_FAILURE(DPCTLQueue_Delete(Q1)); + EXPECT_NO_FATAL_FAILURE(DPCTLQueue_Delete(Q2)); +} - EXPECT_TRUE(Q1 && Q2); - if (!(Q1 && Q2)) { - DPCTLDeviceSelector_Delete(FSRef); - DPCTLDevice_Delete(DRef); - GTEST_SKIP_("No current queue exists. Skip everything else."); - } +TEST(TestDPCTLSyclQueueInterface, CheckAreEq_False) +{ + DPCTLSyclDeviceSelectorRef DSRef = nullptr; + DPCTLSyclDeviceRef DRef = nullptr; + DPCTLSyclQueueRef Q1 = nullptr; + DPCTLSyclQueueRef Q2 = nullptr; + EXPECT_NO_FATAL_FAILURE(DSRef = DPCTLDefaultSelector_Create()); + EXPECT_NO_FATAL_FAILURE(DRef = DPCTLDevice_CreateFromSelector(DSRef)); + EXPECT_NO_FATAL_FAILURE( + Q1 = DPCTLQueue_CreateForDevice(DRef, nullptr, DPCTL_DEFAULT_PROPERTY)); + EXPECT_NO_FATAL_FAILURE( + Q2 = DPCTLQueue_CreateForDevice(DRef, nullptr, DPCTL_DEFAULT_PROPERTY)); + EXPECT_FALSE(DPCTLQueue_AreEq(Q1, Q2)); + EXPECT_FALSE(DPCTLQueue_Hash(Q1) == DPCTLQueue_Hash(Q2)); + auto C0 = DPCTLQueue_GetContext(Q1); + auto C1 = DPCTLQueue_GetContext(Q2); + // All the queues should share the same context + EXPECT_TRUE(DPCTLContext_AreEq(C0, C1)); + EXPECT_NO_FATAL_FAILURE(DPCTLContext_Delete(C0)); + EXPECT_NO_FATAL_FAILURE(DPCTLContext_Delete(C1)); + EXPECT_NO_FATAL_FAILURE(DPCTLQueue_Delete(Q1)); + EXPECT_NO_FATAL_FAILURE(DPCTLQueue_Delete(Q2)); + EXPECT_NO_FATAL_FAILURE(DPCTLDevice_Delete(DRef)); + EXPECT_NO_FATAL_FAILURE(DPCTLDeviceSelector_Delete(DSRef)); +} + +TEST(TestDPCTLSyclQueueInterface, CheckAreEq_True) +{ + DPCTLSyclDeviceSelectorRef DSRef = nullptr; + DPCTLSyclDeviceRef DRef = nullptr; + DPCTLSyclQueueRef Q1 = nullptr; + DPCTLSyclQueueRef Q2 = nullptr; + + EXPECT_NO_FATAL_FAILURE(DSRef = DPCTLDefaultSelector_Create()); + EXPECT_NO_FATAL_FAILURE(DRef = DPCTLDevice_CreateFromSelector(DSRef)); + EXPECT_NO_FATAL_FAILURE( + Q1 = DPCTLQueue_CreateForDevice(DRef, nullptr, DPCTL_DEFAULT_PROPERTY)); + EXPECT_NO_FATAL_FAILURE(Q2 = DPCTLQueue_Copy(Q1)); EXPECT_TRUE(DPCTLQueue_AreEq(Q1, Q2)); EXPECT_TRUE(DPCTLQueue_Hash(Q1) == DPCTLQueue_Hash(Q2)); - auto Q3 = DPCTLQueue_CreateForDevice(DRef, nullptr, 0); - auto Q4 = DPCTLQueue_CreateForDevice(DRef, nullptr, 0); + EXPECT_NO_FATAL_FAILURE(DPCTLQueue_Delete(Q1)); + EXPECT_NO_FATAL_FAILURE(DPCTLQueue_Delete(Q2)); + EXPECT_NO_FATAL_FAILURE(DPCTLDevice_Delete(DRef)); + EXPECT_NO_FATAL_FAILURE(DPCTLDeviceSelector_Delete(DSRef)); +} - // These are different queues - EXPECT_FALSE(DPCTLQueue_AreEq(Q3, Q4)); - EXPECT_FALSE(DPCTLQueue_Hash(Q3) == DPCTLQueue_Hash(Q4)); +TEST(TestDPCTLSyclQueueInterface, CheckAreEq_Invalid) +{ + DPCTLSyclDeviceSelectorRef DSRef = nullptr; + DPCTLSyclDeviceRef DRef = nullptr; + DPCTLSyclQueueRef Q1 = nullptr; + DPCTLSyclQueueRef Q2 = nullptr; - auto C0 = DPCTLQueue_GetContext(Q3); - auto C1 = DPCTLQueue_GetContext(Q4); + EXPECT_FALSE(DPCTLQueue_AreEq(Q1, Q2)); + EXPECT_NO_FATAL_FAILURE(DSRef = DPCTLDefaultSelector_Create()); + EXPECT_NO_FATAL_FAILURE(DRef = DPCTLDevice_CreateFromSelector(DSRef)); + EXPECT_NO_FATAL_FAILURE( + Q1 = DPCTLQueue_CreateForDevice(DRef, nullptr, DPCTL_DEFAULT_PROPERTY)); + EXPECT_FALSE(DPCTLQueue_AreEq(Q1, Q2)); + EXPECT_FALSE(DPCTLQueue_Hash(Q1) == DPCTLQueue_Hash(Q2)); - // All the queues should share the same context - EXPECT_TRUE(DPCTLContext_AreEq(C0, C1)); + EXPECT_NO_FATAL_FAILURE(DPCTLQueue_Delete(Q1)); + EXPECT_NO_FATAL_FAILURE(DPCTLDevice_Delete(DRef)); + EXPECT_NO_FATAL_FAILURE(DPCTLDeviceSelector_Delete(DSRef)); +} - DPCTLContext_Delete(C0); - DPCTLContext_Delete(C1); - DPCTLQueue_Delete(Q1); - DPCTLQueue_Delete(Q2); - DPCTLQueue_Delete(Q3); - DPCTLQueue_Delete(Q4); - DPCTLDeviceSelector_Delete(FSRef); - DPCTLDevice_Delete(DRef); +TEST(TestDPCTLSyclQueueInterface, CheckHash_Invalid) +{ + DPCTLSyclQueueRef Q1 = nullptr; + DPCTLSyclQueueRef Q2 = nullptr; + EXPECT_TRUE(DPCTLQueue_Hash(Q1) == 0); + EXPECT_TRUE(DPCTLQueue_Hash(Q2) == 0); } -TEST_F(TestDPCTLSyclQueueInterface, CheckAreEq2) +TEST(TestDPCTLSyclQueueInterface, CheckGetBackend_Invalid) { - auto FSRef = DPCTLFilterSelector_Create("opencl:gpu:0"); - auto DRef = DPCTLDevice_CreateFromSelector(FSRef); - auto FSRef2 = DPCTLFilterSelector_Create("opencl:cpu:0"); - auto DRef2 = DPCTLDevice_CreateFromSelector(FSRef2); + DPCTLSyclQueueRef Q = nullptr; + DPCTLSyclBackendType Bty = DPCTL_UNKNOWN_BACKEND; + EXPECT_NO_FATAL_FAILURE(Bty = DPCTLQueue_GetBackend(Q)); + EXPECT_TRUE(Bty == DPCTL_UNKNOWN_BACKEND); +} - if (!(DRef && DRef2)) { - DPCTLDeviceSelector_Delete(FSRef); - DPCTLDevice_Delete(DRef); - DPCTLDeviceSelector_Delete(FSRef2); - DPCTLDevice_Delete(DRef2); - GTEST_SKIP_("OpenCL GPUs and CPU not available.\n"); - } +TEST(TestDPCTLSyclQueueInterface, CheckGetContext_Invalid) +{ + DPCTLSyclQueueRef Q = nullptr; + DPCTLSyclContextRef CRef = nullptr; + EXPECT_NO_FATAL_FAILURE(CRef = DPCTLQueue_GetContext(Q)); + EXPECT_TRUE(CRef == nullptr); +} - auto GPU_Q = - DPCTLQueue_CreateForDevice(DRef, nullptr, DPCTL_DEFAULT_PROPERTY); - auto CPU_Q = - DPCTLQueue_CreateForDevice(DRef2, nullptr, DPCTL_DEFAULT_PROPERTY); +TEST(TestDPCTLSyclQueueInterface, CheckGetDevice_Invalid) +{ + DPCTLSyclQueueRef Q = nullptr; + DPCTLSyclDeviceRef DRef = nullptr; + EXPECT_NO_FATAL_FAILURE(DRef = DPCTLQueue_GetDevice(Q)); + EXPECT_TRUE(DRef == nullptr); +} - EXPECT_FALSE(DPCTLQueue_AreEq(GPU_Q, CPU_Q)); +TEST(TestDPCTLSyclQueueInterface, CheckIsInOrder) +{ + bool ioq = true; + DPCTLSyclDeviceSelectorRef DSRef = nullptr; + DPCTLSyclDeviceRef DRef = nullptr; + DPCTLSyclQueueRef Q1 = nullptr; + DPCTLSyclQueueRef Q2 = nullptr; + + EXPECT_NO_FATAL_FAILURE(DSRef = DPCTLDefaultSelector_Create()); + EXPECT_NO_FATAL_FAILURE(DRef = DPCTLDevice_CreateFromSelector(DSRef)); + EXPECT_NO_FATAL_FAILURE( + Q1 = DPCTLQueue_CreateForDevice(DRef, nullptr, DPCTL_DEFAULT_PROPERTY)); + EXPECT_NO_FATAL_FAILURE(ioq = DPCTLQueue_IsInOrder(Q1)); + EXPECT_FALSE(ioq); - DPCTLQueue_Delete(GPU_Q); - DPCTLQueue_Delete(CPU_Q); - DPCTLDeviceSelector_Delete(FSRef); - DPCTLDevice_Delete(DRef); - DPCTLDeviceSelector_Delete(FSRef2); - DPCTLDevice_Delete(DRef2); + EXPECT_NO_FATAL_FAILURE( + Q2 = DPCTLQueue_CreateForDevice(DRef, nullptr, DPCTL_IN_ORDER)); + EXPECT_NO_FATAL_FAILURE(ioq = DPCTLQueue_IsInOrder(Q2)); + EXPECT_TRUE(ioq); + + EXPECT_NO_FATAL_FAILURE(DPCTLQueue_Delete(Q1)); + EXPECT_NO_FATAL_FAILURE(DPCTLQueue_Delete(Q2)); + EXPECT_NO_FATAL_FAILURE(DPCTLDevice_Delete(DRef)); + EXPECT_NO_FATAL_FAILURE(DPCTLDeviceSelector_Delete(DSRef)); +} + +TEST(TestDPCTLSyclQueueInterface, CheckIsInOrder_Invalid) +{ + bool ioq = true; + DPCTLSyclQueueRef Q1 = nullptr; + EXPECT_NO_FATAL_FAILURE(ioq = DPCTLQueue_IsInOrder(Q1)); + EXPECT_FALSE(ioq); } TEST_P(TestDPCTLQueueMemberFunctions, CheckGetBackend) @@ -247,30 +274,14 @@ TEST_P(TestDPCTLQueueMemberFunctions, CheckGetContext) { auto Ctx = DPCTLQueue_GetContext(QRef); ASSERT_TRUE(Ctx != nullptr); - DPCTLContext_Delete(Ctx); + EXPECT_NO_FATAL_FAILURE(DPCTLContext_Delete(Ctx)); } TEST_P(TestDPCTLQueueMemberFunctions, CheckGetDevice) { auto D = DPCTLQueue_GetDevice(QRef); ASSERT_TRUE(D != nullptr); - DPCTLDevice_Delete(D); -} - -TEST_P(TestDPCTLQueueMemberFunctions, CheckIsInOrder) -{ - bool ioq = true; - - EXPECT_NO_FATAL_FAILURE(ioq = DPCTLQueue_IsInOrder(QRef)); - EXPECT_FALSE(ioq); - - DPCTLSyclQueueRef QRef_ioq = nullptr; - EXPECT_NO_FATAL_FAILURE( - QRef_ioq = DPCTLQueue_CreateForDevice(DRef, nullptr, DPCTL_IN_ORDER)); - EXPECT_TRUE(QRef_ioq); - EXPECT_NO_FATAL_FAILURE(ioq = DPCTLQueue_IsInOrder(QRef_ioq)); - EXPECT_TRUE(ioq); - EXPECT_NO_FATAL_FAILURE(DPCTLQueue_Delete(QRef_ioq)); + EXPECT_NO_FATAL_FAILURE(DPCTLDevice_Delete(D)); } INSTANTIATE_TEST_SUITE_P(DPCTLQueueMemberFuncTests, @@ -278,96 +289,3 @@ INSTANTIATE_TEST_SUITE_P(DPCTLQueueMemberFuncTests, ::testing::Values("opencl:gpu:0", "opencl:cpu:0", "level_zero:gpu:0")); - -TEST_F(TestDPCTLSyclQueueInterface, CheckSubmit) -{ - auto FSRef = DPCTLFilterSelector_Create("opencl:gpu:0"); - auto DRef = DPCTLDevice_CreateFromSelector(FSRef); - if (!DRef) { - DPCTLDeviceSelector_Delete(FSRef); - DPCTLDevice_Delete(DRef); - GTEST_SKIP_("Skipping: No OpenCL GPU device.\n"); - } - auto Queue = - DPCTLQueue_CreateForDevice(DRef, nullptr, DPCTL_DEFAULT_PROPERTY); - auto CtxRef = DPCTLQueue_GetContext(Queue); - auto PRef = - DPCTLProgram_CreateFromOCLSource(CtxRef, CLProgramStr, CompileOpts); - ASSERT_TRUE(PRef != nullptr); - ASSERT_TRUE(DPCTLProgram_HasKernel(PRef, "init_arr")); - ASSERT_TRUE(DPCTLProgram_HasKernel(PRef, "add")); - ASSERT_TRUE(DPCTLProgram_HasKernel(PRef, "axpy")); - - auto InitKernel = DPCTLProgram_GetKernel(PRef, "init_arr"); - auto AddKernel = DPCTLProgram_GetKernel(PRef, "add"); - auto AxpyKernel = DPCTLProgram_GetKernel(PRef, "axpy"); - - // Create the input args - auto a = DPCTLmalloc_shared(SIZE, Queue); - ASSERT_TRUE(a != nullptr); - auto b = DPCTLmalloc_shared(SIZE, Queue); - ASSERT_TRUE(b != nullptr); - auto c = DPCTLmalloc_shared(SIZE, Queue); - ASSERT_TRUE(c != nullptr); - - // Initialize a,b - DPCTLKernelArgType argTypes[] = {DPCTL_VOID_PTR}; - size_t Range[] = {SIZE}; - void *arg1[1] = {unwrap(a)}; - void *arg2[1] = {unwrap(b)}; - - auto E1 = DPCTLQueue_SubmitRange(InitKernel, Queue, arg1, argTypes, 1, - Range, 1, nullptr, 0); - auto E2 = DPCTLQueue_SubmitRange(InitKernel, Queue, arg2, argTypes, 1, - Range, 1, nullptr, 0); - ASSERT_TRUE(E1 != nullptr); - ASSERT_TRUE(E2 != nullptr); - - DPCTLQueue_Wait(Queue); - - // Submit the add kernel - void *args[3] = {unwrap(a), unwrap(b), unwrap(c)}; - DPCTLKernelArgType addKernelArgTypes[] = {DPCTL_VOID_PTR, DPCTL_VOID_PTR, - DPCTL_VOID_PTR}; - - auto E3 = DPCTLQueue_SubmitRange(AddKernel, Queue, args, addKernelArgTypes, - 3, Range, 1, nullptr, 0); - ASSERT_TRUE(E3 != nullptr); - DPCTLQueue_Wait(Queue); - - // Verify the result of "add" - add_kernel_checker((float *)a, (float *)b, (float *)c); - - // Create kernel args for axpy - float d = 10.0; - void *args2[4] = {unwrap(a), unwrap(b), unwrap(c), (void *)&d}; - DPCTLKernelArgType addKernelArgTypes2[] = {DPCTL_VOID_PTR, DPCTL_VOID_PTR, - DPCTL_VOID_PTR, DPCTL_FLOAT}; - auto E4 = DPCTLQueue_SubmitRange( - AxpyKernel, Queue, args2, addKernelArgTypes2, 4, Range, 1, nullptr, 0); - ASSERT_TRUE(E4 != nullptr); - DPCTLQueue_Wait(Queue); - - // Verify the result of "axpy" - axpy_kernel_checker((float *)a, (float *)b, (float *)c, d); - - // clean ups - DPCTLEvent_Delete(E1); - DPCTLEvent_Delete(E2); - DPCTLEvent_Delete(E3); - DPCTLEvent_Delete(E4); - - DPCTLKernel_Delete(AddKernel); - DPCTLKernel_Delete(AxpyKernel); - DPCTLKernel_Delete(InitKernel); - - DPCTLfree_with_queue((DPCTLSyclUSMRef)a, Queue); - DPCTLfree_with_queue((DPCTLSyclUSMRef)b, Queue); - DPCTLfree_with_queue((DPCTLSyclUSMRef)c, Queue); - - DPCTLQueue_Delete(Queue); - DPCTLContext_Delete(CtxRef); - DPCTLProgram_Delete(PRef); - DPCTLDeviceSelector_Delete(FSRef); - DPCTLDevice_Delete(DRef); -} diff --git a/dpctl-capi/tests/test_sycl_queue_submit.cpp b/dpctl-capi/tests/test_sycl_queue_submit.cpp new file mode 100644 index 0000000000..c94089aeef --- /dev/null +++ b/dpctl-capi/tests/test_sycl_queue_submit.cpp @@ -0,0 +1,125 @@ +//===-- test_sycl_queue_submit.cpp - Test cases for kernel submission fns. ===// +// +// Data Parallel Control (dpctl) +// +// Copyright 2020-2021 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file has unit test cases for the various submit functions defined +/// inside dpctl_sycl_queue_interface.cpp. +//===----------------------------------------------------------------------===// + +#include "Support/CBindingWrapping.h" +#include "dpctl_sycl_context_interface.h" +#include "dpctl_sycl_device_interface.h" +#include "dpctl_sycl_device_selector_interface.h" +#include "dpctl_sycl_event_interface.h" +#include "dpctl_sycl_kernel_interface.h" +#include "dpctl_sycl_program_interface.h" +#include "dpctl_sycl_queue_interface.h" +#include "dpctl_sycl_usm_interface.h" +#include +#include +#include +#include + +namespace +{ +constexpr size_t SIZE = 1024; +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(void, DPCTLSyclUSMRef); +} /* end of anonymous namespace */ + +struct TestQueueSubmit : public ::testing::Test +{ + std::ifstream spirvFile; + size_t spirvFileSize; + std::vector spirvBuffer; + + TestQueueSubmit() + { + spirvFile.open("./multi_kernel.spv", std::ios::binary | std::ios::ate); + spirvFileSize = std::filesystem::file_size("./multi_kernel.spv"); + spirvBuffer.reserve(spirvFileSize); + spirvFile.seekg(0, std::ios::beg); + spirvFile.read(spirvBuffer.data(), spirvFileSize); + } + + ~TestQueueSubmit() + { + spirvFile.close(); + } +}; + +TEST_F(TestQueueSubmit, CheckSubmitRange_saxpy) +{ + DPCTLSyclDeviceSelectorRef DSRef = nullptr; + DPCTLSyclDeviceRef DRef = nullptr; + + EXPECT_NO_FATAL_FAILURE(DSRef = DPCTLDefaultSelector_Create()); + EXPECT_NO_FATAL_FAILURE(DRef = DPCTLDevice_CreateFromSelector(DSRef)); + DPCTLDeviceMgr_PrintDeviceInfo(DRef); + ASSERT_TRUE(DRef); + auto QRef = + DPCTLQueue_CreateForDevice(DRef, nullptr, DPCTL_DEFAULT_PROPERTY); + ASSERT_TRUE(QRef); + auto CRef = DPCTLQueue_GetContext(QRef); + ASSERT_TRUE(CRef); + auto PRef = DPCTLProgram_CreateFromSpirv(CRef, spirvBuffer.data(), + spirvFileSize, nullptr); + ASSERT_TRUE(PRef != nullptr); + ASSERT_TRUE(DPCTLProgram_HasKernel(PRef, "axpy")); + auto AxpyKernel = DPCTLProgram_GetKernel(PRef, "axpy"); + + // Create the input args + auto a = DPCTLmalloc_shared(SIZE * sizeof(float), QRef); + ASSERT_TRUE(a != nullptr); + auto b = DPCTLmalloc_shared(SIZE * sizeof(float), QRef); + ASSERT_TRUE(b != nullptr); + auto c = DPCTLmalloc_shared(SIZE * sizeof(float), QRef); + ASSERT_TRUE(c != nullptr); + + auto a_ptr = reinterpret_cast(unwrap(a)); + auto b_ptr = reinterpret_cast(unwrap(b)); + // Initialize a,b + for (auto i = 0ul; i < SIZE; ++i) { + a_ptr[i] = i + 1.0; + b_ptr[i] = i + 2.0; + } + + // Create kernel args for axpy + float d = 10.0; + size_t Range[] = {SIZE}; + void *args2[4] = {unwrap(a), unwrap(b), unwrap(c), (void *)&d}; + DPCTLKernelArgType addKernelArgTypes[] = {DPCTL_VOID_PTR, DPCTL_VOID_PTR, + DPCTL_VOID_PTR, DPCTL_FLOAT}; + auto ERef = DPCTLQueue_SubmitRange( + AxpyKernel, QRef, args2, addKernelArgTypes, 4, Range, 1, nullptr, 0); + ASSERT_TRUE(ERef != nullptr); + DPCTLQueue_Wait(QRef); + + // clean ups + DPCTLEvent_Delete(ERef); + DPCTLKernel_Delete(AxpyKernel); + DPCTLfree_with_queue((DPCTLSyclUSMRef)a, QRef); + DPCTLfree_with_queue((DPCTLSyclUSMRef)b, QRef); + DPCTLfree_with_queue((DPCTLSyclUSMRef)c, QRef); + DPCTLQueue_Delete(QRef); + DPCTLContext_Delete(CRef); + DPCTLProgram_Delete(PRef); + DPCTLDevice_Delete(DRef); + DPCTLDeviceSelector_Delete(DSRef); +}