From c74b13aa7505cad00edf6a344c32c5ba51e8e560 Mon Sep 17 00:00:00 2001 From: Justin Lebar Date: Fri, 9 Sep 2016 21:01:02 +0000 Subject: [StreamExecutor] Make SE work with an in-tree LLVM build. Summary: With these changes, we can put parallel-libs within llvm/projects and build as normal. This is kind of the minimal change I could figure out how to make while still making us compatible with llvm's build system. Some things I'm not thrilled about include: * The creation of a CoreTests directory (the macros really seemed to want this) * Pulling SimpleHostPlatformDevice.h into CoreTests. It seems to me this should live inside unittests/include, or maybe tests/include, but I didn't want to make that change in this patch. One important piece of work that remains to be done is to make $ ninja check-streamexecutor run all the tests. Right now the only way I've figured out to run the tests is $ ninja projects/parallel-libs/streamexecutor/unittests/StreamExecutorUnitTests $ projects/parallel-libs/streamexecutor/unittests/CoreTests/CoreTests Reviewers: jhen Subscribers: beanz, parallel_libs-commits, jprice Differential Revision: https://reviews.llvm.org/D24368 --- parallel-libs/CMakeLists.txt | 3 + parallel-libs/streamexecutor/CMakeLists.txt | 14 +- parallel-libs/streamexecutor/lib/CMakeLists.txt | 24 +- .../streamexecutor/lib/Utils/CMakeLists.txt | 3 + .../streamexecutor/lib/unittests/CMakeLists.txt | 41 -- .../streamexecutor/lib/unittests/DeviceTest.cpp | 414 --------------------- .../lib/unittests/KernelSpecTest.cpp | 132 ------- .../unittests/PackedKernelArgumentArrayTest.cpp | 150 -------- .../lib/unittests/SimpleHostPlatformDevice.h | 148 -------- .../streamexecutor/lib/unittests/StreamTest.cpp | 362 ------------------ .../streamexecutor/unittests/CMakeLists.txt | 9 + .../unittests/CoreTests/CMakeLists.txt | 7 + .../unittests/CoreTests/DeviceTest.cpp | 414 +++++++++++++++++++++ .../unittests/CoreTests/KernelSpecTest.cpp | 132 +++++++ .../CoreTests/PackedKernelArgumentArrayTest.cpp | 150 ++++++++ .../unittests/CoreTests/SimpleHostPlatformDevice.h | 148 ++++++++ .../unittests/CoreTests/StreamTest.cpp | 362 ++++++++++++++++++ 17 files changed, 1251 insertions(+), 1262 deletions(-) create mode 100644 parallel-libs/CMakeLists.txt create mode 100644 parallel-libs/streamexecutor/lib/Utils/CMakeLists.txt delete mode 100644 parallel-libs/streamexecutor/lib/unittests/CMakeLists.txt delete mode 100644 parallel-libs/streamexecutor/lib/unittests/DeviceTest.cpp delete mode 100644 parallel-libs/streamexecutor/lib/unittests/KernelSpecTest.cpp delete mode 100644 parallel-libs/streamexecutor/lib/unittests/PackedKernelArgumentArrayTest.cpp delete mode 100644 parallel-libs/streamexecutor/lib/unittests/SimpleHostPlatformDevice.h delete mode 100644 parallel-libs/streamexecutor/lib/unittests/StreamTest.cpp create mode 100644 parallel-libs/streamexecutor/unittests/CMakeLists.txt create mode 100644 parallel-libs/streamexecutor/unittests/CoreTests/CMakeLists.txt create mode 100644 parallel-libs/streamexecutor/unittests/CoreTests/DeviceTest.cpp create mode 100644 parallel-libs/streamexecutor/unittests/CoreTests/KernelSpecTest.cpp create mode 100644 parallel-libs/streamexecutor/unittests/CoreTests/PackedKernelArgumentArrayTest.cpp create mode 100644 parallel-libs/streamexecutor/unittests/CoreTests/SimpleHostPlatformDevice.h create mode 100644 parallel-libs/streamexecutor/unittests/CoreTests/StreamTest.cpp (limited to 'parallel-libs') diff --git a/parallel-libs/CMakeLists.txt b/parallel-libs/CMakeLists.txt new file mode 100644 index 00000000000..e96b2e4a479 --- /dev/null +++ b/parallel-libs/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.1) + +add_subdirectory(streamexecutor) diff --git a/parallel-libs/streamexecutor/CMakeLists.txt b/parallel-libs/streamexecutor/CMakeLists.txt index fde628f75a1..c2901045a6c 100644 --- a/parallel-libs/streamexecutor/CMakeLists.txt +++ b/parallel-libs/streamexecutor/CMakeLists.txt @@ -38,9 +38,9 @@ if(STREAM_EXECUTOR_STANDALONE) OUTPUT_STRIP_TRAILING_WHITESPACE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LLVM_CXXFLAGS}") - # Find the libraries that correspond to the LLVM components - # that we wish to use - llvm_map_components_to_libnames(llvm_libs support symbolize) + set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm") + list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}") + include(AddLLVM) if(STREAM_EXECUTOR_UNIT_TESTS) enable_testing() @@ -55,6 +55,10 @@ else(NOT STREAM_EXECUTOR_STANDALONE) endif() endif(STREAM_EXECUTOR_STANDALONE) +# Find the libraries that correspond to the LLVM components +# that we wish to use +llvm_map_components_to_libnames(llvm_libs support symbolize) + # Insist on C++ 11 features. set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -65,6 +69,10 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter") add_subdirectory(lib) add_subdirectory(examples) +if(STREAM_EXECUTOR_UNIT_TESTS) + add_subdirectory(unittests) +endif() + if(STREAM_EXECUTOR_ENABLE_CONFIG_TOOL ) add_subdirectory(tools/streamexecutor-config) endif(STREAM_EXECUTOR_ENABLE_CONFIG_TOOL ) diff --git a/parallel-libs/streamexecutor/lib/CMakeLists.txt b/parallel-libs/streamexecutor/lib/CMakeLists.txt index 8c3ac025168..11873c42390 100644 --- a/parallel-libs/streamexecutor/lib/CMakeLists.txt +++ b/parallel-libs/streamexecutor/lib/CMakeLists.txt @@ -1,11 +1,12 @@ -add_library( - utils - OBJECT - Utils/Error.cpp) +macro(add_se_library name) + add_llvm_library(${name} ${ARGN}) + set_target_properties(${name} PROPERTIES FOLDER "streamexecutor libraries") +endmacro(add_se_library) -add_library( +add_subdirectory(Utils) + +add_se_library( streamexecutor - $ Device.cpp DeviceMemory.cpp Kernel.cpp @@ -14,11 +15,10 @@ add_library( Platform.cpp PlatformDevice.cpp PlatformManager.cpp - Stream.cpp) -target_link_libraries(streamexecutor ${llvm_libs}) + Stream.cpp -install(TARGETS streamexecutor DESTINATION lib) + LINK_LIBS + utils + ) -if(STREAM_EXECUTOR_UNIT_TESTS) - add_subdirectory(unittests) -endif() +install(TARGETS streamexecutor DESTINATION lib) diff --git a/parallel-libs/streamexecutor/lib/Utils/CMakeLists.txt b/parallel-libs/streamexecutor/lib/Utils/CMakeLists.txt new file mode 100644 index 00000000000..2cbbc3b170f --- /dev/null +++ b/parallel-libs/streamexecutor/lib/Utils/CMakeLists.txt @@ -0,0 +1,3 @@ +add_se_library( + utils + Error.cpp) diff --git a/parallel-libs/streamexecutor/lib/unittests/CMakeLists.txt b/parallel-libs/streamexecutor/lib/unittests/CMakeLists.txt deleted file mode 100644 index e12b675f2c4..00000000000 --- a/parallel-libs/streamexecutor/lib/unittests/CMakeLists.txt +++ /dev/null @@ -1,41 +0,0 @@ -add_executable( - device_test - DeviceTest.cpp) -target_link_libraries( - device_test - streamexecutor - ${GTEST_BOTH_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT}) -add_test(DeviceTest device_test) - -add_executable( - kernel_spec_test - KernelSpecTest.cpp) -target_link_libraries( - kernel_spec_test - streamexecutor - ${GTEST_BOTH_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT}) -add_test(KernelSpecTest kernel_spec_test) - -add_executable( - packed_kernel_argument_array_test - PackedKernelArgumentArrayTest.cpp) -target_link_libraries( - packed_kernel_argument_array_test - streamexecutor - ${llvm_libs} - ${GTEST_BOTH_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT}) -add_test(PackedKernelArgumentArrayTest packed_kernel_argument_array_test) - -add_executable( - stream_test - StreamTest.cpp) -target_link_libraries( - stream_test - streamexecutor - ${llvm_libs} - ${GTEST_BOTH_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT}) -add_test(StreamTest stream_test) diff --git a/parallel-libs/streamexecutor/lib/unittests/DeviceTest.cpp b/parallel-libs/streamexecutor/lib/unittests/DeviceTest.cpp deleted file mode 100644 index 5b16c3c865c..00000000000 --- a/parallel-libs/streamexecutor/lib/unittests/DeviceTest.cpp +++ /dev/null @@ -1,414 +0,0 @@ -//===-- DeviceTest.cpp - Tests for Device ---------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This file contains the unit tests for Device code. -/// -//===----------------------------------------------------------------------===// - -#include -#include - -#include "SimpleHostPlatformDevice.h" -#include "streamexecutor/Device.h" -#include "streamexecutor/PlatformDevice.h" - -#include "gtest/gtest.h" - -namespace { - -namespace se = ::streamexecutor; - -const auto &getDeviceValue = - se::test::SimpleHostPlatformDevice::getDeviceValue; - -/// Test fixture to hold objects used by tests. -class DeviceTest : public ::testing::Test { -public: - DeviceTest() - : Device(&PDevice), HostA5{0, 1, 2, 3, 4}, HostB5{5, 6, 7, 8, 9}, - HostA7{10, 11, 12, 13, 14, 15, 16}, HostB7{17, 18, 19, 20, 21, 22, 23}, - DeviceA5(getOrDie(Device.allocateDeviceMemory(5))), - DeviceB5(getOrDie(Device.allocateDeviceMemory(5))), - DeviceA7(getOrDie(Device.allocateDeviceMemory(7))), - DeviceB7(getOrDie(Device.allocateDeviceMemory(7))), - Host5{24, 25, 26, 27, 28}, Host7{29, 30, 31, 32, 33, 34, 35} { - se::dieIfError(Device.synchronousCopyH2D(HostA5, DeviceA5)); - se::dieIfError(Device.synchronousCopyH2D(HostB5, DeviceB5)); - se::dieIfError(Device.synchronousCopyH2D(HostA7, DeviceA7)); - se::dieIfError(Device.synchronousCopyH2D(HostB7, DeviceB7)); - } - - se::test::SimpleHostPlatformDevice PDevice; - se::Device Device; - - // Device memory is backed by host arrays. - int HostA5[5]; - int HostB5[5]; - int HostA7[7]; - int HostB7[7]; - se::GlobalDeviceMemory DeviceA5; - se::GlobalDeviceMemory DeviceB5; - se::GlobalDeviceMemory DeviceA7; - se::GlobalDeviceMemory DeviceB7; - - // Host memory to be used as actual host memory. - int Host5[5]; - int Host7[7]; -}; - -#define EXPECT_NO_ERROR(E) EXPECT_FALSE(static_cast(E)) -#define EXPECT_ERROR(E) \ - do { \ - se::Error E__ = E; \ - EXPECT_TRUE(static_cast(E__)); \ - consumeError(std::move(E__)); \ - } while (false) - -using llvm::ArrayRef; -using llvm::MutableArrayRef; - -TEST_F(DeviceTest, GetName) { - EXPECT_EQ(Device.getName(), "SimpleHostPlatformDevice"); -} - -TEST_F(DeviceTest, AllocateAndFreeDeviceMemory) { - se::Expected> MaybeMemory = - Device.allocateDeviceMemory(10); - EXPECT_TRUE(static_cast(MaybeMemory)); -} - -TEST_F(DeviceTest, AllocateAndFreeHostMemory) { - se::Expected MaybeMemory = Device.allocateHostMemory(10); - EXPECT_TRUE(static_cast(MaybeMemory)); - EXPECT_NO_ERROR(Device.freeHostMemory(*MaybeMemory)); -} - -TEST_F(DeviceTest, RegisterAndUnregisterHostMemory) { - std::vector Data(10); - EXPECT_NO_ERROR(Device.registerHostMemory(Data.data(), 10)); - EXPECT_NO_ERROR(Device.unregisterHostMemory(Data.data())); -} - -// D2H tests - -TEST_F(DeviceTest, SyncCopyD2HToMutableArrayRefByCount) { - EXPECT_NO_ERROR( - Device.synchronousCopyD2H(DeviceA5, MutableArrayRef(Host5), 5)); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(HostA5[I], Host5[I]); - } - - EXPECT_NO_ERROR( - Device.synchronousCopyD2H(DeviceB5, MutableArrayRef(Host5), 2)); - for (int I = 0; I < 2; ++I) { - EXPECT_EQ(HostB5[I], Host5[I]); - } - - EXPECT_ERROR( - Device.synchronousCopyD2H(DeviceA7, MutableArrayRef(Host5), 7)); - - EXPECT_ERROR( - Device.synchronousCopyD2H(DeviceA5, MutableArrayRef(Host7), 7)); - - EXPECT_ERROR( - Device.synchronousCopyD2H(DeviceA5, MutableArrayRef(Host5), 7)); -} - -TEST_F(DeviceTest, SyncCopyD2HToMutableArrayRef) { - EXPECT_NO_ERROR( - Device.synchronousCopyD2H(DeviceA5, MutableArrayRef(Host5))); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(HostA5[I], Host5[I]); - } - - EXPECT_ERROR( - Device.synchronousCopyD2H(DeviceA7, MutableArrayRef(Host5))); - - EXPECT_ERROR( - Device.synchronousCopyD2H(DeviceA5, MutableArrayRef(Host7))); -} - -TEST_F(DeviceTest, SyncCopyD2HToPointer) { - EXPECT_NO_ERROR(Device.synchronousCopyD2H(DeviceA5, Host5, 5)); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(HostA5[I], Host5[I]); - } - - EXPECT_ERROR(Device.synchronousCopyD2H(DeviceA5, Host7, 7)); -} - -TEST_F(DeviceTest, SyncCopyD2HSliceToMutableArrayRefByCount) { - EXPECT_NO_ERROR(Device.synchronousCopyD2H( - DeviceA5.asSlice().drop_front(1), MutableArrayRef(Host5 + 1, 4), 4)); - for (int I = 1; I < 5; ++I) { - EXPECT_EQ(HostA5[I], Host5[I]); - } - - EXPECT_NO_ERROR(Device.synchronousCopyD2H(DeviceB5.asSlice().drop_back(1), - MutableArrayRef(Host5), 2)); - for (int I = 0; I < 2; ++I) { - EXPECT_EQ(HostB5[I], Host5[I]); - } - - EXPECT_ERROR(Device.synchronousCopyD2H(DeviceA7.asSlice(), - MutableArrayRef(Host5), 7)); - - EXPECT_ERROR(Device.synchronousCopyD2H(DeviceA5.asSlice(), - MutableArrayRef(Host7), 7)); - - EXPECT_ERROR(Device.synchronousCopyD2H(DeviceA5.asSlice(), - MutableArrayRef(Host5), 7)); -} - -TEST_F(DeviceTest, SyncCopyD2HSliceToMutableArrayRef) { - EXPECT_NO_ERROR(Device.synchronousCopyD2H(DeviceA7.asSlice().slice(1, 5), - MutableArrayRef(Host5))); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(HostA7[I + 1], Host5[I]); - } - - EXPECT_ERROR(Device.synchronousCopyD2H(DeviceA7.asSlice().drop_back(1), - MutableArrayRef(Host5))); - - EXPECT_ERROR(Device.synchronousCopyD2H(DeviceA5.asSlice(), - MutableArrayRef(Host7))); -} - -TEST_F(DeviceTest, SyncCopyD2HSliceToPointer) { - EXPECT_NO_ERROR(Device.synchronousCopyD2H(DeviceA5.asSlice().drop_front(1), - Host5 + 1, 4)); - for (int I = 1; I < 5; ++I) { - EXPECT_EQ(HostA5[I], Host5[I]); - } - - EXPECT_ERROR(Device.synchronousCopyD2H(DeviceA5.asSlice(), Host7, 7)); -} - -// H2D tests - -TEST_F(DeviceTest, SyncCopyH2DToArrayRefByCount) { - EXPECT_NO_ERROR(Device.synchronousCopyH2D(ArrayRef(Host5), DeviceA5, 5)); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); - } - - EXPECT_NO_ERROR(Device.synchronousCopyH2D(ArrayRef(Host5), DeviceB5, 2)); - for (int I = 0; I < 2; ++I) { - EXPECT_EQ(getDeviceValue(DeviceB5, I), Host5[I]); - } - - EXPECT_ERROR(Device.synchronousCopyH2D(ArrayRef(Host7), DeviceA5, 7)); - - EXPECT_ERROR(Device.synchronousCopyH2D(ArrayRef(Host5), DeviceA7, 7)); - - EXPECT_ERROR(Device.synchronousCopyH2D(ArrayRef(Host5), DeviceA5, 7)); -} - -TEST_F(DeviceTest, SyncCopyH2DToArrayRef) { - EXPECT_NO_ERROR(Device.synchronousCopyH2D(ArrayRef(Host5), DeviceA5)); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); - } - - EXPECT_ERROR(Device.synchronousCopyH2D(ArrayRef(Host5), DeviceA7)); - - EXPECT_ERROR(Device.synchronousCopyH2D(ArrayRef(Host7), DeviceA5)); -} - -TEST_F(DeviceTest, SyncCopyH2DToPointer) { - EXPECT_NO_ERROR(Device.synchronousCopyH2D(Host5, DeviceA5, 5)); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); - } - - EXPECT_ERROR(Device.synchronousCopyH2D(Host7, DeviceA5, 7)); -} - -TEST_F(DeviceTest, SyncCopyH2DSliceToArrayRefByCount) { - EXPECT_NO_ERROR(Device.synchronousCopyH2D( - ArrayRef(Host5 + 1, 4), DeviceA5.asSlice().drop_front(1), 4)); - for (int I = 1; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); - } - - EXPECT_NO_ERROR(Device.synchronousCopyH2D( - ArrayRef(Host5), DeviceB5.asSlice().drop_back(1), 2)); - for (int I = 0; I < 2; ++I) { - EXPECT_EQ(getDeviceValue(DeviceB5, I), Host5[I]); - } - - EXPECT_ERROR( - Device.synchronousCopyH2D(ArrayRef(Host7), DeviceA5.asSlice(), 7)); - - EXPECT_ERROR( - Device.synchronousCopyH2D(ArrayRef(Host5), DeviceA7.asSlice(), 7)); - - EXPECT_ERROR( - Device.synchronousCopyH2D(ArrayRef(Host5), DeviceA5.asSlice(), 7)); -} - -TEST_F(DeviceTest, SyncCopyH2DSliceToArrayRef) { - EXPECT_NO_ERROR( - Device.synchronousCopyH2D(ArrayRef(Host5), DeviceA5.asSlice())); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); - } - - EXPECT_ERROR( - Device.synchronousCopyH2D(ArrayRef(Host5), DeviceA7.asSlice())); - - EXPECT_ERROR( - Device.synchronousCopyH2D(ArrayRef(Host7), DeviceA5.asSlice())); -} - -TEST_F(DeviceTest, SyncCopyH2DSliceToPointer) { - EXPECT_NO_ERROR(Device.synchronousCopyH2D(Host5, DeviceA5.asSlice(), 5)); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); - } - - EXPECT_ERROR(Device.synchronousCopyH2D(Host7, DeviceA5.asSlice(), 7)); -} - -// D2D tests - -TEST_F(DeviceTest, SyncCopyD2DByCount) { - EXPECT_NO_ERROR(Device.synchronousCopyD2D(DeviceA5, DeviceB5, 5)); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB5, I)); - } - - EXPECT_NO_ERROR(Device.synchronousCopyD2D(DeviceA7, DeviceB7, 2)); - for (int I = 0; I < 2; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB7, I)); - } - - EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA5, DeviceB5, 7)); - - EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA7, DeviceB5, 7)); - - EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA5, DeviceB7, 7)); -} - -TEST_F(DeviceTest, SyncCopyD2D) { - EXPECT_NO_ERROR(Device.synchronousCopyD2D(DeviceA5, DeviceB5)); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB5, I)); - } - - EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA7, DeviceB5)); - - EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA5, DeviceB7)); -} - -TEST_F(DeviceTest, SyncCopySliceD2DByCount) { - EXPECT_NO_ERROR( - Device.synchronousCopyD2D(DeviceA5.asSlice().drop_front(1), DeviceB5, 4)); - for (int I = 0; I < 4; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I + 1), getDeviceValue(DeviceB5, I)); - } - - EXPECT_NO_ERROR( - Device.synchronousCopyD2D(DeviceA7.asSlice().drop_back(1), DeviceB7, 2)); - for (int I = 0; I < 2; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB7, I)); - } - - EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB5, 7)); - - EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA7.asSlice(), DeviceB5, 7)); - - EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB7, 7)); -} - -TEST_F(DeviceTest, SyncCopySliceD2D) { - EXPECT_NO_ERROR( - Device.synchronousCopyD2D(DeviceA7.asSlice().drop_back(2), DeviceB5)); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB5, I)); - } - - EXPECT_ERROR( - Device.synchronousCopyD2D(DeviceA7.asSlice().drop_front(1), DeviceB5)); - - EXPECT_ERROR( - Device.synchronousCopyD2D(DeviceA5.asSlice().drop_back(1), DeviceB7)); -} - -TEST_F(DeviceTest, SyncCopyD2DSliceByCount) { - EXPECT_NO_ERROR( - Device.synchronousCopyD2D(DeviceA5, DeviceB7.asSlice().drop_front(2), 5)); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB7, I + 2)); - } - - EXPECT_NO_ERROR( - Device.synchronousCopyD2D(DeviceA7, DeviceB7.asSlice().drop_back(3), 2)); - for (int I = 0; I < 2; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB7, I)); - } - - EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA5, DeviceB5.asSlice(), 7)); - - EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA7, DeviceB5.asSlice(), 7)); - - EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA5, DeviceB7.asSlice(), 7)); -} - -TEST_F(DeviceTest, SyncCopyD2DSlice) { - EXPECT_NO_ERROR( - Device.synchronousCopyD2D(DeviceA5, DeviceB7.asSlice().drop_back(2))); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB7, I)); - } - - EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA7, DeviceB5.asSlice())); - - EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA5, DeviceB7.asSlice())); -} - -TEST_F(DeviceTest, SyncCopySliceD2DSliceByCount) { - EXPECT_NO_ERROR( - Device.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB5.asSlice(), 5)); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB5, I)); - } - - EXPECT_NO_ERROR( - Device.synchronousCopyD2D(DeviceA7.asSlice(), DeviceB7.asSlice(), 2)); - for (int I = 0; I < 2; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB7, I)); - } - - EXPECT_ERROR( - Device.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB5.asSlice(), 7)); - - EXPECT_ERROR( - Device.synchronousCopyD2D(DeviceA7.asSlice(), DeviceB5.asSlice(), 7)); - - EXPECT_ERROR( - Device.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB7.asSlice(), 7)); -} - -TEST_F(DeviceTest, SyncCopySliceD2DSlice) { - EXPECT_NO_ERROR( - Device.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB5.asSlice())); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB5, I)); - } - - EXPECT_ERROR( - Device.synchronousCopyD2D(DeviceA7.asSlice(), DeviceB5.asSlice())); - - EXPECT_ERROR( - Device.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB7.asSlice())); -} - -} // namespace diff --git a/parallel-libs/streamexecutor/lib/unittests/KernelSpecTest.cpp b/parallel-libs/streamexecutor/lib/unittests/KernelSpecTest.cpp deleted file mode 100644 index fc9eb549968..00000000000 --- a/parallel-libs/streamexecutor/lib/unittests/KernelSpecTest.cpp +++ /dev/null @@ -1,132 +0,0 @@ -//===-- KernelSpecTest.cpp - Tests for KernelSpec -------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This file contains the unit tests for the code in KernelSpec. -/// -//===----------------------------------------------------------------------===// - -#include "streamexecutor/KernelSpec.h" - -#include "gtest/gtest.h" - -namespace { - -namespace se = ::streamexecutor; - -TEST(CUDAPTXInMemorySpec, NoCode) { - se::CUDAPTXInMemorySpec Spec("KernelName", {}); - EXPECT_EQ("KernelName", Spec.getKernelName()); - EXPECT_EQ(nullptr, Spec.getCode(1, 0)); -} - -TEST(CUDAPTXInMemorySpec, SingleComputeCapability) { - const char *PTXCodeString = "Dummy PTX code"; - se::CUDAPTXInMemorySpec Spec("KernelName", {{{1, 0}, PTXCodeString}}); - EXPECT_EQ("KernelName", Spec.getKernelName()); - EXPECT_EQ(PTXCodeString, Spec.getCode(1, 0)); - EXPECT_EQ(nullptr, Spec.getCode(2, 0)); -} - -TEST(CUDAPTXInMemorySpec, TwoComputeCapabilities) { - const char *PTXCodeString10 = "Dummy PTX code 10"; - const char *PTXCodeString30 = "Dummy PTX code 30"; - se::CUDAPTXInMemorySpec Spec( - "KernelName", {{{1, 0}, PTXCodeString10}, {{3, 0}, PTXCodeString30}}); - EXPECT_EQ("KernelName", Spec.getKernelName()); - EXPECT_EQ(PTXCodeString10, Spec.getCode(1, 0)); - EXPECT_EQ(PTXCodeString30, Spec.getCode(3, 0)); - EXPECT_EQ(nullptr, Spec.getCode(2, 0)); -} - -TEST(CUDAFatbinInMemorySpec, BasicUsage) { - const char *FatbinBytes = "Dummy fatbin bytes"; - se::CUDAFatbinInMemorySpec Spec("KernelName", FatbinBytes); - EXPECT_EQ("KernelName", Spec.getKernelName()); - EXPECT_EQ(FatbinBytes, Spec.getBytes()); -} - -TEST(OpenCLTextInMemorySpec, BasicUsage) { - const char *OpenCLText = "Dummy OpenCL text"; - se::OpenCLTextInMemorySpec Spec("KernelName", OpenCLText); - EXPECT_EQ("KernelName", Spec.getKernelName()); - EXPECT_EQ(OpenCLText, Spec.getText()); -} - -TEST(MultiKernelLoaderSpec, NoCode) { - se::MultiKernelLoaderSpec MultiSpec; - EXPECT_FALSE(MultiSpec.hasCUDAPTXInMemory()); - EXPECT_FALSE(MultiSpec.hasCUDAFatbinInMemory()); - EXPECT_FALSE(MultiSpec.hasOpenCLTextInMemory()); - - EXPECT_DEBUG_DEATH(MultiSpec.getCUDAPTXInMemory(), - "getting spec that is not present"); - EXPECT_DEBUG_DEATH(MultiSpec.getCUDAFatbinInMemory(), - "getting spec that is not present"); - EXPECT_DEBUG_DEATH(MultiSpec.getOpenCLTextInMemory(), - "getting spec that is not present"); -} - -TEST(MultiKernelLoaderSpec, Registration) { - se::MultiKernelLoaderSpec MultiSpec; - const char *KernelName = "KernelName"; - const char *PTXCodeString = "Dummy PTX code"; - const char *FatbinBytes = "Dummy fatbin bytes"; - const char *OpenCLText = "Dummy OpenCL text"; - - MultiSpec.addCUDAPTXInMemory(KernelName, {{{1, 0}, PTXCodeString}}) - .addCUDAFatbinInMemory(KernelName, FatbinBytes) - .addOpenCLTextInMemory(KernelName, OpenCLText); - - EXPECT_TRUE(MultiSpec.hasCUDAPTXInMemory()); - EXPECT_TRUE(MultiSpec.hasCUDAFatbinInMemory()); - EXPECT_TRUE(MultiSpec.hasOpenCLTextInMemory()); - - EXPECT_EQ(KernelName, MultiSpec.getCUDAPTXInMemory().getKernelName()); - EXPECT_EQ(PTXCodeString, MultiSpec.getCUDAPTXInMemory().getCode(1, 0)); - EXPECT_EQ(nullptr, MultiSpec.getCUDAPTXInMemory().getCode(2, 0)); - - EXPECT_EQ(KernelName, MultiSpec.getCUDAFatbinInMemory().getKernelName()); - EXPECT_EQ(FatbinBytes, MultiSpec.getCUDAFatbinInMemory().getBytes()); - - EXPECT_EQ(KernelName, MultiSpec.getOpenCLTextInMemory().getKernelName()); - EXPECT_EQ(OpenCLText, MultiSpec.getOpenCLTextInMemory().getText()); -} - -TEST(MultiKernelLoaderSpec, RegisterTwice) { - se::MultiKernelLoaderSpec MultiSpec; - const char *KernelName = "KernelName"; - const char *FatbinBytes = "Dummy fatbin bytes"; - - MultiSpec.addCUDAFatbinInMemory(KernelName, FatbinBytes); - - EXPECT_DEBUG_DEATH(MultiSpec.addCUDAFatbinInMemory(KernelName, FatbinBytes), - "illegal loader spec overwrite"); -} - -TEST(MultiKernelLoaderSpec, ConflictingKernelNames) { - se::MultiKernelLoaderSpec MultiSpec; - const char *KernelNameA = "KernelName"; - std::string KernelNameB = KernelNameA; - const char *PTXCodeString = "Dummy PTX code"; - const char *FatbinBytes = "Dummy fatbin bytes"; - - // Check that names don't conflict if they are equivalent strings in different - // locations. - MultiSpec.addCUDAPTXInMemory(KernelNameA, {{{1, 0}, PTXCodeString}}) - .addCUDAFatbinInMemory(KernelNameB, FatbinBytes); - - const char *OtherKernelName = "OtherKernelName"; - const char *OpenCLText = "Dummy OpenCL text"; - EXPECT_DEBUG_DEATH( - MultiSpec.addOpenCLTextInMemory(OtherKernelName, OpenCLText), - "different kernel names in one MultiKernelLoaderSpec"); -} - -} // namespace diff --git a/parallel-libs/streamexecutor/lib/unittests/PackedKernelArgumentArrayTest.cpp b/parallel-libs/streamexecutor/lib/unittests/PackedKernelArgumentArrayTest.cpp deleted file mode 100644 index dd6d0e1c655..00000000000 --- a/parallel-libs/streamexecutor/lib/unittests/PackedKernelArgumentArrayTest.cpp +++ /dev/null @@ -1,150 +0,0 @@ -//===-- PackedKernelArgumentArrayTest.cpp - tests for kernel arg packing --===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// Unit tests for kernel argument packing. -/// -//===----------------------------------------------------------------------===// - -#include "SimpleHostPlatformDevice.h" -#include "streamexecutor/Device.h" -#include "streamexecutor/DeviceMemory.h" -#include "streamexecutor/PackedKernelArgumentArray.h" -#include "streamexecutor/PlatformDevice.h" - -#include "llvm/ADT/Twine.h" - -#include "gtest/gtest.h" - -namespace { - -namespace se = ::streamexecutor; - -using Type = se::KernelArgumentType; - -// Test fixture class for testing argument packing. -// -// Basically defines a bunch of types to be packed so they don't have to be -// defined separately in each test. -class DeviceMemoryPackingTest : public ::testing::Test { -public: - DeviceMemoryPackingTest() - : Device(&PDevice), Value(42), Handle(&Value), ByteCount(15), - ElementCount(5), - TypedGlobal(getOrDie(Device.allocateDeviceMemory(ElementCount))), - TypedShared( - se::SharedDeviceMemory::makeFromElementCount(ElementCount)) {} - - se::test::SimpleHostPlatformDevice PDevice; - se::Device Device; - int Value; - void *Handle; - size_t ByteCount; - size_t ElementCount; - se::GlobalDeviceMemory TypedGlobal; - se::SharedDeviceMemory TypedShared; -}; - -// Utility method to check the expected address, size, and type for a packed -// argument at the given index of a PackedKernelArgumentArray. -template -static void -ExpectEqual(const void *ExpectedAddress, size_t ExpectedSize, Type ExpectedType, - const se::PackedKernelArgumentArray &Observed, - size_t Index) { - SCOPED_TRACE(("Index = " + llvm::Twine(Index)).str()); - EXPECT_EQ(ExpectedAddress, Observed.getAddress(Index)); - EXPECT_EQ(ExpectedAddress, Observed.getAddresses()[Index]); - EXPECT_EQ(ExpectedSize, Observed.getSize(Index)); - EXPECT_EQ(ExpectedSize, Observed.getSizes()[Index]); - EXPECT_EQ(ExpectedType, Observed.getType(Index)); - EXPECT_EQ(ExpectedType, Observed.getTypes()[Index]); -} - -TEST_F(DeviceMemoryPackingTest, SingleValue) { - auto Array = se::make_kernel_argument_pack(Value); - ExpectEqual(&Value, sizeof(Value), Type::VALUE, Array, 0); - EXPECT_EQ(1u, Array.getArgumentCount()); - EXPECT_EQ(0u, Array.getSharedCount()); -} - -TEST_F(DeviceMemoryPackingTest, SingleTypedGlobal) { - auto Array = se::make_kernel_argument_pack(TypedGlobal); - ExpectEqual(TypedGlobal.getHandle(), sizeof(void *), - Type::GLOBAL_DEVICE_MEMORY, Array, 0); - EXPECT_EQ(1u, Array.getArgumentCount()); - EXPECT_EQ(0u, Array.getSharedCount()); -} - -TEST_F(DeviceMemoryPackingTest, SingleTypedGlobalPointer) { - auto Array = se::make_kernel_argument_pack(&TypedGlobal); - ExpectEqual(TypedGlobal.getHandle(), sizeof(void *), - Type::GLOBAL_DEVICE_MEMORY, Array, 0); - EXPECT_EQ(1u, Array.getArgumentCount()); - EXPECT_EQ(0u, Array.getSharedCount()); -} - -TEST_F(DeviceMemoryPackingTest, SingleConstTypedGlobalPointer) { - const se::GlobalDeviceMemory *ArgumentPointer = &TypedGlobal; - auto Array = se::make_kernel_argument_pack(ArgumentPointer); - ExpectEqual(TypedGlobal.getHandle(), sizeof(void *), - Type::GLOBAL_DEVICE_MEMORY, Array, 0); - EXPECT_EQ(1u, Array.getArgumentCount()); - EXPECT_EQ(0u, Array.getSharedCount()); -} - -TEST_F(DeviceMemoryPackingTest, SingleTypedShared) { - auto Array = se::make_kernel_argument_pack(TypedShared); - ExpectEqual(nullptr, TypedShared.getByteCount(), Type::SHARED_DEVICE_MEMORY, - Array, 0); - EXPECT_EQ(1u, Array.getArgumentCount()); - EXPECT_EQ(1u, Array.getSharedCount()); -} - -TEST_F(DeviceMemoryPackingTest, SingleTypedSharedPointer) { - auto Array = se::make_kernel_argument_pack(&TypedShared); - ExpectEqual(nullptr, TypedShared.getByteCount(), Type::SHARED_DEVICE_MEMORY, - Array, 0); - EXPECT_EQ(1u, Array.getArgumentCount()); - EXPECT_EQ(1u, Array.getSharedCount()); -} - -TEST_F(DeviceMemoryPackingTest, SingleConstTypedSharedPointer) { - const se::SharedDeviceMemory *ArgumentPointer = &TypedShared; - auto Array = se::make_kernel_argument_pack(ArgumentPointer); - ExpectEqual(nullptr, TypedShared.getByteCount(), Type::SHARED_DEVICE_MEMORY, - Array, 0); - EXPECT_EQ(1u, Array.getArgumentCount()); - EXPECT_EQ(1u, Array.getSharedCount()); -} - -TEST_F(DeviceMemoryPackingTest, PackSeveralArguments) { - const se::GlobalDeviceMemory *TypedGlobalPointer = &TypedGlobal; - const se::SharedDeviceMemory *TypedSharedPointer = &TypedShared; - auto Array = se::make_kernel_argument_pack(Value, TypedGlobal, &TypedGlobal, - TypedGlobalPointer, TypedShared, - &TypedShared, TypedSharedPointer); - ExpectEqual(&Value, sizeof(Value), Type::VALUE, Array, 0); - ExpectEqual(TypedGlobal.getHandle(), sizeof(void *), - Type::GLOBAL_DEVICE_MEMORY, Array, 1); - ExpectEqual(TypedGlobal.getHandle(), sizeof(void *), - Type::GLOBAL_DEVICE_MEMORY, Array, 2); - ExpectEqual(TypedGlobal.getHandle(), sizeof(void *), - Type::GLOBAL_DEVICE_MEMORY, Array, 3); - ExpectEqual(nullptr, TypedShared.getByteCount(), Type::SHARED_DEVICE_MEMORY, - Array, 4); - ExpectEqual(nullptr, TypedShared.getByteCount(), Type::SHARED_DEVICE_MEMORY, - Array, 5); - ExpectEqual(nullptr, TypedShared.getByteCount(), Type::SHARED_DEVICE_MEMORY, - Array, 6); - EXPECT_EQ(7u, Array.getArgumentCount()); - EXPECT_EQ(3u, Array.getSharedCount()); -} - -} // namespace diff --git a/parallel-libs/streamexecutor/lib/unittests/SimpleHostPlatformDevice.h b/parallel-libs/streamexecutor/lib/unittests/SimpleHostPlatformDevice.h deleted file mode 100644 index 5c5953098c4..00000000000 --- a/parallel-libs/streamexecutor/lib/unittests/SimpleHostPlatformDevice.h +++ /dev/null @@ -1,148 +0,0 @@ -//===-- SimpleHostPlatformDevice.h - Host device for testing ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// The SimpleHostPlatformDevice class is a streamexecutor::PlatformDevice that -/// is really just the host processor and memory. It is useful for testing -/// because no extra device platform is required. -/// -//===----------------------------------------------------------------------===// - -#ifndef STREAMEXECUTOR_LIB_UNITTESTS_SIMPLEHOSTPLATFORMDEVICE_H -#define STREAMEXECUTOR_LIB_UNITTESTS_SIMPLEHOSTPLATFORMDEVICE_H - -#include -#include - -#include "streamexecutor/PlatformDevice.h" - -namespace streamexecutor { -namespace test { - -/// A streamexecutor::PlatformDevice that simply forwards all operations to the -/// host platform. -/// -/// The allocate and copy methods are simple wrappers for std::malloc and -/// std::memcpy. -class SimpleHostPlatformDevice : public streamexecutor::PlatformDevice { -public: - std::string getName() const override { return "SimpleHostPlatformDevice"; } - - streamexecutor::Expected createStream() override { - return nullptr; - } - - streamexecutor::Expected - allocateDeviceMemory(size_t ByteCount) override { - return std::malloc(ByteCount); - } - - streamexecutor::Error freeDeviceMemory(const void *Handle) override { - std::free(const_cast(Handle)); - return streamexecutor::Error::success(); - } - - streamexecutor::Expected - allocateHostMemory(size_t ByteCount) override { - return std::malloc(ByteCount); - } - - streamexecutor::Error freeHostMemory(void *Memory) override { - std::free(const_cast(Memory)); - return streamexecutor::Error::success(); - } - - streamexecutor::Error registerHostMemory(void *Memory, - size_t ByteCount) override { - return streamexecutor::Error::success(); - } - - streamexecutor::Error unregisterHostMemory(void *Memory) override { - return streamexecutor::Error::success(); - } - - streamexecutor::Error copyD2H(const void *StreamHandle, - const void *DeviceHandleSrc, - size_t SrcByteOffset, void *HostDst, - size_t DstByteOffset, - size_t ByteCount) override { - std::memcpy(static_cast(HostDst) + DstByteOffset, - static_cast(DeviceHandleSrc) + SrcByteOffset, - ByteCount); - return streamexecutor::Error::success(); - } - - streamexecutor::Error copyH2D(const void *StreamHandle, const void *HostSrc, - size_t SrcByteOffset, - const void *DeviceHandleDst, - size_t DstByteOffset, - size_t ByteCount) override { - std::memcpy(static_cast(const_cast(DeviceHandleDst)) + - DstByteOffset, - static_cast(HostSrc) + SrcByteOffset, ByteCount); - return streamexecutor::Error::success(); - } - - streamexecutor::Error - copyD2D(const void *StreamHandle, const void *DeviceHandleSrc, - size_t SrcByteOffset, const void *DeviceHandleDst, - size_t DstByteOffset, size_t ByteCount) override { - std::memcpy(static_cast(const_cast(DeviceHandleDst)) + - DstByteOffset, - static_cast(DeviceHandleSrc) + SrcByteOffset, - ByteCount); - return streamexecutor::Error::success(); - } - - streamexecutor::Error synchronousCopyD2H(const void *DeviceHandleSrc, - size_t SrcByteOffset, void *HostDst, - size_t DstByteOffset, - size_t ByteCount) override { - std::memcpy(static_cast(HostDst) + DstByteOffset, - static_cast(DeviceHandleSrc) + SrcByteOffset, - ByteCount); - return streamexecutor::Error::success(); - } - - streamexecutor::Error synchronousCopyH2D(const void *HostSrc, - size_t SrcByteOffset, - const void *DeviceHandleDst, - size_t DstByteOffset, - size_t ByteCount) override { - std::memcpy(static_cast(const_cast(DeviceHandleDst)) + - DstByteOffset, - static_cast(HostSrc) + SrcByteOffset, ByteCount); - return streamexecutor::Error::success(); - } - - streamexecutor::Error synchronousCopyD2D(const void *DeviceHandleSrc, - size_t SrcByteOffset, - const void *DeviceHandleDst, - size_t DstByteOffset, - size_t ByteCount) override { - std::memcpy(static_cast(const_cast(DeviceHandleDst)) + - DstByteOffset, - static_cast(DeviceHandleSrc) + SrcByteOffset, - ByteCount); - return streamexecutor::Error::success(); - } - - /// Gets the value at the given index from a GlobalDeviceMemory instance - /// created by this class. - template - static T getDeviceValue(const streamexecutor::GlobalDeviceMemory &Memory, - size_t Index) { - return static_cast(Memory.getHandle())[Index]; - } -}; - -} // namespace test -} // namespace streamexecutor - -#endif // STREAMEXECUTOR_LIB_UNITTESTS_SIMPLEHOSTPLATFORMDEVICE_H diff --git a/parallel-libs/streamexecutor/lib/unittests/StreamTest.cpp b/parallel-libs/streamexecutor/lib/unittests/StreamTest.cpp deleted file mode 100644 index 65598540d67..00000000000 --- a/parallel-libs/streamexecutor/lib/unittests/StreamTest.cpp +++ /dev/null @@ -1,362 +0,0 @@ -//===-- StreamTest.cpp - Tests for Stream ---------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This file contains the unit tests for Stream code. -/// -//===----------------------------------------------------------------------===// - -#include - -#include "SimpleHostPlatformDevice.h" -#include "streamexecutor/Device.h" -#include "streamexecutor/Kernel.h" -#include "streamexecutor/KernelSpec.h" -#include "streamexecutor/PlatformDevice.h" -#include "streamexecutor/Stream.h" - -#include "gtest/gtest.h" - -namespace { - -namespace se = ::streamexecutor; - -const auto &getDeviceValue = - se::test::SimpleHostPlatformDevice::getDeviceValue; - -/// Test fixture to hold objects used by tests. -class StreamTest : public ::testing::Test { -public: - StreamTest() - : DummyPlatformStream(1), Device(&PDevice), - Stream(&PDevice, &DummyPlatformStream), HostA5{0, 1, 2, 3, 4}, - HostB5{5, 6, 7, 8, 9}, HostA7{10, 11, 12, 13, 14, 15, 16}, - HostB7{17, 18, 19, 20, 21, 22, 23}, Host5{24, 25, 26, 27, 28}, - Host7{29, 30, 31, 32, 33, 34, 35}, - DeviceA5(getOrDie(Device.allocateDeviceMemory(5))), - DeviceB5(getOrDie(Device.allocateDeviceMemory(5))), - DeviceA7(getOrDie(Device.allocateDeviceMemory(7))), - DeviceB7(getOrDie(Device.allocateDeviceMemory(7))) { - se::dieIfError(Device.synchronousCopyH2D(HostA5, DeviceA5)); - se::dieIfError(Device.synchronousCopyH2D(HostB5, DeviceB5)); - se::dieIfError(Device.synchronousCopyH2D(HostA7, DeviceA7)); - se::dieIfError(Device.synchronousCopyH2D(HostB7, DeviceB7)); - } - -protected: - int DummyPlatformStream; // Mimicking a platform where the platform stream - // handle is just a stream number. - se::test::SimpleHostPlatformDevice PDevice; - se::Device Device; - se::Stream Stream; - - // Device memory is matched by host arrays. - int HostA5[5]; - int HostB5[5]; - int HostA7[7]; - int HostB7[7]; - - // Host memory to be used as actual host memory. - int Host5[5]; - int Host7[7]; - - // Device memory. - se::GlobalDeviceMemory DeviceA5; - se::GlobalDeviceMemory DeviceB5; - se::GlobalDeviceMemory DeviceA7; - se::GlobalDeviceMemory DeviceB7; -}; - -using llvm::ArrayRef; -using llvm::MutableArrayRef; - -// D2H tests - -TEST_F(StreamTest, CopyD2HToMutableArrayRefByCount) { - Stream.thenCopyD2H(DeviceA5, MutableArrayRef(Host5), 5); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(HostA5[I], Host5[I]); - } - - Stream.thenCopyD2H(DeviceB5, MutableArrayRef(Host5), 2); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 2; ++I) { - EXPECT_EQ(HostB5[I], Host5[I]); - } - - Stream.thenCopyD2H(DeviceA7, MutableArrayRef(Host5), 7); - EXPECT_FALSE(Stream.isOK()); -} - -TEST_F(StreamTest, CopyD2HToMutableArrayRef) { - Stream.thenCopyD2H(DeviceA5, MutableArrayRef(Host5)); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(HostA5[I], Host5[I]); - } - - Stream.thenCopyD2H(DeviceA5, MutableArrayRef(Host7)); - EXPECT_FALSE(Stream.isOK()); -} - -TEST_F(StreamTest, CopyD2HToPointer) { - Stream.thenCopyD2H(DeviceA5, Host5, 5); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(HostA5[I], Host5[I]); - } - - Stream.thenCopyD2H(DeviceA5, Host7, 7); - EXPECT_FALSE(Stream.isOK()); -} - -TEST_F(StreamTest, CopyD2HSliceToMutableArrayRefByCount) { - Stream.thenCopyD2H(DeviceA5.asSlice().drop_front(1), - MutableArrayRef(Host5 + 1, 4), 4); - EXPECT_TRUE(Stream.isOK()); - for (int I = 1; I < 5; ++I) { - EXPECT_EQ(HostA5[I], Host5[I]); - } - - Stream.thenCopyD2H(DeviceB5.asSlice().drop_back(1), - MutableArrayRef(Host5), 2); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 2; ++I) { - EXPECT_EQ(HostB5[I], Host5[I]); - } - - Stream.thenCopyD2H(DeviceA5.asSlice(), MutableArrayRef(Host7), 7); - EXPECT_FALSE(Stream.isOK()); -} - -TEST_F(StreamTest, CopyD2HSliceToMutableArrayRef) { - Stream.thenCopyD2H(DeviceA7.asSlice().slice(1, 5), - MutableArrayRef(Host5)); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(HostA7[I + 1], Host5[I]); - } - - Stream.thenCopyD2H(DeviceA5.asSlice(), MutableArrayRef(Host7)); - EXPECT_FALSE(Stream.isOK()); -} - -TEST_F(StreamTest, CopyD2HSliceToPointer) { - Stream.thenCopyD2H(DeviceA5.asSlice().drop_front(1), Host5 + 1, 4); - EXPECT_TRUE(Stream.isOK()); - for (int I = 1; I < 5; ++I) { - EXPECT_EQ(HostA5[I], Host5[I]); - } - - Stream.thenCopyD2H(DeviceA5.asSlice(), Host7, 7); - EXPECT_FALSE(Stream.isOK()); -} - -// H2D tests - -TEST_F(StreamTest, CopyH2DToArrayRefByCount) { - Stream.thenCopyH2D(ArrayRef(Host5), DeviceA5, 5); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); - } - - Stream.thenCopyH2D(ArrayRef(Host5), DeviceB5, 2); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 2; ++I) { - EXPECT_EQ(getDeviceValue(DeviceB5, I), Host5[I]); - } - - Stream.thenCopyH2D(ArrayRef(Host7), DeviceA5, 7); - EXPECT_FALSE(Stream.isOK()); -} - -TEST_F(StreamTest, CopyH2DToArrayRef) { - Stream.thenCopyH2D(ArrayRef(Host5), DeviceA5); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); - } - - Stream.thenCopyH2D(ArrayRef(Host7), DeviceA5); - EXPECT_FALSE(Stream.isOK()); -} - -TEST_F(StreamTest, CopyH2DToPointer) { - Stream.thenCopyH2D(Host5, DeviceA5, 5); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); - } - - Stream.thenCopyH2D(Host7, DeviceA5, 7); - EXPECT_FALSE(Stream.isOK()); -} - -TEST_F(StreamTest, CopyH2DSliceToArrayRefByCount) { - Stream.thenCopyH2D(ArrayRef(Host5 + 1, 4), - DeviceA5.asSlice().drop_front(1), 4); - EXPECT_TRUE(Stream.isOK()); - for (int I = 1; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); - } - - Stream.thenCopyH2D(ArrayRef(Host5), DeviceB5.asSlice().drop_back(1), 2); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 2; ++I) { - EXPECT_EQ(getDeviceValue(DeviceB5, I), Host5[I]); - } - - Stream.thenCopyH2D(ArrayRef(Host5), DeviceA5.asSlice(), 7); - EXPECT_FALSE(Stream.isOK()); -} - -TEST_F(StreamTest, CopyH2DSliceToArrayRef) { - - Stream.thenCopyH2D(ArrayRef(Host5), DeviceA5.asSlice()); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); - } - - Stream.thenCopyH2D(ArrayRef(Host7), DeviceA5.asSlice()); - EXPECT_FALSE(Stream.isOK()); -} - -TEST_F(StreamTest, CopyH2DSliceToPointer) { - Stream.thenCopyH2D(Host5, DeviceA5.asSlice(), 5); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); - } - - Stream.thenCopyH2D(Host7, DeviceA5.asSlice(), 7); - EXPECT_FALSE(Stream.isOK()); -} - -// D2D tests - -TEST_F(StreamTest, CopyD2DByCount) { - Stream.thenCopyD2D(DeviceA5, DeviceB5, 5); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB5, I)); - } - - Stream.thenCopyD2D(DeviceA7, DeviceB7, 2); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 2; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB7, I)); - } - - Stream.thenCopyD2D(DeviceA7, DeviceB5, 7); - EXPECT_FALSE(Stream.isOK()); -} - -TEST_F(StreamTest, CopyD2D) { - Stream.thenCopyD2D(DeviceA5, DeviceB5); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB5, I)); - } - - Stream.thenCopyD2D(DeviceA7, DeviceB5); - EXPECT_FALSE(Stream.isOK()); -} - -TEST_F(StreamTest, CopySliceD2DByCount) { - Stream.thenCopyD2D(DeviceA5.asSlice().drop_front(1), DeviceB5, 4); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 4; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I + 1), getDeviceValue(DeviceB5, I)); - } - - Stream.thenCopyD2D(DeviceA7.asSlice().drop_back(1), DeviceB7, 2); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 2; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB7, I)); - } - - Stream.thenCopyD2D(DeviceA5.asSlice(), DeviceB5, 7); - EXPECT_FALSE(Stream.isOK()); -} - -TEST_F(StreamTest, CopySliceD2D) { - - Stream.thenCopyD2D(DeviceA7.asSlice().drop_back(2), DeviceB5); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB5, I)); - } - - Stream.thenCopyD2D(DeviceA5.asSlice().drop_back(1), DeviceB7); - EXPECT_FALSE(Stream.isOK()); -} - -TEST_F(StreamTest, CopyD2DSliceByCount) { - Stream.thenCopyD2D(DeviceA5, DeviceB7.asSlice().drop_front(2), 5); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB7, I + 2)); - } - - Stream.thenCopyD2D(DeviceA7, DeviceB7.asSlice().drop_back(3), 2); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 2; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB7, I)); - } - - Stream.thenCopyD2D(DeviceA5, DeviceB7.asSlice(), 7); - EXPECT_FALSE(Stream.isOK()); -} - -TEST_F(StreamTest, CopyD2DSlice) { - - Stream.thenCopyD2D(DeviceA5, DeviceB7.asSlice().drop_back(2)); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB7, I)); - } - - Stream.thenCopyD2D(DeviceA5, DeviceB7.asSlice()); - EXPECT_FALSE(Stream.isOK()); -} - -TEST_F(StreamTest, CopySliceD2DSliceByCount) { - - Stream.thenCopyD2D(DeviceA5.asSlice(), DeviceB5.asSlice(), 5); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB5, I)); - } - - Stream.thenCopyD2D(DeviceA7.asSlice(), DeviceB7.asSlice(), 2); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 2; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB7, I)); - } - - Stream.thenCopyD2D(DeviceA7.asSlice(), DeviceB5.asSlice(), 7); - EXPECT_FALSE(Stream.isOK()); -} - -TEST_F(StreamTest, CopySliceD2DSlice) { - - Stream.thenCopyD2D(DeviceA5.asSlice(), DeviceB5.asSlice()); - EXPECT_TRUE(Stream.isOK()); - for (int I = 0; I < 5; ++I) { - EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB5, I)); - } - - Stream.thenCopyD2D(DeviceA5.asSlice(), DeviceB7.asSlice()); - EXPECT_FALSE(Stream.isOK()); -} - -} // namespace diff --git a/parallel-libs/streamexecutor/unittests/CMakeLists.txt b/parallel-libs/streamexecutor/unittests/CMakeLists.txt new file mode 100644 index 00000000000..3a8142273a5 --- /dev/null +++ b/parallel-libs/streamexecutor/unittests/CMakeLists.txt @@ -0,0 +1,9 @@ +add_custom_target(StreamExecutorUnitTests) +set_target_properties(StreamExecutorUnitTests PROPERTIES FOLDER "streamexecutor tests") + +function(add_se_unittest testdir_name) + add_unittest(StreamExecutorUnitTests ${testdir_name} ${ARGN}) + target_link_libraries(${testdir_name} streamexecutor) +endfunction() + +add_subdirectory(CoreTests) diff --git a/parallel-libs/streamexecutor/unittests/CoreTests/CMakeLists.txt b/parallel-libs/streamexecutor/unittests/CoreTests/CMakeLists.txt new file mode 100644 index 00000000000..3365dd07e76 --- /dev/null +++ b/parallel-libs/streamexecutor/unittests/CoreTests/CMakeLists.txt @@ -0,0 +1,7 @@ +add_se_unittest( + CoreTests + DeviceTest.cpp + KernelSpecTest.cpp + PackedKernelArgumentArrayTest.cpp + StreamTest.cpp +) diff --git a/parallel-libs/streamexecutor/unittests/CoreTests/DeviceTest.cpp b/parallel-libs/streamexecutor/unittests/CoreTests/DeviceTest.cpp new file mode 100644 index 00000000000..5b16c3c865c --- /dev/null +++ b/parallel-libs/streamexecutor/unittests/CoreTests/DeviceTest.cpp @@ -0,0 +1,414 @@ +//===-- DeviceTest.cpp - Tests for Device ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the unit tests for Device code. +/// +//===----------------------------------------------------------------------===// + +#include +#include + +#include "SimpleHostPlatformDevice.h" +#include "streamexecutor/Device.h" +#include "streamexecutor/PlatformDevice.h" + +#include "gtest/gtest.h" + +namespace { + +namespace se = ::streamexecutor; + +const auto &getDeviceValue = + se::test::SimpleHostPlatformDevice::getDeviceValue; + +/// Test fixture to hold objects used by tests. +class DeviceTest : public ::testing::Test { +public: + DeviceTest() + : Device(&PDevice), HostA5{0, 1, 2, 3, 4}, HostB5{5, 6, 7, 8, 9}, + HostA7{10, 11, 12, 13, 14, 15, 16}, HostB7{17, 18, 19, 20, 21, 22, 23}, + DeviceA5(getOrDie(Device.allocateDeviceMemory(5))), + DeviceB5(getOrDie(Device.allocateDeviceMemory(5))), + DeviceA7(getOrDie(Device.allocateDeviceMemory(7))), + DeviceB7(getOrDie(Device.allocateDeviceMemory(7))), + Host5{24, 25, 26, 27, 28}, Host7{29, 30, 31, 32, 33, 34, 35} { + se::dieIfError(Device.synchronousCopyH2D(HostA5, DeviceA5)); + se::dieIfError(Device.synchronousCopyH2D(HostB5, DeviceB5)); + se::dieIfError(Device.synchronousCopyH2D(HostA7, DeviceA7)); + se::dieIfError(Device.synchronousCopyH2D(HostB7, DeviceB7)); + } + + se::test::SimpleHostPlatformDevice PDevice; + se::Device Device; + + // Device memory is backed by host arrays. + int HostA5[5]; + int HostB5[5]; + int HostA7[7]; + int HostB7[7]; + se::GlobalDeviceMemory DeviceA5; + se::GlobalDeviceMemory DeviceB5; + se::GlobalDeviceMemory DeviceA7; + se::GlobalDeviceMemory DeviceB7; + + // Host memory to be used as actual host memory. + int Host5[5]; + int Host7[7]; +}; + +#define EXPECT_NO_ERROR(E) EXPECT_FALSE(static_cast(E)) +#define EXPECT_ERROR(E) \ + do { \ + se::Error E__ = E; \ + EXPECT_TRUE(static_cast(E__)); \ + consumeError(std::move(E__)); \ + } while (false) + +using llvm::ArrayRef; +using llvm::MutableArrayRef; + +TEST_F(DeviceTest, GetName) { + EXPECT_EQ(Device.getName(), "SimpleHostPlatformDevice"); +} + +TEST_F(DeviceTest, AllocateAndFreeDeviceMemory) { + se::Expected> MaybeMemory = + Device.allocateDeviceMemory(10); + EXPECT_TRUE(static_cast(MaybeMemory)); +} + +TEST_F(DeviceTest, AllocateAndFreeHostMemory) { + se::Expected MaybeMemory = Device.allocateHostMemory(10); + EXPECT_TRUE(static_cast(MaybeMemory)); + EXPECT_NO_ERROR(Device.freeHostMemory(*MaybeMemory)); +} + +TEST_F(DeviceTest, RegisterAndUnregisterHostMemory) { + std::vector Data(10); + EXPECT_NO_ERROR(Device.registerHostMemory(Data.data(), 10)); + EXPECT_NO_ERROR(Device.unregisterHostMemory(Data.data())); +} + +// D2H tests + +TEST_F(DeviceTest, SyncCopyD2HToMutableArrayRefByCount) { + EXPECT_NO_ERROR( + Device.synchronousCopyD2H(DeviceA5, MutableArrayRef(Host5), 5)); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(HostA5[I], Host5[I]); + } + + EXPECT_NO_ERROR( + Device.synchronousCopyD2H(DeviceB5, MutableArrayRef(Host5), 2)); + for (int I = 0; I < 2; ++I) { + EXPECT_EQ(HostB5[I], Host5[I]); + } + + EXPECT_ERROR( + Device.synchronousCopyD2H(DeviceA7, MutableArrayRef(Host5), 7)); + + EXPECT_ERROR( + Device.synchronousCopyD2H(DeviceA5, MutableArrayRef(Host7), 7)); + + EXPECT_ERROR( + Device.synchronousCopyD2H(DeviceA5, MutableArrayRef(Host5), 7)); +} + +TEST_F(DeviceTest, SyncCopyD2HToMutableArrayRef) { + EXPECT_NO_ERROR( + Device.synchronousCopyD2H(DeviceA5, MutableArrayRef(Host5))); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(HostA5[I], Host5[I]); + } + + EXPECT_ERROR( + Device.synchronousCopyD2H(DeviceA7, MutableArrayRef(Host5))); + + EXPECT_ERROR( + Device.synchronousCopyD2H(DeviceA5, MutableArrayRef(Host7))); +} + +TEST_F(DeviceTest, SyncCopyD2HToPointer) { + EXPECT_NO_ERROR(Device.synchronousCopyD2H(DeviceA5, Host5, 5)); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(HostA5[I], Host5[I]); + } + + EXPECT_ERROR(Device.synchronousCopyD2H(DeviceA5, Host7, 7)); +} + +TEST_F(DeviceTest, SyncCopyD2HSliceToMutableArrayRefByCount) { + EXPECT_NO_ERROR(Device.synchronousCopyD2H( + DeviceA5.asSlice().drop_front(1), MutableArrayRef(Host5 + 1, 4), 4)); + for (int I = 1; I < 5; ++I) { + EXPECT_EQ(HostA5[I], Host5[I]); + } + + EXPECT_NO_ERROR(Device.synchronousCopyD2H(DeviceB5.asSlice().drop_back(1), + MutableArrayRef(Host5), 2)); + for (int I = 0; I < 2; ++I) { + EXPECT_EQ(HostB5[I], Host5[I]); + } + + EXPECT_ERROR(Device.synchronousCopyD2H(DeviceA7.asSlice(), + MutableArrayRef(Host5), 7)); + + EXPECT_ERROR(Device.synchronousCopyD2H(DeviceA5.asSlice(), + MutableArrayRef(Host7), 7)); + + EXPECT_ERROR(Device.synchronousCopyD2H(DeviceA5.asSlice(), + MutableArrayRef(Host5), 7)); +} + +TEST_F(DeviceTest, SyncCopyD2HSliceToMutableArrayRef) { + EXPECT_NO_ERROR(Device.synchronousCopyD2H(DeviceA7.asSlice().slice(1, 5), + MutableArrayRef(Host5))); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(HostA7[I + 1], Host5[I]); + } + + EXPECT_ERROR(Device.synchronousCopyD2H(DeviceA7.asSlice().drop_back(1), + MutableArrayRef(Host5))); + + EXPECT_ERROR(Device.synchronousCopyD2H(DeviceA5.asSlice(), + MutableArrayRef(Host7))); +} + +TEST_F(DeviceTest, SyncCopyD2HSliceToPointer) { + EXPECT_NO_ERROR(Device.synchronousCopyD2H(DeviceA5.asSlice().drop_front(1), + Host5 + 1, 4)); + for (int I = 1; I < 5; ++I) { + EXPECT_EQ(HostA5[I], Host5[I]); + } + + EXPECT_ERROR(Device.synchronousCopyD2H(DeviceA5.asSlice(), Host7, 7)); +} + +// H2D tests + +TEST_F(DeviceTest, SyncCopyH2DToArrayRefByCount) { + EXPECT_NO_ERROR(Device.synchronousCopyH2D(ArrayRef(Host5), DeviceA5, 5)); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); + } + + EXPECT_NO_ERROR(Device.synchronousCopyH2D(ArrayRef(Host5), DeviceB5, 2)); + for (int I = 0; I < 2; ++I) { + EXPECT_EQ(getDeviceValue(DeviceB5, I), Host5[I]); + } + + EXPECT_ERROR(Device.synchronousCopyH2D(ArrayRef(Host7), DeviceA5, 7)); + + EXPECT_ERROR(Device.synchronousCopyH2D(ArrayRef(Host5), DeviceA7, 7)); + + EXPECT_ERROR(Device.synchronousCopyH2D(ArrayRef(Host5), DeviceA5, 7)); +} + +TEST_F(DeviceTest, SyncCopyH2DToArrayRef) { + EXPECT_NO_ERROR(Device.synchronousCopyH2D(ArrayRef(Host5), DeviceA5)); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); + } + + EXPECT_ERROR(Device.synchronousCopyH2D(ArrayRef(Host5), DeviceA7)); + + EXPECT_ERROR(Device.synchronousCopyH2D(ArrayRef(Host7), DeviceA5)); +} + +TEST_F(DeviceTest, SyncCopyH2DToPointer) { + EXPECT_NO_ERROR(Device.synchronousCopyH2D(Host5, DeviceA5, 5)); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); + } + + EXPECT_ERROR(Device.synchronousCopyH2D(Host7, DeviceA5, 7)); +} + +TEST_F(DeviceTest, SyncCopyH2DSliceToArrayRefByCount) { + EXPECT_NO_ERROR(Device.synchronousCopyH2D( + ArrayRef(Host5 + 1, 4), DeviceA5.asSlice().drop_front(1), 4)); + for (int I = 1; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); + } + + EXPECT_NO_ERROR(Device.synchronousCopyH2D( + ArrayRef(Host5), DeviceB5.asSlice().drop_back(1), 2)); + for (int I = 0; I < 2; ++I) { + EXPECT_EQ(getDeviceValue(DeviceB5, I), Host5[I]); + } + + EXPECT_ERROR( + Device.synchronousCopyH2D(ArrayRef(Host7), DeviceA5.asSlice(), 7)); + + EXPECT_ERROR( + Device.synchronousCopyH2D(ArrayRef(Host5), DeviceA7.asSlice(), 7)); + + EXPECT_ERROR( + Device.synchronousCopyH2D(ArrayRef(Host5), DeviceA5.asSlice(), 7)); +} + +TEST_F(DeviceTest, SyncCopyH2DSliceToArrayRef) { + EXPECT_NO_ERROR( + Device.synchronousCopyH2D(ArrayRef(Host5), DeviceA5.asSlice())); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); + } + + EXPECT_ERROR( + Device.synchronousCopyH2D(ArrayRef(Host5), DeviceA7.asSlice())); + + EXPECT_ERROR( + Device.synchronousCopyH2D(ArrayRef(Host7), DeviceA5.asSlice())); +} + +TEST_F(DeviceTest, SyncCopyH2DSliceToPointer) { + EXPECT_NO_ERROR(Device.synchronousCopyH2D(Host5, DeviceA5.asSlice(), 5)); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); + } + + EXPECT_ERROR(Device.synchronousCopyH2D(Host7, DeviceA5.asSlice(), 7)); +} + +// D2D tests + +TEST_F(DeviceTest, SyncCopyD2DByCount) { + EXPECT_NO_ERROR(Device.synchronousCopyD2D(DeviceA5, DeviceB5, 5)); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB5, I)); + } + + EXPECT_NO_ERROR(Device.synchronousCopyD2D(DeviceA7, DeviceB7, 2)); + for (int I = 0; I < 2; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB7, I)); + } + + EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA5, DeviceB5, 7)); + + EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA7, DeviceB5, 7)); + + EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA5, DeviceB7, 7)); +} + +TEST_F(DeviceTest, SyncCopyD2D) { + EXPECT_NO_ERROR(Device.synchronousCopyD2D(DeviceA5, DeviceB5)); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB5, I)); + } + + EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA7, DeviceB5)); + + EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA5, DeviceB7)); +} + +TEST_F(DeviceTest, SyncCopySliceD2DByCount) { + EXPECT_NO_ERROR( + Device.synchronousCopyD2D(DeviceA5.asSlice().drop_front(1), DeviceB5, 4)); + for (int I = 0; I < 4; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I + 1), getDeviceValue(DeviceB5, I)); + } + + EXPECT_NO_ERROR( + Device.synchronousCopyD2D(DeviceA7.asSlice().drop_back(1), DeviceB7, 2)); + for (int I = 0; I < 2; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB7, I)); + } + + EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB5, 7)); + + EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA7.asSlice(), DeviceB5, 7)); + + EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB7, 7)); +} + +TEST_F(DeviceTest, SyncCopySliceD2D) { + EXPECT_NO_ERROR( + Device.synchronousCopyD2D(DeviceA7.asSlice().drop_back(2), DeviceB5)); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB5, I)); + } + + EXPECT_ERROR( + Device.synchronousCopyD2D(DeviceA7.asSlice().drop_front(1), DeviceB5)); + + EXPECT_ERROR( + Device.synchronousCopyD2D(DeviceA5.asSlice().drop_back(1), DeviceB7)); +} + +TEST_F(DeviceTest, SyncCopyD2DSliceByCount) { + EXPECT_NO_ERROR( + Device.synchronousCopyD2D(DeviceA5, DeviceB7.asSlice().drop_front(2), 5)); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB7, I + 2)); + } + + EXPECT_NO_ERROR( + Device.synchronousCopyD2D(DeviceA7, DeviceB7.asSlice().drop_back(3), 2)); + for (int I = 0; I < 2; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB7, I)); + } + + EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA5, DeviceB5.asSlice(), 7)); + + EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA7, DeviceB5.asSlice(), 7)); + + EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA5, DeviceB7.asSlice(), 7)); +} + +TEST_F(DeviceTest, SyncCopyD2DSlice) { + EXPECT_NO_ERROR( + Device.synchronousCopyD2D(DeviceA5, DeviceB7.asSlice().drop_back(2))); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB7, I)); + } + + EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA7, DeviceB5.asSlice())); + + EXPECT_ERROR(Device.synchronousCopyD2D(DeviceA5, DeviceB7.asSlice())); +} + +TEST_F(DeviceTest, SyncCopySliceD2DSliceByCount) { + EXPECT_NO_ERROR( + Device.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB5.asSlice(), 5)); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB5, I)); + } + + EXPECT_NO_ERROR( + Device.synchronousCopyD2D(DeviceA7.asSlice(), DeviceB7.asSlice(), 2)); + for (int I = 0; I < 2; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB7, I)); + } + + EXPECT_ERROR( + Device.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB5.asSlice(), 7)); + + EXPECT_ERROR( + Device.synchronousCopyD2D(DeviceA7.asSlice(), DeviceB5.asSlice(), 7)); + + EXPECT_ERROR( + Device.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB7.asSlice(), 7)); +} + +TEST_F(DeviceTest, SyncCopySliceD2DSlice) { + EXPECT_NO_ERROR( + Device.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB5.asSlice())); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB5, I)); + } + + EXPECT_ERROR( + Device.synchronousCopyD2D(DeviceA7.asSlice(), DeviceB5.asSlice())); + + EXPECT_ERROR( + Device.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB7.asSlice())); +} + +} // namespace diff --git a/parallel-libs/streamexecutor/unittests/CoreTests/KernelSpecTest.cpp b/parallel-libs/streamexecutor/unittests/CoreTests/KernelSpecTest.cpp new file mode 100644 index 00000000000..fc9eb549968 --- /dev/null +++ b/parallel-libs/streamexecutor/unittests/CoreTests/KernelSpecTest.cpp @@ -0,0 +1,132 @@ +//===-- KernelSpecTest.cpp - Tests for KernelSpec -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the unit tests for the code in KernelSpec. +/// +//===----------------------------------------------------------------------===// + +#include "streamexecutor/KernelSpec.h" + +#include "gtest/gtest.h" + +namespace { + +namespace se = ::streamexecutor; + +TEST(CUDAPTXInMemorySpec, NoCode) { + se::CUDAPTXInMemorySpec Spec("KernelName", {}); + EXPECT_EQ("KernelName", Spec.getKernelName()); + EXPECT_EQ(nullptr, Spec.getCode(1, 0)); +} + +TEST(CUDAPTXInMemorySpec, SingleComputeCapability) { + const char *PTXCodeString = "Dummy PTX code"; + se::CUDAPTXInMemorySpec Spec("KernelName", {{{1, 0}, PTXCodeString}}); + EXPECT_EQ("KernelName", Spec.getKernelName()); + EXPECT_EQ(PTXCodeString, Spec.getCode(1, 0)); + EXPECT_EQ(nullptr, Spec.getCode(2, 0)); +} + +TEST(CUDAPTXInMemorySpec, TwoComputeCapabilities) { + const char *PTXCodeString10 = "Dummy PTX code 10"; + const char *PTXCodeString30 = "Dummy PTX code 30"; + se::CUDAPTXInMemorySpec Spec( + "KernelName", {{{1, 0}, PTXCodeString10}, {{3, 0}, PTXCodeString30}}); + EXPECT_EQ("KernelName", Spec.getKernelName()); + EXPECT_EQ(PTXCodeString10, Spec.getCode(1, 0)); + EXPECT_EQ(PTXCodeString30, Spec.getCode(3, 0)); + EXPECT_EQ(nullptr, Spec.getCode(2, 0)); +} + +TEST(CUDAFatbinInMemorySpec, BasicUsage) { + const char *FatbinBytes = "Dummy fatbin bytes"; + se::CUDAFatbinInMemorySpec Spec("KernelName", FatbinBytes); + EXPECT_EQ("KernelName", Spec.getKernelName()); + EXPECT_EQ(FatbinBytes, Spec.getBytes()); +} + +TEST(OpenCLTextInMemorySpec, BasicUsage) { + const char *OpenCLText = "Dummy OpenCL text"; + se::OpenCLTextInMemorySpec Spec("KernelName", OpenCLText); + EXPECT_EQ("KernelName", Spec.getKernelName()); + EXPECT_EQ(OpenCLText, Spec.getText()); +} + +TEST(MultiKernelLoaderSpec, NoCode) { + se::MultiKernelLoaderSpec MultiSpec; + EXPECT_FALSE(MultiSpec.hasCUDAPTXInMemory()); + EXPECT_FALSE(MultiSpec.hasCUDAFatbinInMemory()); + EXPECT_FALSE(MultiSpec.hasOpenCLTextInMemory()); + + EXPECT_DEBUG_DEATH(MultiSpec.getCUDAPTXInMemory(), + "getting spec that is not present"); + EXPECT_DEBUG_DEATH(MultiSpec.getCUDAFatbinInMemory(), + "getting spec that is not present"); + EXPECT_DEBUG_DEATH(MultiSpec.getOpenCLTextInMemory(), + "getting spec that is not present"); +} + +TEST(MultiKernelLoaderSpec, Registration) { + se::MultiKernelLoaderSpec MultiSpec; + const char *KernelName = "KernelName"; + const char *PTXCodeString = "Dummy PTX code"; + const char *FatbinBytes = "Dummy fatbin bytes"; + const char *OpenCLText = "Dummy OpenCL text"; + + MultiSpec.addCUDAPTXInMemory(KernelName, {{{1, 0}, PTXCodeString}}) + .addCUDAFatbinInMemory(KernelName, FatbinBytes) + .addOpenCLTextInMemory(KernelName, OpenCLText); + + EXPECT_TRUE(MultiSpec.hasCUDAPTXInMemory()); + EXPECT_TRUE(MultiSpec.hasCUDAFatbinInMemory()); + EXPECT_TRUE(MultiSpec.hasOpenCLTextInMemory()); + + EXPECT_EQ(KernelName, MultiSpec.getCUDAPTXInMemory().getKernelName()); + EXPECT_EQ(PTXCodeString, MultiSpec.getCUDAPTXInMemory().getCode(1, 0)); + EXPECT_EQ(nullptr, MultiSpec.getCUDAPTXInMemory().getCode(2, 0)); + + EXPECT_EQ(KernelName, MultiSpec.getCUDAFatbinInMemory().getKernelName()); + EXPECT_EQ(FatbinBytes, MultiSpec.getCUDAFatbinInMemory().getBytes()); + + EXPECT_EQ(KernelName, MultiSpec.getOpenCLTextInMemory().getKernelName()); + EXPECT_EQ(OpenCLText, MultiSpec.getOpenCLTextInMemory().getText()); +} + +TEST(MultiKernelLoaderSpec, RegisterTwice) { + se::MultiKernelLoaderSpec MultiSpec; + const char *KernelName = "KernelName"; + const char *FatbinBytes = "Dummy fatbin bytes"; + + MultiSpec.addCUDAFatbinInMemory(KernelName, FatbinBytes); + + EXPECT_DEBUG_DEATH(MultiSpec.addCUDAFatbinInMemory(KernelName, FatbinBytes), + "illegal loader spec overwrite"); +} + +TEST(MultiKernelLoaderSpec, ConflictingKernelNames) { + se::MultiKernelLoaderSpec MultiSpec; + const char *KernelNameA = "KernelName"; + std::string KernelNameB = KernelNameA; + const char *PTXCodeString = "Dummy PTX code"; + const char *FatbinBytes = "Dummy fatbin bytes"; + + // Check that names don't conflict if they are equivalent strings in different + // locations. + MultiSpec.addCUDAPTXInMemory(KernelNameA, {{{1, 0}, PTXCodeString}}) + .addCUDAFatbinInMemory(KernelNameB, FatbinBytes); + + const char *OtherKernelName = "OtherKernelName"; + const char *OpenCLText = "Dummy OpenCL text"; + EXPECT_DEBUG_DEATH( + MultiSpec.addOpenCLTextInMemory(OtherKernelName, OpenCLText), + "different kernel names in one MultiKernelLoaderSpec"); +} + +} // namespace diff --git a/parallel-libs/streamexecutor/unittests/CoreTests/PackedKernelArgumentArrayTest.cpp b/parallel-libs/streamexecutor/unittests/CoreTests/PackedKernelArgumentArrayTest.cpp new file mode 100644 index 00000000000..dd6d0e1c655 --- /dev/null +++ b/parallel-libs/streamexecutor/unittests/CoreTests/PackedKernelArgumentArrayTest.cpp @@ -0,0 +1,150 @@ +//===-- PackedKernelArgumentArrayTest.cpp - tests for kernel arg packing --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Unit tests for kernel argument packing. +/// +//===----------------------------------------------------------------------===// + +#include "SimpleHostPlatformDevice.h" +#include "streamexecutor/Device.h" +#include "streamexecutor/DeviceMemory.h" +#include "streamexecutor/PackedKernelArgumentArray.h" +#include "streamexecutor/PlatformDevice.h" + +#include "llvm/ADT/Twine.h" + +#include "gtest/gtest.h" + +namespace { + +namespace se = ::streamexecutor; + +using Type = se::KernelArgumentType; + +// Test fixture class for testing argument packing. +// +// Basically defines a bunch of types to be packed so they don't have to be +// defined separately in each test. +class DeviceMemoryPackingTest : public ::testing::Test { +public: + DeviceMemoryPackingTest() + : Device(&PDevice), Value(42), Handle(&Value), ByteCount(15), + ElementCount(5), + TypedGlobal(getOrDie(Device.allocateDeviceMemory(ElementCount))), + TypedShared( + se::SharedDeviceMemory::makeFromElementCount(ElementCount)) {} + + se::test::SimpleHostPlatformDevice PDevice; + se::Device Device; + int Value; + void *Handle; + size_t ByteCount; + size_t ElementCount; + se::GlobalDeviceMemory TypedGlobal; + se::SharedDeviceMemory TypedShared; +}; + +// Utility method to check the expected address, size, and type for a packed +// argument at the given index of a PackedKernelArgumentArray. +template +static void +ExpectEqual(const void *ExpectedAddress, size_t ExpectedSize, Type ExpectedType, + const se::PackedKernelArgumentArray &Observed, + size_t Index) { + SCOPED_TRACE(("Index = " + llvm::Twine(Index)).str()); + EXPECT_EQ(ExpectedAddress, Observed.getAddress(Index)); + EXPECT_EQ(ExpectedAddress, Observed.getAddresses()[Index]); + EXPECT_EQ(ExpectedSize, Observed.getSize(Index)); + EXPECT_EQ(ExpectedSize, Observed.getSizes()[Index]); + EXPECT_EQ(ExpectedType, Observed.getType(Index)); + EXPECT_EQ(ExpectedType, Observed.getTypes()[Index]); +} + +TEST_F(DeviceMemoryPackingTest, SingleValue) { + auto Array = se::make_kernel_argument_pack(Value); + ExpectEqual(&Value, sizeof(Value), Type::VALUE, Array, 0); + EXPECT_EQ(1u, Array.getArgumentCount()); + EXPECT_EQ(0u, Array.getSharedCount()); +} + +TEST_F(DeviceMemoryPackingTest, SingleTypedGlobal) { + auto Array = se::make_kernel_argument_pack(TypedGlobal); + ExpectEqual(TypedGlobal.getHandle(), sizeof(void *), + Type::GLOBAL_DEVICE_MEMORY, Array, 0); + EXPECT_EQ(1u, Array.getArgumentCount()); + EXPECT_EQ(0u, Array.getSharedCount()); +} + +TEST_F(DeviceMemoryPackingTest, SingleTypedGlobalPointer) { + auto Array = se::make_kernel_argument_pack(&TypedGlobal); + ExpectEqual(TypedGlobal.getHandle(), sizeof(void *), + Type::GLOBAL_DEVICE_MEMORY, Array, 0); + EXPECT_EQ(1u, Array.getArgumentCount()); + EXPECT_EQ(0u, Array.getSharedCount()); +} + +TEST_F(DeviceMemoryPackingTest, SingleConstTypedGlobalPointer) { + const se::GlobalDeviceMemory *ArgumentPointer = &TypedGlobal; + auto Array = se::make_kernel_argument_pack(ArgumentPointer); + ExpectEqual(TypedGlobal.getHandle(), sizeof(void *), + Type::GLOBAL_DEVICE_MEMORY, Array, 0); + EXPECT_EQ(1u, Array.getArgumentCount()); + EXPECT_EQ(0u, Array.getSharedCount()); +} + +TEST_F(DeviceMemoryPackingTest, SingleTypedShared) { + auto Array = se::make_kernel_argument_pack(TypedShared); + ExpectEqual(nullptr, TypedShared.getByteCount(), Type::SHARED_DEVICE_MEMORY, + Array, 0); + EXPECT_EQ(1u, Array.getArgumentCount()); + EXPECT_EQ(1u, Array.getSharedCount()); +} + +TEST_F(DeviceMemoryPackingTest, SingleTypedSharedPointer) { + auto Array = se::make_kernel_argument_pack(&TypedShared); + ExpectEqual(nullptr, TypedShared.getByteCount(), Type::SHARED_DEVICE_MEMORY, + Array, 0); + EXPECT_EQ(1u, Array.getArgumentCount()); + EXPECT_EQ(1u, Array.getSharedCount()); +} + +TEST_F(DeviceMemoryPackingTest, SingleConstTypedSharedPointer) { + const se::SharedDeviceMemory *ArgumentPointer = &TypedShared; + auto Array = se::make_kernel_argument_pack(ArgumentPointer); + ExpectEqual(nullptr, TypedShared.getByteCount(), Type::SHARED_DEVICE_MEMORY, + Array, 0); + EXPECT_EQ(1u, Array.getArgumentCount()); + EXPECT_EQ(1u, Array.getSharedCount()); +} + +TEST_F(DeviceMemoryPackingTest, PackSeveralArguments) { + const se::GlobalDeviceMemory *TypedGlobalPointer = &TypedGlobal; + const se::SharedDeviceMemory *TypedSharedPointer = &TypedShared; + auto Array = se::make_kernel_argument_pack(Value, TypedGlobal, &TypedGlobal, + TypedGlobalPointer, TypedShared, + &TypedShared, TypedSharedPointer); + ExpectEqual(&Value, sizeof(Value), Type::VALUE, Array, 0); + ExpectEqual(TypedGlobal.getHandle(), sizeof(void *), + Type::GLOBAL_DEVICE_MEMORY, Array, 1); + ExpectEqual(TypedGlobal.getHandle(), sizeof(void *), + Type::GLOBAL_DEVICE_MEMORY, Array, 2); + ExpectEqual(TypedGlobal.getHandle(), sizeof(void *), + Type::GLOBAL_DEVICE_MEMORY, Array, 3); + ExpectEqual(nullptr, TypedShared.getByteCount(), Type::SHARED_DEVICE_MEMORY, + Array, 4); + ExpectEqual(nullptr, TypedShared.getByteCount(), Type::SHARED_DEVICE_MEMORY, + Array, 5); + ExpectEqual(nullptr, TypedShared.getByteCount(), Type::SHARED_DEVICE_MEMORY, + Array, 6); + EXPECT_EQ(7u, Array.getArgumentCount()); + EXPECT_EQ(3u, Array.getSharedCount()); +} + +} // namespace diff --git a/parallel-libs/streamexecutor/unittests/CoreTests/SimpleHostPlatformDevice.h b/parallel-libs/streamexecutor/unittests/CoreTests/SimpleHostPlatformDevice.h new file mode 100644 index 00000000000..5c5953098c4 --- /dev/null +++ b/parallel-libs/streamexecutor/unittests/CoreTests/SimpleHostPlatformDevice.h @@ -0,0 +1,148 @@ +//===-- SimpleHostPlatformDevice.h - Host device for testing ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// The SimpleHostPlatformDevice class is a streamexecutor::PlatformDevice that +/// is really just the host processor and memory. It is useful for testing +/// because no extra device platform is required. +/// +//===----------------------------------------------------------------------===// + +#ifndef STREAMEXECUTOR_LIB_UNITTESTS_SIMPLEHOSTPLATFORMDEVICE_H +#define STREAMEXECUTOR_LIB_UNITTESTS_SIMPLEHOSTPLATFORMDEVICE_H + +#include +#include + +#include "streamexecutor/PlatformDevice.h" + +namespace streamexecutor { +namespace test { + +/// A streamexecutor::PlatformDevice that simply forwards all operations to the +/// host platform. +/// +/// The allocate and copy methods are simple wrappers for std::malloc and +/// std::memcpy. +class SimpleHostPlatformDevice : public streamexecutor::PlatformDevice { +public: + std::string getName() const override { return "SimpleHostPlatformDevice"; } + + streamexecutor::Expected createStream() override { + return nullptr; + } + + streamexecutor::Expected + allocateDeviceMemory(size_t ByteCount) override { + return std::malloc(ByteCount); + } + + streamexecutor::Error freeDeviceMemory(const void *Handle) override { + std::free(const_cast(Handle)); + return streamexecutor::Error::success(); + } + + streamexecutor::Expected + allocateHostMemory(size_t ByteCount) override { + return std::malloc(ByteCount); + } + + streamexecutor::Error freeHostMemory(void *Memory) override { + std::free(const_cast(Memory)); + return streamexecutor::Error::success(); + } + + streamexecutor::Error registerHostMemory(void *Memory, + size_t ByteCount) override { + return streamexecutor::Error::success(); + } + + streamexecutor::Error unregisterHostMemory(void *Memory) override { + return streamexecutor::Error::success(); + } + + streamexecutor::Error copyD2H(const void *StreamHandle, + const void *DeviceHandleSrc, + size_t SrcByteOffset, void *HostDst, + size_t DstByteOffset, + size_t ByteCount) override { + std::memcpy(static_cast(HostDst) + DstByteOffset, + static_cast(DeviceHandleSrc) + SrcByteOffset, + ByteCount); + return streamexecutor::Error::success(); + } + + streamexecutor::Error copyH2D(const void *StreamHandle, const void *HostSrc, + size_t SrcByteOffset, + const void *DeviceHandleDst, + size_t DstByteOffset, + size_t ByteCount) override { + std::memcpy(static_cast(const_cast(DeviceHandleDst)) + + DstByteOffset, + static_cast(HostSrc) + SrcByteOffset, ByteCount); + return streamexecutor::Error::success(); + } + + streamexecutor::Error + copyD2D(const void *StreamHandle, const void *DeviceHandleSrc, + size_t SrcByteOffset, const void *DeviceHandleDst, + size_t DstByteOffset, size_t ByteCount) override { + std::memcpy(static_cast(const_cast(DeviceHandleDst)) + + DstByteOffset, + static_cast(DeviceHandleSrc) + SrcByteOffset, + ByteCount); + return streamexecutor::Error::success(); + } + + streamexecutor::Error synchronousCopyD2H(const void *DeviceHandleSrc, + size_t SrcByteOffset, void *HostDst, + size_t DstByteOffset, + size_t ByteCount) override { + std::memcpy(static_cast(HostDst) + DstByteOffset, + static_cast(DeviceHandleSrc) + SrcByteOffset, + ByteCount); + return streamexecutor::Error::success(); + } + + streamexecutor::Error synchronousCopyH2D(const void *HostSrc, + size_t SrcByteOffset, + const void *DeviceHandleDst, + size_t DstByteOffset, + size_t ByteCount) override { + std::memcpy(static_cast(const_cast(DeviceHandleDst)) + + DstByteOffset, + static_cast(HostSrc) + SrcByteOffset, ByteCount); + return streamexecutor::Error::success(); + } + + streamexecutor::Error synchronousCopyD2D(const void *DeviceHandleSrc, + size_t SrcByteOffset, + const void *DeviceHandleDst, + size_t DstByteOffset, + size_t ByteCount) override { + std::memcpy(static_cast(const_cast(DeviceHandleDst)) + + DstByteOffset, + static_cast(DeviceHandleSrc) + SrcByteOffset, + ByteCount); + return streamexecutor::Error::success(); + } + + /// Gets the value at the given index from a GlobalDeviceMemory instance + /// created by this class. + template + static T getDeviceValue(const streamexecutor::GlobalDeviceMemory &Memory, + size_t Index) { + return static_cast(Memory.getHandle())[Index]; + } +}; + +} // namespace test +} // namespace streamexecutor + +#endif // STREAMEXECUTOR_LIB_UNITTESTS_SIMPLEHOSTPLATFORMDEVICE_H diff --git a/parallel-libs/streamexecutor/unittests/CoreTests/StreamTest.cpp b/parallel-libs/streamexecutor/unittests/CoreTests/StreamTest.cpp new file mode 100644 index 00000000000..65598540d67 --- /dev/null +++ b/parallel-libs/streamexecutor/unittests/CoreTests/StreamTest.cpp @@ -0,0 +1,362 @@ +//===-- StreamTest.cpp - Tests for Stream ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the unit tests for Stream code. +/// +//===----------------------------------------------------------------------===// + +#include + +#include "SimpleHostPlatformDevice.h" +#include "streamexecutor/Device.h" +#include "streamexecutor/Kernel.h" +#include "streamexecutor/KernelSpec.h" +#include "streamexecutor/PlatformDevice.h" +#include "streamexecutor/Stream.h" + +#include "gtest/gtest.h" + +namespace { + +namespace se = ::streamexecutor; + +const auto &getDeviceValue = + se::test::SimpleHostPlatformDevice::getDeviceValue; + +/// Test fixture to hold objects used by tests. +class StreamTest : public ::testing::Test { +public: + StreamTest() + : DummyPlatformStream(1), Device(&PDevice), + Stream(&PDevice, &DummyPlatformStream), HostA5{0, 1, 2, 3, 4}, + HostB5{5, 6, 7, 8, 9}, HostA7{10, 11, 12, 13, 14, 15, 16}, + HostB7{17, 18, 19, 20, 21, 22, 23}, Host5{24, 25, 26, 27, 28}, + Host7{29, 30, 31, 32, 33, 34, 35}, + DeviceA5(getOrDie(Device.allocateDeviceMemory(5))), + DeviceB5(getOrDie(Device.allocateDeviceMemory(5))), + DeviceA7(getOrDie(Device.allocateDeviceMemory(7))), + DeviceB7(getOrDie(Device.allocateDeviceMemory(7))) { + se::dieIfError(Device.synchronousCopyH2D(HostA5, DeviceA5)); + se::dieIfError(Device.synchronousCopyH2D(HostB5, DeviceB5)); + se::dieIfError(Device.synchronousCopyH2D(HostA7, DeviceA7)); + se::dieIfError(Device.synchronousCopyH2D(HostB7, DeviceB7)); + } + +protected: + int DummyPlatformStream; // Mimicking a platform where the platform stream + // handle is just a stream number. + se::test::SimpleHostPlatformDevice PDevice; + se::Device Device; + se::Stream Stream; + + // Device memory is matched by host arrays. + int HostA5[5]; + int HostB5[5]; + int HostA7[7]; + int HostB7[7]; + + // Host memory to be used as actual host memory. + int Host5[5]; + int Host7[7]; + + // Device memory. + se::GlobalDeviceMemory DeviceA5; + se::GlobalDeviceMemory DeviceB5; + se::GlobalDeviceMemory DeviceA7; + se::GlobalDeviceMemory DeviceB7; +}; + +using llvm::ArrayRef; +using llvm::MutableArrayRef; + +// D2H tests + +TEST_F(StreamTest, CopyD2HToMutableArrayRefByCount) { + Stream.thenCopyD2H(DeviceA5, MutableArrayRef(Host5), 5); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(HostA5[I], Host5[I]); + } + + Stream.thenCopyD2H(DeviceB5, MutableArrayRef(Host5), 2); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 2; ++I) { + EXPECT_EQ(HostB5[I], Host5[I]); + } + + Stream.thenCopyD2H(DeviceA7, MutableArrayRef(Host5), 7); + EXPECT_FALSE(Stream.isOK()); +} + +TEST_F(StreamTest, CopyD2HToMutableArrayRef) { + Stream.thenCopyD2H(DeviceA5, MutableArrayRef(Host5)); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(HostA5[I], Host5[I]); + } + + Stream.thenCopyD2H(DeviceA5, MutableArrayRef(Host7)); + EXPECT_FALSE(Stream.isOK()); +} + +TEST_F(StreamTest, CopyD2HToPointer) { + Stream.thenCopyD2H(DeviceA5, Host5, 5); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(HostA5[I], Host5[I]); + } + + Stream.thenCopyD2H(DeviceA5, Host7, 7); + EXPECT_FALSE(Stream.isOK()); +} + +TEST_F(StreamTest, CopyD2HSliceToMutableArrayRefByCount) { + Stream.thenCopyD2H(DeviceA5.asSlice().drop_front(1), + MutableArrayRef(Host5 + 1, 4), 4); + EXPECT_TRUE(Stream.isOK()); + for (int I = 1; I < 5; ++I) { + EXPECT_EQ(HostA5[I], Host5[I]); + } + + Stream.thenCopyD2H(DeviceB5.asSlice().drop_back(1), + MutableArrayRef(Host5), 2); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 2; ++I) { + EXPECT_EQ(HostB5[I], Host5[I]); + } + + Stream.thenCopyD2H(DeviceA5.asSlice(), MutableArrayRef(Host7), 7); + EXPECT_FALSE(Stream.isOK()); +} + +TEST_F(StreamTest, CopyD2HSliceToMutableArrayRef) { + Stream.thenCopyD2H(DeviceA7.asSlice().slice(1, 5), + MutableArrayRef(Host5)); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(HostA7[I + 1], Host5[I]); + } + + Stream.thenCopyD2H(DeviceA5.asSlice(), MutableArrayRef(Host7)); + EXPECT_FALSE(Stream.isOK()); +} + +TEST_F(StreamTest, CopyD2HSliceToPointer) { + Stream.thenCopyD2H(DeviceA5.asSlice().drop_front(1), Host5 + 1, 4); + EXPECT_TRUE(Stream.isOK()); + for (int I = 1; I < 5; ++I) { + EXPECT_EQ(HostA5[I], Host5[I]); + } + + Stream.thenCopyD2H(DeviceA5.asSlice(), Host7, 7); + EXPECT_FALSE(Stream.isOK()); +} + +// H2D tests + +TEST_F(StreamTest, CopyH2DToArrayRefByCount) { + Stream.thenCopyH2D(ArrayRef(Host5), DeviceA5, 5); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); + } + + Stream.thenCopyH2D(ArrayRef(Host5), DeviceB5, 2); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 2; ++I) { + EXPECT_EQ(getDeviceValue(DeviceB5, I), Host5[I]); + } + + Stream.thenCopyH2D(ArrayRef(Host7), DeviceA5, 7); + EXPECT_FALSE(Stream.isOK()); +} + +TEST_F(StreamTest, CopyH2DToArrayRef) { + Stream.thenCopyH2D(ArrayRef(Host5), DeviceA5); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); + } + + Stream.thenCopyH2D(ArrayRef(Host7), DeviceA5); + EXPECT_FALSE(Stream.isOK()); +} + +TEST_F(StreamTest, CopyH2DToPointer) { + Stream.thenCopyH2D(Host5, DeviceA5, 5); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); + } + + Stream.thenCopyH2D(Host7, DeviceA5, 7); + EXPECT_FALSE(Stream.isOK()); +} + +TEST_F(StreamTest, CopyH2DSliceToArrayRefByCount) { + Stream.thenCopyH2D(ArrayRef(Host5 + 1, 4), + DeviceA5.asSlice().drop_front(1), 4); + EXPECT_TRUE(Stream.isOK()); + for (int I = 1; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); + } + + Stream.thenCopyH2D(ArrayRef(Host5), DeviceB5.asSlice().drop_back(1), 2); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 2; ++I) { + EXPECT_EQ(getDeviceValue(DeviceB5, I), Host5[I]); + } + + Stream.thenCopyH2D(ArrayRef(Host5), DeviceA5.asSlice(), 7); + EXPECT_FALSE(Stream.isOK()); +} + +TEST_F(StreamTest, CopyH2DSliceToArrayRef) { + + Stream.thenCopyH2D(ArrayRef(Host5), DeviceA5.asSlice()); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); + } + + Stream.thenCopyH2D(ArrayRef(Host7), DeviceA5.asSlice()); + EXPECT_FALSE(Stream.isOK()); +} + +TEST_F(StreamTest, CopyH2DSliceToPointer) { + Stream.thenCopyH2D(Host5, DeviceA5.asSlice(), 5); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), Host5[I]); + } + + Stream.thenCopyH2D(Host7, DeviceA5.asSlice(), 7); + EXPECT_FALSE(Stream.isOK()); +} + +// D2D tests + +TEST_F(StreamTest, CopyD2DByCount) { + Stream.thenCopyD2D(DeviceA5, DeviceB5, 5); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB5, I)); + } + + Stream.thenCopyD2D(DeviceA7, DeviceB7, 2); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 2; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB7, I)); + } + + Stream.thenCopyD2D(DeviceA7, DeviceB5, 7); + EXPECT_FALSE(Stream.isOK()); +} + +TEST_F(StreamTest, CopyD2D) { + Stream.thenCopyD2D(DeviceA5, DeviceB5); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB5, I)); + } + + Stream.thenCopyD2D(DeviceA7, DeviceB5); + EXPECT_FALSE(Stream.isOK()); +} + +TEST_F(StreamTest, CopySliceD2DByCount) { + Stream.thenCopyD2D(DeviceA5.asSlice().drop_front(1), DeviceB5, 4); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 4; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I + 1), getDeviceValue(DeviceB5, I)); + } + + Stream.thenCopyD2D(DeviceA7.asSlice().drop_back(1), DeviceB7, 2); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 2; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB7, I)); + } + + Stream.thenCopyD2D(DeviceA5.asSlice(), DeviceB5, 7); + EXPECT_FALSE(Stream.isOK()); +} + +TEST_F(StreamTest, CopySliceD2D) { + + Stream.thenCopyD2D(DeviceA7.asSlice().drop_back(2), DeviceB5); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB5, I)); + } + + Stream.thenCopyD2D(DeviceA5.asSlice().drop_back(1), DeviceB7); + EXPECT_FALSE(Stream.isOK()); +} + +TEST_F(StreamTest, CopyD2DSliceByCount) { + Stream.thenCopyD2D(DeviceA5, DeviceB7.asSlice().drop_front(2), 5); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB7, I + 2)); + } + + Stream.thenCopyD2D(DeviceA7, DeviceB7.asSlice().drop_back(3), 2); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 2; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB7, I)); + } + + Stream.thenCopyD2D(DeviceA5, DeviceB7.asSlice(), 7); + EXPECT_FALSE(Stream.isOK()); +} + +TEST_F(StreamTest, CopyD2DSlice) { + + Stream.thenCopyD2D(DeviceA5, DeviceB7.asSlice().drop_back(2)); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB7, I)); + } + + Stream.thenCopyD2D(DeviceA5, DeviceB7.asSlice()); + EXPECT_FALSE(Stream.isOK()); +} + +TEST_F(StreamTest, CopySliceD2DSliceByCount) { + + Stream.thenCopyD2D(DeviceA5.asSlice(), DeviceB5.asSlice(), 5); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB5, I)); + } + + Stream.thenCopyD2D(DeviceA7.asSlice(), DeviceB7.asSlice(), 2); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 2; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA7, I), getDeviceValue(DeviceB7, I)); + } + + Stream.thenCopyD2D(DeviceA7.asSlice(), DeviceB5.asSlice(), 7); + EXPECT_FALSE(Stream.isOK()); +} + +TEST_F(StreamTest, CopySliceD2DSlice) { + + Stream.thenCopyD2D(DeviceA5.asSlice(), DeviceB5.asSlice()); + EXPECT_TRUE(Stream.isOK()); + for (int I = 0; I < 5; ++I) { + EXPECT_EQ(getDeviceValue(DeviceA5, I), getDeviceValue(DeviceB5, I)); + } + + Stream.thenCopyD2D(DeviceA5.asSlice(), DeviceB7.asSlice()); + EXPECT_FALSE(Stream.isOK()); +} + +} // namespace -- cgit v1.2.3