From ad8579bf61f86788585a06f4fb8800268ab4dd0f Mon Sep 17 00:00:00 2001 From: Michael Aziz Date: Sun, 6 Oct 2024 19:52:45 -0700 Subject: [PATCH 1/2] Implement tests for `sycl_ext_oneapi_local_memory` extension Signed-off-by: Michael Aziz --- CMakeLists.txt | 4 + .../oneapi_local_memory/CMakeLists.txt | 5 + .../oneapi_local_memory/local_memory.cpp | 256 ++++++++++++++++++ 3 files changed, 265 insertions(+) create mode 100644 tests/extension/oneapi_local_memory/CMakeLists.txt create mode 100644 tests/extension/oneapi_local_memory/local_memory.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 971c6c10c..752d5dbe4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,6 +103,10 @@ add_cts_option(SYCL_CTS_ENABLE_EXT_ONEAPI_ENQUEUE_FUNCTIONS_TESTS "Enable extension oneAPI enqueue_functions tests" OFF FORCE_ON ${SYCL_CTS_ENABLE_EXT_ONEAPI_TESTS}) +add_cts_option(SYCL_CTS_ENABLE_EXT_ONEAPI_LOCAL_MEMORY_TESTS + "Enable extension oneAPI local_memory tests" OFF + FORCE_ON ${SYCL_CTS_ENABLE_EXT_ONEAPI_TESTS}) + # TODO: Deprecated - remove add_cts_option(SYCL_CTS_ENABLE_VERBOSE_LOG "Enable debug-level logs (deprecated)" OFF) diff --git a/tests/extension/oneapi_local_memory/CMakeLists.txt b/tests/extension/oneapi_local_memory/CMakeLists.txt new file mode 100644 index 000000000..b7c0ecaae --- /dev/null +++ b/tests/extension/oneapi_local_memory/CMakeLists.txt @@ -0,0 +1,5 @@ +if(SYCL_CTS_ENABLE_EXT_ONEAPI_LOCAL_MEMORY_TESTS) + file(GLOB test_cases_list *.cpp) + + add_cts_test(${test_cases_list}) +endif() diff --git a/tests/extension/oneapi_local_memory/local_memory.cpp b/tests/extension/oneapi_local_memory/local_memory.cpp new file mode 100644 index 000000000..7f9277e3b --- /dev/null +++ b/tests/extension/oneapi_local_memory/local_memory.cpp @@ -0,0 +1,256 @@ +/******************************************************************************* +// +// SYCL 2020 Conformance Test Suite +// +// Copyright (c) 2024 The Khronos Group Inc. +// +// 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. +// +*******************************************************************************/ + +#include "../../common/common.h" + +namespace local_memory::tests { + +#ifdef SYCL_EXT_ONEAPI_LOCAL_MEMORY + +struct Point3D { + int x; + int y; + int z; + Point3D() : x{0}, y{0}, z{0} {} + Point3D(int x) : x{x}, y{0}, z{0} {} + Point3D(int x, int y) : x{x}, y{y}, z{0} {} + Point3D(int x, int y, int z) : x{x}, y{y}, z{z} {} +}; + +static bool operator==(const Point3D& a, const Point3D& b) { + return (a.x == b.x) && (a.y == b.y) && (a.z == b.z); +} + +template +static bool checkInitialValue(const T& value, Args&&... args) { + const T reference(std::forward(args)...); + return (value == reference); +} + +template +static bool checkInitialValue(const T (&value)[N], Args&&... args) { + const T reference[N]{std::forward(args)...}; + for (int i = 0; i < N; i++) + if (value[i] != reference[i]) return false; + return true; +} + +template +static void runTestKernel(const F& kernel) { + sycl::queue q; + bool* passed = sycl::malloc_shared(GlobalSize, q); + q.parallel_for(sycl::nd_range<1>(GlobalSize, LocalSize), + [=](sycl::nd_item<1> item) { kernel(item, passed); }) + .wait(); + for (int i = 0; i < GlobalSize; i++) CHECK(passed[i]); + sycl::free(passed, q); +} + +template +static void testInitialValue(Args&&... args) { + runTestKernel([=](sycl::nd_item<1> item, bool* passed) { + auto ptr = + sycl::ext::oneapi::group_local_memory(item.get_group(), args...); + static_assert( + std::is_same_v< + decltype(ptr), + sycl::multi_ptr>, + "group_local_memory returns the wrong type"); + passed[item.get_global_id()] = checkInitialValue(*ptr, args...); + }); +} + +template +static void testInitialValueForOverwrite() { + runTestKernel([=](sycl::nd_item<1> item, bool* passed) { + auto ptr = sycl::ext::oneapi::group_local_memory_for_overwrite( + item.get_group()); + static_assert( + std::is_same_v< + decltype(ptr), + sycl::multi_ptr>, + "group_local_memory_for_overwrite returns the wrong type"); + passed[item.get_global_id()] = + (std::is_same_v ? checkInitialValue(*ptr) : true); + }); +} + +template +static void testDifferentInitialValues(Args&&... args) { + runTestKernel([=](sycl::nd_item<1> item, bool* passed) { + const int factor = static_cast(item.get_group_linear_id()); + auto ptr = sycl::ext::oneapi::group_local_memory( + item.get_group(), (static_cast(args * factor))...); + passed[item.get_global_id()] = checkInitialValue(*ptr, (args * factor)...); + }); +} + +template +static void testArrayInitializationWithFewArguments(Args&&... args) { + runTestKernel([=](sycl::nd_item<1> item, bool* passed) { + constexpr size_t M = sizeof...(args); + static_assert( + M < N, + "Array must be initialized with fewer arguments than its length"); + auto ptr = + sycl::ext::oneapi::group_local_memory(item.get_group(), args...); + passed[item.get_global_id()] = checkInitialValue(*ptr, args...); + }); +} + +template +static void testLocalMemoryAvailability() { + constexpr size_t N = 10; + const auto kernel = [=](sycl::nd_item<1> item, bool* passed) { + auto ptr = sycl::ext::oneapi::group_local_memory(item.get_group()); + T(&array)[N] = *ptr; + array[(N - 1) - item.get_local_linear_id()] = item.get_local_linear_id(); + sycl::group_barrier(item.get_group()); + passed[item.get_global_id()] = + (array[item.get_local_linear_id()] == + static_cast((N - 1) - item.get_local_linear_id())); + }; + runTestKernel(kernel); +} + +template +static void testLocalMemoryForOverwriteAvailability() { + constexpr size_t N = 10; + const auto kernel = [=](sycl::nd_item<1> item, bool* passed) { + auto ptr = sycl::ext::oneapi::group_local_memory_for_overwrite( + item.get_group()); + T(&array)[N] = *ptr; + array[(N - 1) - item.get_local_linear_id()] = item.get_local_linear_id(); + sycl::group_barrier(item.get_group()); + passed[item.get_global_id()] = + (array[item.get_local_linear_id()] == + static_cast((N - 1) - item.get_local_linear_id())); + }; + runTestKernel(kernel); +} + +#endif + +TEST_CASE("Test case for \"Local Memory\" extension", "[oneapi_local_memory") { +#ifndef SYCL_EXT_ONEAPI_LOCAL_MEMORY + SKIP("SYCL_EXT_ONEAPI_LOCAL_MEMORY is not defined"); +#else + testInitialValue(2); + testInitialValue(1.5f); + testInitialValue(5); + testInitialValue(5, 7); + testInitialValue(5, 7, 13); + testInitialValue(1, -2, 3, -4, 5); +#ifdef SYCL_CTS_ENABLE_FULL_CONFORMANCE + testInitialValue(true); + testInitialValue('A'); + testInitialValue('A'); + testInitialValue('A'); + testInitialValue(17); + testInitialValue(19); + testInitialValue(23); + testInitialValue(29); + testInitialValue(31); + testInitialValue(37); + testInitialValue(43); + testInitialValue(3.14); +#endif + + testInitialValueForOverwrite(); + testInitialValueForOverwrite(); + testInitialValueForOverwrite(); + testInitialValueForOverwrite(); +#ifdef SYCL_CTS_ENABLE_FULL_CONFORMANCE + testInitialValueForOverwrite(); + testInitialValueForOverwrite(); + testInitialValueForOverwrite(); + testInitialValueForOverwrite(); + testInitialValueForOverwrite(); + testInitialValueForOverwrite(); + testInitialValueForOverwrite(); + testInitialValueForOverwrite(); + testInitialValueForOverwrite(); + testInitialValueForOverwrite(); + testInitialValueForOverwrite(); + testInitialValueForOverwrite(); +#endif + + testDifferentInitialValues(2); + testDifferentInitialValues(1.5f); + testDifferentInitialValues(5); + testDifferentInitialValues(5, 7); + testDifferentInitialValues(5, 7, 13); + testDifferentInitialValues(1, -2, 3, -4, 5); +#ifdef SYCL_CTS_ENABLE_FULL_CONFORMANCE + testDifferentInitialValues(true); + testDifferentInitialValues('A'); + testDifferentInitialValues('A'); + testDifferentInitialValues('A'); + testDifferentInitialValues(17); + testDifferentInitialValues(19); + testDifferentInitialValues(23); + testDifferentInitialValues(29); + testDifferentInitialValues(31); + testDifferentInitialValues(37); + testDifferentInitialValues(43); + testDifferentInitialValues(3.14); +#endif + + testLocalMemoryAvailability(); + testLocalMemoryAvailability(); + testLocalMemoryAvailability(); +#ifdef SYCL_CTS_ENABLE_FULL_CONFORMANCE + testLocalMemoryAvailability(); + testLocalMemoryAvailability(); + testLocalMemoryAvailability(); + testLocalMemoryAvailability(); + testLocalMemoryAvailability(); + testLocalMemoryAvailability(); + testLocalMemoryAvailability(); + testLocalMemoryAvailability(); + testLocalMemoryAvailability(); + testLocalMemoryAvailability(); + testLocalMemoryAvailability(); + testLocalMemoryAvailability(); +#endif + + testLocalMemoryForOverwriteAvailability(); + testLocalMemoryForOverwriteAvailability(); + testLocalMemoryForOverwriteAvailability(); +#ifdef SYCL_CTS_ENABLE_FULL_CONFORMANCE + testLocalMemoryForOverwriteAvailability(); + testLocalMemoryForOverwriteAvailability(); + testLocalMemoryForOverwriteAvailability(); + testLocalMemoryForOverwriteAvailability(); + testLocalMemoryForOverwriteAvailability(); + testLocalMemoryForOverwriteAvailability(); + testLocalMemoryForOverwriteAvailability(); + testLocalMemoryForOverwriteAvailability(); + testLocalMemoryForOverwriteAvailability(); + testLocalMemoryForOverwriteAvailability(); + testLocalMemoryForOverwriteAvailability(); + testLocalMemoryForOverwriteAvailability(); +#endif + + testArrayInitializationWithFewArguments(1, -2, 3, -4); +#endif +} + +} // namespace local_memory::tests From b0dc946e632587b4125ddfd5a6cef0df6acc360f Mon Sep 17 00:00:00 2001 From: Michael Aziz Date: Thu, 5 Dec 2024 12:23:26 -0800 Subject: [PATCH 2/2] Address review comments Signed-off-by: Michael Aziz --- tests/extension/oneapi_local_memory/local_memory.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/tests/extension/oneapi_local_memory/local_memory.cpp b/tests/extension/oneapi_local_memory/local_memory.cpp index 7f9277e3b..f4c664c0f 100644 --- a/tests/extension/oneapi_local_memory/local_memory.cpp +++ b/tests/extension/oneapi_local_memory/local_memory.cpp @@ -28,10 +28,7 @@ struct Point3D { int x; int y; int z; - Point3D() : x{0}, y{0}, z{0} {} - Point3D(int x) : x{x}, y{0}, z{0} {} - Point3D(int x, int y) : x{x}, y{y}, z{0} {} - Point3D(int x, int y, int z) : x{x}, y{y}, z{z} {} + Point3D(int x = 1, int y = -2, int z = 3) : x{x}, y{y}, z{z} {} }; static bool operator==(const Point3D& a, const Point3D& b) { @@ -119,8 +116,7 @@ template static void testLocalMemoryAvailability() { constexpr size_t N = 10; const auto kernel = [=](sycl::nd_item<1> item, bool* passed) { - auto ptr = sycl::ext::oneapi::group_local_memory(item.get_group()); - T(&array)[N] = *ptr; + auto array = *sycl::ext::oneapi::group_local_memory(item.get_group()); array[(N - 1) - item.get_local_linear_id()] = item.get_local_linear_id(); sycl::group_barrier(item.get_group()); passed[item.get_global_id()] = @@ -134,9 +130,8 @@ template static void testLocalMemoryForOverwriteAvailability() { constexpr size_t N = 10; const auto kernel = [=](sycl::nd_item<1> item, bool* passed) { - auto ptr = sycl::ext::oneapi::group_local_memory_for_overwrite( + auto array = *sycl::ext::oneapi::group_local_memory_for_overwrite( item.get_group()); - T(&array)[N] = *ptr; array[(N - 1) - item.get_local_linear_id()] = item.get_local_linear_id(); sycl::group_barrier(item.get_group()); passed[item.get_global_id()] =