Skip to content

[SYCL] Enable PI unit testing on multiple plugins. #1647

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions sycl/include/CL/sycl/detail/pi.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,16 @@ typedef enum {
// make the translation to OpenCL transparent.
//
typedef enum : pi_uint64 {
PI_DEVICE_TYPE_CPU = CL_DEVICE_TYPE_CPU,
PI_DEVICE_TYPE_GPU = CL_DEVICE_TYPE_GPU,
PI_DEVICE_TYPE_ACC = CL_DEVICE_TYPE_ACCELERATOR
PI_DEVICE_TYPE_DEFAULT =
CL_DEVICE_TYPE_DEFAULT, ///< The default device available in the PI
///< plugin.
PI_DEVICE_TYPE_ALL =
CL_DEVICE_TYPE_ALL, ///< All devices available in the PI plugin.
PI_DEVICE_TYPE_CPU =
CL_DEVICE_TYPE_CPU, ///< A PI device that is the host processor.
PI_DEVICE_TYPE_GPU = CL_DEVICE_TYPE_GPU, ///< A PI device that is a GPU.
PI_DEVICE_TYPE_ACC = CL_DEVICE_TYPE_ACCELERATOR ///< A PI device that is a
///< dedicated accelerator.
} _pi_device_type;

typedef enum {
Expand Down
9 changes: 6 additions & 3 deletions sycl/plugins/cuda/pi_cuda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -716,15 +716,18 @@ pi_result cuda_piDevicesGet(pi_platform platform, pi_device_type device_type,
pi_uint32 *num_devices) {

pi_result err = PI_SUCCESS;
const bool askingForGPU = (device_type & PI_DEVICE_TYPE_GPU);
size_t numDevices = askingForGPU ? platform->devices_.size() : 0;
const bool askingForDefault = device_type == PI_DEVICE_TYPE_DEFAULT;
const bool askingForGPU = device_type & PI_DEVICE_TYPE_GPU;
const bool returnDevices = askingForDefault || askingForGPU;

size_t numDevices = returnDevices ? platform->devices_.size() : 0;

try {
if (num_devices) {
*num_devices = numDevices;
}

if (askingForGPU && devices) {
if (returnDevices && devices) {
for (size_t i = 0; i < std::min(size_t(num_entries), numDevices); ++i) {
devices[i] = platform->devices_[i].get();
}
Expand Down
23 changes: 23 additions & 0 deletions sycl/unittests/pi/BackendString.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#pragma once

#include <detail/plugin.hpp>

namespace pi {
inline const char *GetBackendString(cl::sycl::backend backend) {
switch (backend) {
#define PI_BACKEND_STR(backend_name) \
case cl::sycl::backend::backend_name: \
return #backend_name
PI_BACKEND_STR(cuda);
PI_BACKEND_STR(host);
PI_BACKEND_STR(opencl);
#undef PI_BACKEND_STR
default:
return "Unknown Plugin";
}
}
} // namespace pi
2 changes: 1 addition & 1 deletion sycl/unittests/pi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)

# Enable exception handling for these unit tests
set(LLVM_REQUIRES_EH 1)
add_sycl_unittest(PiTests OBJECT
add_sycl_unittest(PiTests OBJECT
EnqueueMemTest.cpp
PiMock.cpp
PlatformTest.cpp
Expand Down
118 changes: 59 additions & 59 deletions sycl/unittests/pi/EnqueueMemTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,16 @@
//
//===----------------------------------------------------------------------===//

#include "BackendString.hpp"
#include <CL/sycl/detail/pi.hpp>
#include <detail/plugin.hpp>
#include <gtest/gtest.h>

using namespace cl::sycl;

namespace {
class DISABLED_EnqueueMemTest : public ::testing::Test {
class EnqueueMemTest : public testing::TestWithParam<detail::plugin> {
protected:
std::vector<detail::plugin> Plugins;

constexpr static size_t _numElementsX = 8;
constexpr static size_t _numElementsY = 4;

Expand All @@ -25,124 +24,125 @@ class DISABLED_EnqueueMemTest : public ::testing::Test {
pi_queue _queue = nullptr;
pi_mem _mem = nullptr;

DISABLED_EnqueueMemTest() = default;
EnqueueMemTest() = default;

~DISABLED_EnqueueMemTest() = default;
~EnqueueMemTest() = default;

void SetUp() override {
Plugins = detail::pi::initialize();
ASSERT_FALSE(Plugins.empty());

detail::plugin plugin = GetParam();

pi_platform platform = nullptr;
ASSERT_EQ((Plugins[0].call_nocheck<detail::PiApiKind::piPlatformsGet>(
ASSERT_EQ((plugin.call_nocheck<detail::PiApiKind::piPlatformsGet>(
1, &platform, nullptr)),
PI_SUCCESS);

ASSERT_EQ((Plugins[0].call_nocheck<detail::PiApiKind::piDevicesGet>(
platform, PI_DEVICE_TYPE_GPU, 1, &_device, nullptr)),
ASSERT_EQ((plugin.call_nocheck<detail::PiApiKind::piDevicesGet>(
platform, PI_DEVICE_TYPE_DEFAULT, 1, &_device, nullptr)),
PI_SUCCESS);

pi_result result = PI_INVALID_VALUE;
result = Plugins[0].call_nocheck<detail::PiApiKind::piContextCreate>(
result = plugin.call_nocheck<detail::PiApiKind::piContextCreate>(
nullptr, 1u, &_device, nullptr, nullptr, &_context);
ASSERT_EQ(result, PI_SUCCESS);

ASSERT_EQ((Plugins[0].call_nocheck<detail::PiApiKind::piQueueCreate>(
ASSERT_EQ((plugin.call_nocheck<detail::PiApiKind::piQueueCreate>(
_context, _device, 0, &_queue)),
PI_SUCCESS);

ASSERT_EQ((Plugins[0].call_nocheck<detail::PiApiKind::piMemBufferCreate>(
ASSERT_EQ((plugin.call_nocheck<detail::PiApiKind::piMemBufferCreate>(
_context, 0, _numElementsX * _numElementsY * sizeof(pi_int32),
nullptr, &_mem)),
PI_SUCCESS);
}

void TearDown() override {
ASSERT_EQ((Plugins[0].call_nocheck<detail::PiApiKind::piMemRelease>(_mem)),

detail::plugin plugin = GetParam();

ASSERT_EQ((plugin.call_nocheck<detail::PiApiKind::piMemRelease>(_mem)),
PI_SUCCESS);
ASSERT_EQ((plugin.call_nocheck<detail::PiApiKind::piQueueRelease>(_queue)),
PI_SUCCESS);
ASSERT_EQ(
(Plugins[0].call_nocheck<detail::PiApiKind::piQueueRelease>(_queue)),
(plugin.call_nocheck<detail::PiApiKind::piContextRelease>(_context)),
PI_SUCCESS);
ASSERT_EQ((Plugins[0].call_nocheck<detail::PiApiKind::piContextRelease>(
_context)),
PI_SUCCESS);
}

template <typename T> void TestBufferFill(const T &pattern) {

detail::plugin plugin = GetParam();

T inValues[_numElementsX] = {};

for (size_t i = 0; i < _numElementsX; ++i) {
ASSERT_NE(pattern, inValues[i]);
}

ASSERT_EQ(
(Plugins[0].call_nocheck<detail::PiApiKind::piEnqueueMemBufferWrite>(
_queue, _mem, PI_TRUE, 0, _numElementsX * sizeof(T), inValues, 0,
nullptr, nullptr)),
PI_SUCCESS);
ASSERT_EQ((plugin.call_nocheck<detail::PiApiKind::piEnqueueMemBufferWrite>(
_queue, _mem, PI_TRUE, 0, _numElementsX * sizeof(T), inValues,
0, nullptr, nullptr)),
PI_SUCCESS);

ASSERT_EQ(
(Plugins[0].call_nocheck<detail::PiApiKind::piEnqueueMemBufferFill>(
_queue, _mem, &pattern, sizeof(T), 0, sizeof(inValues), 0, nullptr,
nullptr)),
PI_SUCCESS);
ASSERT_EQ((plugin.call_nocheck<detail::PiApiKind::piEnqueueMemBufferFill>(
_queue, _mem, &pattern, sizeof(T), 0, sizeof(inValues), 0,
nullptr, nullptr)),
PI_SUCCESS);

T outValues[_numElementsX] = {};
ASSERT_EQ(
(Plugins[0].call_nocheck<detail::PiApiKind::piEnqueueMemBufferRead>(
_queue, _mem, PI_TRUE, 0, _numElementsX * sizeof(T), outValues, 0,
nullptr, nullptr)),
PI_SUCCESS);
ASSERT_EQ((plugin.call_nocheck<detail::PiApiKind::piEnqueueMemBufferRead>(
_queue, _mem, PI_TRUE, 0, _numElementsX * sizeof(T),
outValues, 0, nullptr, nullptr)),
PI_SUCCESS);

for (size_t i = 0; i < _numElementsX; ++i) {
ASSERT_EQ(pattern, outValues[i]);
}
}
};

template<typename T>
struct vec4 {
static std::vector<detail::plugin> Plugins = detail::pi::initialize();

INSTANTIATE_TEST_CASE_P(
EnqueueMemTestImpl, EnqueueMemTest, testing::ValuesIn(Plugins),
[](const testing::TestParamInfo<EnqueueMemTest::ParamType> &info) {
return pi::GetBackendString(info.param.getBackend());
});

template <typename T> struct vec4 {
T x, y, z, w;

bool operator==(const vec4 &rhs) const {
return x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w;
}

bool operator!=(const vec4 &rhs) const {
return !(*this == rhs);
}
bool operator!=(const vec4 &rhs) const { return !(*this == rhs); }
};

template<typename T>
struct vec2 {
template <typename T> struct vec2 {
T x, y;

bool operator==(const vec2 &rhs) const {
return x == rhs.x && y == rhs.y;
}
bool operator==(const vec2 &rhs) const { return x == rhs.x && y == rhs.y; }

bool operator!=(const vec2 &rhs) const {
return !(*this == rhs);
}
bool operator!=(const vec2 &rhs) const { return !(*this == rhs); }
};

TEST_F(DISABLED_EnqueueMemTest, piEnqueueMemBufferFill) {
TEST_P(EnqueueMemTest, piEnqueueMemBufferFill) {

TestBufferFill(float{1});
TestBufferFill(vec2<float>{1, 2});
TestBufferFill(vec4<float>{1, 2, 3, 4});
TestBufferFill(float{1});
TestBufferFill(vec2<float>{1, 2});
TestBufferFill(vec4<float>{1, 2, 3, 4});

TestBufferFill(uint8_t{1});
TestBufferFill(vec2<uint8_t>{1, 2});
TestBufferFill(vec4<uint8_t>{1, 2, 3, 4});
TestBufferFill(uint8_t{1});
TestBufferFill(vec2<uint8_t>{1, 2});
TestBufferFill(vec4<uint8_t>{1, 2, 3, 4});

TestBufferFill(uint16_t{1});
TestBufferFill(vec2<uint16_t>{1, 2});
TestBufferFill(vec4<uint16_t>{1, 2, 3, 4});
TestBufferFill(uint16_t{1});
TestBufferFill(vec2<uint16_t>{1, 2});
TestBufferFill(vec4<uint16_t>{1, 2, 3, 4});

TestBufferFill(uint32_t{1});
TestBufferFill(vec2<uint32_t>{1, 2});
TestBufferFill(vec4<uint32_t>{1, 2, 3, 4});
TestBufferFill(uint32_t{1});
TestBufferFill(vec2<uint32_t>{1, 2});
TestBufferFill(vec4<uint32_t>{1, 2, 3, 4});
}
} // namespace
Loading