summaryrefslogtreecommitdiffstats
path: root/parallel-libs/streamexecutor/lib
diff options
context:
space:
mode:
Diffstat (limited to 'parallel-libs/streamexecutor/lib')
-rw-r--r--parallel-libs/streamexecutor/lib/Utils/Error.cpp6
-rw-r--r--parallel-libs/streamexecutor/lib/unittests/CMakeLists.txt10
-rw-r--r--parallel-libs/streamexecutor/lib/unittests/ExecutorTest.cpp451
-rw-r--r--parallel-libs/streamexecutor/lib/unittests/StreamTest.cpp340
4 files changed, 773 insertions, 34 deletions
diff --git a/parallel-libs/streamexecutor/lib/Utils/Error.cpp b/parallel-libs/streamexecutor/lib/Utils/Error.cpp
index 78912c531ae..f3d09673c21 100644
--- a/parallel-libs/streamexecutor/lib/Utils/Error.cpp
+++ b/parallel-libs/streamexecutor/lib/Utils/Error.cpp
@@ -27,7 +27,7 @@ public:
std::error_code convertToErrorCode() const override {
llvm_unreachable(
- "StreamExecutorError does not support convertion to std::error_code");
+ "StreamExecutorError does not support conversion to std::error_code");
}
std::string getErrorMessage() const { return Message; }
@@ -44,8 +44,8 @@ char StreamExecutorError::ID = 0;
namespace streamexecutor {
-Error make_error(StringRef Message) {
- return llvm::make_error<StreamExecutorError>(Message);
+Error make_error(Twine Message) {
+ return llvm::make_error<StreamExecutorError>(Message.str());
}
std::string consumeAndGetMessage(Error &&E) {
diff --git a/parallel-libs/streamexecutor/lib/unittests/CMakeLists.txt b/parallel-libs/streamexecutor/lib/unittests/CMakeLists.txt
index f6e6edbebfd..244312ff12c 100644
--- a/parallel-libs/streamexecutor/lib/unittests/CMakeLists.txt
+++ b/parallel-libs/streamexecutor/lib/unittests/CMakeLists.txt
@@ -1,4 +1,14 @@
add_executable(
+ executor_test
+ ExecutorTest.cpp)
+target_link_libraries(
+ executor_test
+ streamexecutor
+ ${GTEST_BOTH_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT})
+add_test(ExecutorTest executor_test)
+
+add_executable(
kernel_test
KernelTest.cpp)
target_link_libraries(
diff --git a/parallel-libs/streamexecutor/lib/unittests/ExecutorTest.cpp b/parallel-libs/streamexecutor/lib/unittests/ExecutorTest.cpp
new file mode 100644
index 00000000000..d2d03fb6c88
--- /dev/null
+++ b/parallel-libs/streamexecutor/lib/unittests/ExecutorTest.cpp
@@ -0,0 +1,451 @@
+//===-- ExecutorTest.cpp - Tests for Executor -----------------------------===//
+//
+// 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 Executor code.
+///
+//===----------------------------------------------------------------------===//
+
+#include <cstdlib>
+#include <cstring>
+
+#include "streamexecutor/Executor.h"
+#include "streamexecutor/PlatformInterfaces.h"
+
+#include "gtest/gtest.h"
+
+namespace {
+
+namespace se = ::streamexecutor;
+
+class MockPlatformExecutor : public se::PlatformExecutor {
+public:
+ ~MockPlatformExecutor() override {}
+
+ std::string getName() const override { return "MockPlatformExecutor"; }
+
+ se::Expected<std::unique_ptr<se::PlatformStreamHandle>>
+ createStream() override {
+ return se::make_error("not implemented");
+ }
+
+ se::Expected<se::GlobalDeviceMemoryBase>
+ allocateDeviceMemory(size_t ByteCount) override {
+ return se::GlobalDeviceMemoryBase(std::malloc(ByteCount));
+ }
+
+ se::Error freeDeviceMemory(se::GlobalDeviceMemoryBase Memory) override {
+ std::free(const_cast<void *>(Memory.getHandle()));
+ return se::Error::success();
+ }
+
+ se::Expected<void *> allocateHostMemory(size_t ByteCount) override {
+ return std::malloc(ByteCount);
+ }
+
+ se::Error freeHostMemory(void *Memory) override {
+ std::free(Memory);
+ return se::Error::success();
+ }
+
+ se::Error synchronousCopyD2H(const se::GlobalDeviceMemoryBase &DeviceSrc,
+ size_t SrcByteOffset, void *HostDst,
+ size_t DstByteOffset,
+ size_t ByteCount) override {
+ std::memcpy(static_cast<char *>(HostDst) + DstByteOffset,
+ static_cast<const char *>(DeviceSrc.getHandle()) +
+ SrcByteOffset,
+ ByteCount);
+ return se::Error::success();
+ }
+
+ se::Error synchronousCopyH2D(const void *HostSrc, size_t SrcByteOffset,
+ se::GlobalDeviceMemoryBase DeviceDst,
+ size_t DstByteOffset,
+ size_t ByteCount) override {
+ std::memcpy(static_cast<char *>(const_cast<void *>(DeviceDst.getHandle())) +
+ DstByteOffset,
+ static_cast<const char *>(HostSrc) + SrcByteOffset, ByteCount);
+ return se::Error::success();
+ }
+
+ se::Error synchronousCopyD2D(se::GlobalDeviceMemoryBase DeviceDst,
+ size_t DstByteOffset,
+ const se::GlobalDeviceMemoryBase &DeviceSrc,
+ size_t SrcByteOffset,
+ size_t ByteCount) override {
+ std::memcpy(static_cast<char *>(const_cast<void *>(DeviceDst.getHandle())) +
+ DstByteOffset,
+ static_cast<const char *>(DeviceSrc.getHandle()) +
+ SrcByteOffset,
+ ByteCount);
+ return se::Error::success();
+ }
+};
+
+/// Test fixture to hold objects used by tests.
+class ExecutorTest : public ::testing::Test {
+public:
+ ExecutorTest()
+ : 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(se::GlobalDeviceMemory<int>::makeFromElementCount(HostA5, 5)),
+ DeviceB5(se::GlobalDeviceMemory<int>::makeFromElementCount(HostB5, 5)),
+ DeviceA7(se::GlobalDeviceMemory<int>::makeFromElementCount(HostA7, 7)),
+ DeviceB7(se::GlobalDeviceMemory<int>::makeFromElementCount(HostB7, 7)),
+ Host5{24, 25, 26, 27, 28}, Host7{29, 30, 31, 32, 33, 34, 35},
+ Executor(&PExecutor) {}
+
+ // Device memory is backed by host arrays.
+ int HostA5[5];
+ int HostB5[5];
+ int HostA7[7];
+ int HostB7[7];
+ se::GlobalDeviceMemory<int> DeviceA5;
+ se::GlobalDeviceMemory<int> DeviceB5;
+ se::GlobalDeviceMemory<int> DeviceA7;
+ se::GlobalDeviceMemory<int> DeviceB7;
+
+ // Host memory to be used as actual host memory.
+ int Host5[5];
+ int Host7[7];
+
+ MockPlatformExecutor PExecutor;
+ se::Executor Executor;
+};
+
+#define EXPECT_NO_ERROR(E) EXPECT_FALSE(static_cast<bool>(E))
+#define EXPECT_ERROR(E) \
+ do { \
+ se::Error E__ = E; \
+ EXPECT_TRUE(static_cast<bool>(E__)); \
+ consumeError(std::move(E__)); \
+ } while (false)
+
+using llvm::ArrayRef;
+using llvm::MutableArrayRef;
+
+// D2H tests
+
+TEST_F(ExecutorTest, SyncCopyD2HToMutableArrayRefByCount) {
+ EXPECT_NO_ERROR(
+ Executor.synchronousCopyD2H(DeviceA5, MutableArrayRef<int>(Host5), 5));
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], Host5[I]);
+ }
+
+ EXPECT_NO_ERROR(
+ Executor.synchronousCopyD2H(DeviceB5, MutableArrayRef<int>(Host5), 2));
+ for (int I = 0; I < 2; ++I) {
+ EXPECT_EQ(HostB5[I], Host5[I]);
+ }
+
+ EXPECT_ERROR(
+ Executor.synchronousCopyD2H(DeviceA7, MutableArrayRef<int>(Host5), 7));
+
+ EXPECT_ERROR(
+ Executor.synchronousCopyD2H(DeviceA5, MutableArrayRef<int>(Host7), 7));
+
+ EXPECT_ERROR(
+ Executor.synchronousCopyD2H(DeviceA5, MutableArrayRef<int>(Host5), 7));
+}
+
+TEST_F(ExecutorTest, SyncCopyD2HToMutableArrayRef) {
+ EXPECT_NO_ERROR(
+ Executor.synchronousCopyD2H(DeviceA5, MutableArrayRef<int>(Host5)));
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], Host5[I]);
+ }
+
+ EXPECT_ERROR(
+ Executor.synchronousCopyD2H(DeviceA7, MutableArrayRef<int>(Host5)));
+
+ EXPECT_ERROR(
+ Executor.synchronousCopyD2H(DeviceA5, MutableArrayRef<int>(Host7)));
+}
+
+TEST_F(ExecutorTest, SyncCopyD2HToPointer) {
+ EXPECT_NO_ERROR(Executor.synchronousCopyD2H(DeviceA5, Host5, 5));
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], Host5[I]);
+ }
+
+ EXPECT_ERROR(Executor.synchronousCopyD2H(DeviceA5, Host7, 7));
+}
+
+TEST_F(ExecutorTest, SyncCopyD2HSliceToMutableArrayRefByCount) {
+ EXPECT_NO_ERROR(Executor.synchronousCopyD2H(
+ DeviceA5.asSlice().drop_front(1), MutableArrayRef<int>(Host5 + 1, 4), 4));
+ for (int I = 1; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], Host5[I]);
+ }
+
+ EXPECT_NO_ERROR(Executor.synchronousCopyD2H(DeviceB5.asSlice().drop_back(1),
+ MutableArrayRef<int>(Host5), 2));
+ for (int I = 0; I < 2; ++I) {
+ EXPECT_EQ(HostB5[I], Host5[I]);
+ }
+
+ EXPECT_ERROR(Executor.synchronousCopyD2H(DeviceA7.asSlice(),
+ MutableArrayRef<int>(Host5), 7));
+
+ EXPECT_ERROR(Executor.synchronousCopyD2H(DeviceA5.asSlice(),
+ MutableArrayRef<int>(Host7), 7));
+
+ EXPECT_ERROR(Executor.synchronousCopyD2H(DeviceA5.asSlice(),
+ MutableArrayRef<int>(Host5), 7));
+}
+
+TEST_F(ExecutorTest, SyncCopyD2HSliceToMutableArrayRef) {
+ EXPECT_NO_ERROR(Executor.synchronousCopyD2H(DeviceA7.asSlice().slice(1, 5),
+ MutableArrayRef<int>(Host5)));
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA7[I + 1], Host5[I]);
+ }
+
+ EXPECT_ERROR(Executor.synchronousCopyD2H(DeviceA7.asSlice().drop_back(1),
+ MutableArrayRef<int>(Host5)));
+
+ EXPECT_ERROR(Executor.synchronousCopyD2H(DeviceA5.asSlice(),
+ MutableArrayRef<int>(Host7)));
+}
+
+TEST_F(ExecutorTest, SyncCopyD2HSliceToPointer) {
+ EXPECT_NO_ERROR(Executor.synchronousCopyD2H(DeviceA5.asSlice().drop_front(1),
+ Host5 + 1, 4));
+ for (int I = 1; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], Host5[I]);
+ }
+
+ EXPECT_ERROR(Executor.synchronousCopyD2H(DeviceA5.asSlice(), Host7, 7));
+}
+
+// H2D tests
+
+TEST_F(ExecutorTest, SyncCopyH2DToArrayRefByCount) {
+ EXPECT_NO_ERROR(
+ Executor.synchronousCopyH2D(ArrayRef<int>(Host5), DeviceA5, 5));
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], Host5[I]);
+ }
+
+ EXPECT_NO_ERROR(
+ Executor.synchronousCopyH2D(ArrayRef<int>(Host5), DeviceB5, 2));
+ for (int I = 0; I < 2; ++I) {
+ EXPECT_EQ(HostB5[I], Host5[I]);
+ }
+
+ EXPECT_ERROR(Executor.synchronousCopyH2D(ArrayRef<int>(Host7), DeviceA5, 7));
+
+ EXPECT_ERROR(Executor.synchronousCopyH2D(ArrayRef<int>(Host5), DeviceA7, 7));
+
+ EXPECT_ERROR(Executor.synchronousCopyH2D(ArrayRef<int>(Host5), DeviceA5, 7));
+}
+
+TEST_F(ExecutorTest, SyncCopyH2DToArrayRef) {
+ EXPECT_NO_ERROR(Executor.synchronousCopyH2D(ArrayRef<int>(Host5), DeviceA5));
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], Host5[I]);
+ }
+
+ EXPECT_ERROR(Executor.synchronousCopyH2D(ArrayRef<int>(Host5), DeviceA7));
+
+ EXPECT_ERROR(Executor.synchronousCopyH2D(ArrayRef<int>(Host7), DeviceA5));
+}
+
+TEST_F(ExecutorTest, SyncCopyH2DToPointer) {
+ EXPECT_NO_ERROR(Executor.synchronousCopyH2D(Host5, DeviceA5, 5));
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], Host5[I]);
+ }
+
+ EXPECT_ERROR(Executor.synchronousCopyH2D(Host7, DeviceA5, 7));
+}
+
+TEST_F(ExecutorTest, SyncCopyH2DSliceToArrayRefByCount) {
+ EXPECT_NO_ERROR(Executor.synchronousCopyH2D(
+ ArrayRef<int>(Host5 + 1, 4), DeviceA5.asSlice().drop_front(1), 4));
+ for (int I = 1; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], Host5[I]);
+ }
+
+ EXPECT_NO_ERROR(Executor.synchronousCopyH2D(
+ ArrayRef<int>(Host5), DeviceB5.asSlice().drop_back(1), 2));
+ for (int I = 0; I < 2; ++I) {
+ EXPECT_EQ(HostB5[I], Host5[I]);
+ }
+
+ EXPECT_ERROR(
+ Executor.synchronousCopyH2D(ArrayRef<int>(Host7), DeviceA5.asSlice(), 7));
+
+ EXPECT_ERROR(
+ Executor.synchronousCopyH2D(ArrayRef<int>(Host5), DeviceA7.asSlice(), 7));
+
+ EXPECT_ERROR(
+ Executor.synchronousCopyH2D(ArrayRef<int>(Host5), DeviceA5.asSlice(), 7));
+}
+
+TEST_F(ExecutorTest, SyncCopyH2DSliceToArrayRef) {
+ EXPECT_NO_ERROR(
+ Executor.synchronousCopyH2D(ArrayRef<int>(Host5), DeviceA5.asSlice()));
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], Host5[I]);
+ }
+
+ EXPECT_ERROR(
+ Executor.synchronousCopyH2D(ArrayRef<int>(Host5), DeviceA7.asSlice()));
+
+ EXPECT_ERROR(
+ Executor.synchronousCopyH2D(ArrayRef<int>(Host7), DeviceA5.asSlice()));
+}
+
+TEST_F(ExecutorTest, SyncCopyH2DSliceToPointer) {
+ EXPECT_NO_ERROR(Executor.synchronousCopyH2D(Host5, DeviceA5.asSlice(), 5));
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], Host5[I]);
+ }
+
+ EXPECT_ERROR(Executor.synchronousCopyH2D(Host7, DeviceA5.asSlice(), 7));
+}
+
+// D2D tests
+
+TEST_F(ExecutorTest, SyncCopyD2DByCount) {
+ EXPECT_NO_ERROR(Executor.synchronousCopyD2D(DeviceA5, DeviceB5, 5));
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], HostB5[I]);
+ }
+
+ EXPECT_NO_ERROR(Executor.synchronousCopyD2D(DeviceA7, DeviceB7, 2));
+ for (int I = 0; I < 2; ++I) {
+ EXPECT_EQ(HostA7[I], HostB7[I]);
+ }
+
+ EXPECT_ERROR(Executor.synchronousCopyD2D(DeviceA5, DeviceB5, 7));
+
+ EXPECT_ERROR(Executor.synchronousCopyD2D(DeviceA7, DeviceB5, 7));
+
+ EXPECT_ERROR(Executor.synchronousCopyD2D(DeviceA5, DeviceB7, 7));
+}
+
+TEST_F(ExecutorTest, SyncCopyD2D) {
+ EXPECT_NO_ERROR(Executor.synchronousCopyD2D(DeviceA5, DeviceB5));
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], HostB5[I]);
+ }
+
+ EXPECT_ERROR(Executor.synchronousCopyD2D(DeviceA7, DeviceB5));
+
+ EXPECT_ERROR(Executor.synchronousCopyD2D(DeviceA5, DeviceB7));
+}
+
+TEST_F(ExecutorTest, SyncCopySliceD2DByCount) {
+ EXPECT_NO_ERROR(Executor.synchronousCopyD2D(DeviceA5.asSlice().drop_front(1),
+ DeviceB5, 4));
+ for (int I = 0; I < 4; ++I) {
+ EXPECT_EQ(HostA5[I + 1], HostB5[I]);
+ }
+
+ EXPECT_NO_ERROR(Executor.synchronousCopyD2D(DeviceA7.asSlice().drop_back(1),
+ DeviceB7, 2));
+ for (int I = 0; I < 2; ++I) {
+ EXPECT_EQ(HostA7[I], HostB7[I]);
+ }
+
+ EXPECT_ERROR(Executor.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB5, 7));
+
+ EXPECT_ERROR(Executor.synchronousCopyD2D(DeviceA7.asSlice(), DeviceB5, 7));
+
+ EXPECT_ERROR(Executor.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB7, 7));
+}
+
+TEST_F(ExecutorTest, SyncCopySliceD2D) {
+ EXPECT_NO_ERROR(
+ Executor.synchronousCopyD2D(DeviceA7.asSlice().drop_back(2), DeviceB5));
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA7[I], HostB5[I]);
+ }
+
+ EXPECT_ERROR(
+ Executor.synchronousCopyD2D(DeviceA7.asSlice().drop_front(1), DeviceB5));
+
+ EXPECT_ERROR(
+ Executor.synchronousCopyD2D(DeviceA5.asSlice().drop_back(1), DeviceB7));
+}
+
+TEST_F(ExecutorTest, SyncCopyD2DSliceByCount) {
+ EXPECT_NO_ERROR(Executor.synchronousCopyD2D(
+ DeviceA5, DeviceB7.asSlice().drop_front(2), 5));
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], HostB7[I + 2]);
+ }
+
+ EXPECT_NO_ERROR(Executor.synchronousCopyD2D(
+ DeviceA7, DeviceB7.asSlice().drop_back(3), 2));
+ for (int I = 0; I < 2; ++I) {
+ EXPECT_EQ(HostA7[I], HostB7[I]);
+ }
+
+ EXPECT_ERROR(Executor.synchronousCopyD2D(DeviceA5, DeviceB5.asSlice(), 7));
+
+ EXPECT_ERROR(Executor.synchronousCopyD2D(DeviceA7, DeviceB5.asSlice(), 7));
+
+ EXPECT_ERROR(Executor.synchronousCopyD2D(DeviceA5, DeviceB7.asSlice(), 7));
+}
+
+TEST_F(ExecutorTest, SyncCopyD2DSlice) {
+ EXPECT_NO_ERROR(
+ Executor.synchronousCopyD2D(DeviceA5, DeviceB7.asSlice().drop_back(2)));
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], HostB7[I]);
+ }
+
+ EXPECT_ERROR(Executor.synchronousCopyD2D(DeviceA7, DeviceB5.asSlice()));
+
+ EXPECT_ERROR(Executor.synchronousCopyD2D(DeviceA5, DeviceB7.asSlice()));
+}
+
+TEST_F(ExecutorTest, SyncCopySliceD2DSliceByCount) {
+ EXPECT_NO_ERROR(
+ Executor.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB5.asSlice(), 5));
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], HostB5[I]);
+ }
+
+ EXPECT_NO_ERROR(
+ Executor.synchronousCopyD2D(DeviceA7.asSlice(), DeviceB7.asSlice(), 2));
+ for (int I = 0; I < 2; ++I) {
+ EXPECT_EQ(HostA7[I], HostB7[I]);
+ }
+
+ EXPECT_ERROR(
+ Executor.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB5.asSlice(), 7));
+
+ EXPECT_ERROR(
+ Executor.synchronousCopyD2D(DeviceA7.asSlice(), DeviceB5.asSlice(), 7));
+
+ EXPECT_ERROR(
+ Executor.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB7.asSlice(), 7));
+}
+
+TEST_F(ExecutorTest, SyncCopySliceD2DSlice) {
+ EXPECT_NO_ERROR(
+ Executor.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB5.asSlice()));
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], HostB5[I]);
+ }
+
+ EXPECT_ERROR(
+ Executor.synchronousCopyD2D(DeviceA7.asSlice(), DeviceB5.asSlice()));
+
+ EXPECT_ERROR(
+ Executor.synchronousCopyD2D(DeviceA5.asSlice(), DeviceB7.asSlice()));
+}
+
+} // namespace
diff --git a/parallel-libs/streamexecutor/lib/unittests/StreamTest.cpp b/parallel-libs/streamexecutor/lib/unittests/StreamTest.cpp
index 6ef21833108..756467057ac 100644
--- a/parallel-libs/streamexecutor/lib/unittests/StreamTest.cpp
+++ b/parallel-libs/streamexecutor/lib/unittests/StreamTest.cpp
@@ -40,26 +40,34 @@ public:
return nullptr;
}
- se::Error memcpyD2H(se::PlatformStreamHandle *,
- const se::GlobalDeviceMemoryBase &DeviceSrc,
- void *HostDst, size_t ByteCount) override {
- std::memcpy(HostDst, DeviceSrc.getHandle(), ByteCount);
+ se::Error copyD2H(se::PlatformStreamHandle *S,
+ const se::GlobalDeviceMemoryBase &DeviceSrc,
+ size_t SrcByteOffset, void *HostDst, size_t DstByteOffset,
+ size_t ByteCount) override {
+ std::memcpy(HostDst, static_cast<const char *>(DeviceSrc.getHandle()) +
+ SrcByteOffset,
+ ByteCount);
return se::Error::success();
}
- se::Error memcpyH2D(se::PlatformStreamHandle *, const void *HostSrc,
- se::GlobalDeviceMemoryBase *DeviceDst,
- size_t ByteCount) override {
- std::memcpy(const_cast<void *>(DeviceDst->getHandle()), HostSrc, ByteCount);
+ se::Error copyH2D(se::PlatformStreamHandle *S, const void *HostSrc,
+ size_t SrcByteOffset, se::GlobalDeviceMemoryBase DeviceDst,
+ size_t DstByteOffset, size_t ByteCount) override {
+ std::memcpy(static_cast<char *>(const_cast<void *>(DeviceDst.getHandle())) +
+ DstByteOffset,
+ HostSrc, ByteCount);
return se::Error::success();
}
- se::Error memcpyD2D(se::PlatformStreamHandle *,
- const se::GlobalDeviceMemoryBase &DeviceSrc,
- se::GlobalDeviceMemoryBase *DeviceDst,
- size_t ByteCount) override {
- std::memcpy(const_cast<void *>(DeviceDst->getHandle()),
- DeviceSrc.getHandle(), ByteCount);
+ se::Error copyD2D(se::PlatformStreamHandle *S,
+ const se::GlobalDeviceMemoryBase &DeviceSrc,
+ size_t SrcByteOffset, se::GlobalDeviceMemoryBase DeviceDst,
+ size_t DstByteOffset, size_t ByteCount) override {
+ std::memcpy(static_cast<char *>(const_cast<void *>(DeviceDst.getHandle())) +
+ DstByteOffset,
+ static_cast<const char *>(DeviceSrc.getHandle()) +
+ SrcByteOffset,
+ ByteCount);
return se::Error::success();
}
};
@@ -68,47 +76,317 @@ public:
class StreamTest : public ::testing::Test {
public:
StreamTest()
- : DeviceA(se::GlobalDeviceMemory<int>::makeFromElementCount(HostA, 10)),
- DeviceB(se::GlobalDeviceMemory<int>::makeFromElementCount(HostB, 10)),
+ : 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(se::GlobalDeviceMemory<int>::makeFromElementCount(HostA5, 5)),
+ DeviceB5(se::GlobalDeviceMemory<int>::makeFromElementCount(HostB5, 5)),
+ DeviceA7(se::GlobalDeviceMemory<int>::makeFromElementCount(HostA7, 7)),
+ DeviceB7(se::GlobalDeviceMemory<int>::makeFromElementCount(HostB7, 7)),
+ Host5{24, 25, 26, 27, 28}, Host7{29, 30, 31, 32, 33, 34, 35},
Stream(llvm::make_unique<se::PlatformStreamHandle>(&PExecutor)) {}
protected:
// Device memory is backed by host arrays.
- int HostA[10];
- se::GlobalDeviceMemory<int> DeviceA;
- int HostB[10];
- se::GlobalDeviceMemory<int> DeviceB;
+ int HostA5[5];
+ int HostB5[5];
+ int HostA7[7];
+ int HostB7[7];
+ se::GlobalDeviceMemory<int> DeviceA5;
+ se::GlobalDeviceMemory<int> DeviceB5;
+ se::GlobalDeviceMemory<int> DeviceA7;
+ se::GlobalDeviceMemory<int> DeviceB7;
// Host memory to be used as actual host memory.
- int Host[10];
+ int Host5[5];
+ int Host7[7];
MockPlatformExecutor PExecutor;
se::Stream Stream;
};
-TEST_F(StreamTest, MemcpyCorrectSize) {
- Stream.thenMemcpyH2D(llvm::ArrayRef<int>(Host), &DeviceA);
+using llvm::ArrayRef;
+using llvm::MutableArrayRef;
+
+// D2H tests
+
+TEST_F(StreamTest, CopyD2HToMutableArrayRefByCount) {
+ Stream.thenCopyD2H(DeviceA5, MutableArrayRef<int>(Host5), 5);
EXPECT_TRUE(Stream.isOK());
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], Host5[I]);
+ }
- Stream.thenMemcpyD2H(DeviceA, llvm::MutableArrayRef<int>(Host));
+ Stream.thenCopyD2H(DeviceB5, MutableArrayRef<int>(Host5), 2);
EXPECT_TRUE(Stream.isOK());
+ for (int I = 0; I < 2; ++I) {
+ EXPECT_EQ(HostB5[I], Host5[I]);
+ }
- Stream.thenMemcpyD2D(DeviceA, &DeviceB);
+ Stream.thenCopyD2H(DeviceA7, MutableArrayRef<int>(Host5), 7);
+ EXPECT_FALSE(Stream.isOK());
+}
+
+TEST_F(StreamTest, CopyD2HToMutableArrayRef) {
+ Stream.thenCopyD2H(DeviceA5, MutableArrayRef<int>(Host5));
EXPECT_TRUE(Stream.isOK());
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], Host5[I]);
+ }
+
+ Stream.thenCopyD2H(DeviceA5, MutableArrayRef<int>(Host7));
+ EXPECT_FALSE(Stream.isOK());
}
-TEST_F(StreamTest, MemcpyH2DTooManyElements) {
- Stream.thenMemcpyH2D(llvm::ArrayRef<int>(Host), &DeviceA, 20);
+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, MemcpyD2HTooManyElements) {
- Stream.thenMemcpyD2H(DeviceA, llvm::MutableArrayRef<int>(Host), 20);
+TEST_F(StreamTest, CopyD2HSliceToMutableArrayRefByCount) {
+ Stream.thenCopyD2H(DeviceA5.asSlice().drop_front(1),
+ MutableArrayRef<int>(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<int>(Host5), 2);
+ EXPECT_TRUE(Stream.isOK());
+ for (int I = 0; I < 2; ++I) {
+ EXPECT_EQ(HostB5[I], Host5[I]);
+ }
+
+ Stream.thenCopyD2H(DeviceA5.asSlice(), MutableArrayRef<int>(Host7), 7);
+ EXPECT_FALSE(Stream.isOK());
+}
+
+TEST_F(StreamTest, CopyD2HSliceToMutableArrayRef) {
+ Stream.thenCopyD2H(DeviceA7.asSlice().slice(1, 5),
+ MutableArrayRef<int>(Host5));
+ EXPECT_TRUE(Stream.isOK());
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA7[I + 1], Host5[I]);
+ }
+
+ Stream.thenCopyD2H(DeviceA5.asSlice(), MutableArrayRef<int>(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<int>(Host5), DeviceA5, 5);
+ EXPECT_TRUE(Stream.isOK());
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], Host5[I]);
+ }
+
+ Stream.thenCopyH2D(ArrayRef<int>(Host5), DeviceB5, 2);
+ EXPECT_TRUE(Stream.isOK());
+ for (int I = 0; I < 2; ++I) {
+ EXPECT_EQ(HostB5[I], Host5[I]);
+ }
+
+ Stream.thenCopyH2D(ArrayRef<int>(Host7), DeviceA5, 7);
+ EXPECT_FALSE(Stream.isOK());
+}
+
+TEST_F(StreamTest, CopyH2DToArrayRef) {
+ Stream.thenCopyH2D(ArrayRef<int>(Host5), DeviceA5);
+ EXPECT_TRUE(Stream.isOK());
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], Host5[I]);
+ }
+
+ Stream.thenCopyH2D(ArrayRef<int>(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(HostA5[I], Host5[I]);
+ }
+
+ Stream.thenCopyH2D(Host7, DeviceA5, 7);
+ EXPECT_FALSE(Stream.isOK());
+}
+
+TEST_F(StreamTest, CopyH2DSliceToArrayRefByCount) {
+ Stream.thenCopyH2D(ArrayRef<int>(Host5 + 1, 4),
+ DeviceA5.asSlice().drop_front(1), 4);
+ EXPECT_TRUE(Stream.isOK());
+ for (int I = 1; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], Host5[I]);
+ }
+
+ Stream.thenCopyH2D(ArrayRef<int>(Host5), DeviceB5.asSlice().drop_back(1), 2);
+ EXPECT_TRUE(Stream.isOK());
+ for (int I = 0; I < 2; ++I) {
+ EXPECT_EQ(HostB5[I], Host5[I]);
+ }
+
+ Stream.thenCopyH2D(ArrayRef<int>(Host5), DeviceA5.asSlice(), 7);
+ EXPECT_FALSE(Stream.isOK());
+}
+
+TEST_F(StreamTest, CopyH2DSliceToArrayRef) {
+
+ Stream.thenCopyH2D(ArrayRef<int>(Host5), DeviceA5.asSlice());
+ EXPECT_TRUE(Stream.isOK());
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[I], Host5[I]);
+ }
+
+ Stream.thenCopyH2D(ArrayRef<int>(Host7), DeviceA5.asSlice());
EXPECT_FALSE(Stream.isOK());
}
-TEST_F(StreamTest, MemcpyD2DTooManyElements) {
- Stream.thenMemcpyD2D(DeviceA, &DeviceB, 20);
+TEST_F(StreamTest, CopyH2DSliceToPointer) {
+ Stream.thenCopyH2D(Host5, DeviceA5.asSlice(), 5);
+ EXPECT_TRUE(Stream.isOK());
+ for (int I = 0; I < 5; ++I) {
+ EXPECT_EQ(HostA5[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(HostA5[I], HostB5[I]);
+ }
+
+ Stream.thenCopyD2D(DeviceA7, DeviceB7, 2);
+ EXPECT_TRUE(Stream.isOK());
+ for (int I = 0; I < 2; ++I) {
+ EXPECT_EQ(HostA7[I], HostB7[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(HostA5[I], HostB5[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(HostA5[I + 1], HostB5[I]);
+ }
+
+ Stream.thenCopyD2D(DeviceA7.asSlice().drop_back(1), DeviceB7, 2);
+ EXPECT_TRUE(Stream.isOK());
+ for (int I = 0; I < 2; ++I) {
+ EXPECT_EQ(HostA7[I], HostB7[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(HostA7[I], HostB5[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(HostA5[I], HostB7[I + 2]);
+ }
+
+ Stream.thenCopyD2D(DeviceA7, DeviceB7.asSlice().drop_back(3), 2);
+ EXPECT_TRUE(Stream.isOK());
+ for (int I = 0; I < 2; ++I) {
+ EXPECT_EQ(HostA7[I], HostB7[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(HostA5[I], HostB7[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(HostA5[I], HostB5[I]);
+ }
+
+ Stream.thenCopyD2D(DeviceA7.asSlice(), DeviceB7.asSlice(), 2);
+ EXPECT_TRUE(Stream.isOK());
+ for (int I = 0; I < 2; ++I) {
+ EXPECT_EQ(HostA7[I], HostB7[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(HostA5[I], HostB5[I]);
+ }
+
+ Stream.thenCopyD2D(DeviceA5.asSlice(), DeviceB7.asSlice());
EXPECT_FALSE(Stream.isOK());
}
OpenPOWER on IntegriCloud