From b29ee99c6b32b9318581ddbe9a29d440771cb7bf Mon Sep 17 00:00:00 2001 From: Steffen Larsen Date: Wed, 27 May 2020 16:04:51 +0100 Subject: [PATCH] [SYCL][CUDA] Fixes CUDA unit tests that uses SYCL directly CUDA-specific unit tests that use SYCL directly fail if another backend is in use. This commit fixes this by actively selecting CUDA platforms and only runs the tests on these. Signed-off-by: Steffen Larsen --- sycl/unittests/pi/TestGetPlatforms.hpp | 30 +++++++ .../pi/cuda/test_interop_get_native.cpp | 51 +++++------- .../pi/cuda/test_primary_context.cpp | 82 ++++++------------- 3 files changed, 74 insertions(+), 89 deletions(-) create mode 100644 sycl/unittests/pi/TestGetPlatforms.hpp diff --git a/sycl/unittests/pi/TestGetPlatforms.hpp b/sycl/unittests/pi/TestGetPlatforms.hpp new file mode 100644 index 0000000000000..3696709217be9 --- /dev/null +++ b/sycl/unittests/pi/TestGetPlatforms.hpp @@ -0,0 +1,30 @@ +// 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 +#include +#include +#include + +namespace pi { +inline std::vector getPlatformsWithName(const char *name) { + std::vector platforms = + cl::sycl::platform::get_platforms(); + + // Remove platforms that have no devices or doesn't contain the name + auto end = + std::remove_if(platforms.begin(), platforms.end(), + [=](const cl::sycl::platform &platform) -> bool { + const std::string platformName = + platform.get_info(); + return platformName.find(name) == std::string::npos || + platform.get_devices().size() == 0; + }); + platforms.erase(end, platforms.end()); + + return platforms; +} +} // namespace pi \ No newline at end of file diff --git a/sycl/unittests/pi/cuda/test_interop_get_native.cpp b/sycl/unittests/pi/cuda/test_interop_get_native.cpp index cfb4ab9aae2be..f8cf9f5fea310 100644 --- a/sycl/unittests/pi/cuda/test_interop_get_native.cpp +++ b/sycl/unittests/pi/cuda/test_interop_get_native.cpp @@ -8,6 +8,7 @@ #include "gtest/gtest.h" +#include "TestGetPlatforms.hpp" #include #include #include @@ -15,41 +16,23 @@ using namespace cl::sycl; -struct CudaInteropGetNativeTests : public ::testing::Test { +struct CudaInteropGetNativeTests : public ::testing::TestWithParam { protected: queue syclQueue_; context syclContext_; device syclDevice_; - CudaInteropGetNativeTests() - : syclQueue_(cuda_device_selector()), - syclContext_(syclQueue_.get_context()), - syclDevice_(syclQueue_.get_device()) {} - - static bool isCudaDevice(const device &dev) { - const platform platform = dev.get_info(); - const std::string platformVersion = - platform.get_info(); - const std::string platformName = platform.get_info(); - // If using PI_CUDA, don't accept a non-CUDA device - return platformVersion.find("CUDA") != std::string::npos && - platformName.find("NVIDIA CUDA") != std::string::npos; + void SetUp() override { + syclDevice_ = GetParam().get_devices()[0]; + syclQueue_ = queue{syclDevice_}; + syclContext_ = syclQueue_.get_context(); } - class cuda_device_selector : public device_selector { - public: - int operator()(const device &dev) const { - return isCudaDevice(dev) ? 1000 : -1000; - } - }; - - void SetUp() override {} - void TearDown() override {} }; -TEST_F(CudaInteropGetNativeTests, getNativeDevice) { +TEST_P(CudaInteropGetNativeTests, getNativeDevice) { CUdevice cudaDevice = get_native(syclDevice_); char cudaDeviceName[2] = {0, 0}; CUresult result = cuDeviceGetName(cudaDeviceName, 2, cudaDevice); @@ -57,12 +40,12 @@ TEST_F(CudaInteropGetNativeTests, getNativeDevice) { ASSERT_NE(cudaDeviceName[0], 0); } -TEST_F(CudaInteropGetNativeTests, getNativeContext) { +TEST_P(CudaInteropGetNativeTests, getNativeContext) { CUcontext cudaContext = get_native(syclContext_); ASSERT_NE(cudaContext, nullptr); } -TEST_F(CudaInteropGetNativeTests, getNativeQueue) { +TEST_P(CudaInteropGetNativeTests, getNativeQueue) { CUstream cudaStream = get_native(syclQueue_); ASSERT_NE(cudaStream, nullptr); @@ -74,7 +57,7 @@ TEST_F(CudaInteropGetNativeTests, getNativeQueue) { ASSERT_EQ(streamContext, cudaContext); } -TEST_F(CudaInteropGetNativeTests, interopTaskGetMem) { +TEST_P(CudaInteropGetNativeTests, interopTaskGetMem) { buffer syclBuffer(range<1>{1}); syclQueue_.submit([&](handler &cgh) { auto syclAccessor = syclBuffer.get_access(cgh); @@ -82,13 +65,17 @@ TEST_F(CudaInteropGetNativeTests, interopTaskGetMem) { CUdeviceptr cudaPtr = ih.get_mem(syclAccessor); CUdeviceptr cudaPtrBase; size_t cudaPtrSize = 0; - cuMemGetAddressRange(&cudaPtrBase, &cudaPtrSize, cudaPtr); - ASSERT_EQ(cudaPtrSize, sizeof(int)); + CUcontext cudaContext = get_native(syclContext_); + ASSERT_EQ(CUDA_SUCCESS, cuCtxPushCurrent(cudaContext)); + ASSERT_EQ(CUDA_SUCCESS, + cuMemGetAddressRange(&cudaPtrBase, &cudaPtrSize, cudaPtr)); + ASSERT_EQ(CUDA_SUCCESS, cuCtxPopCurrent(nullptr)); + ASSERT_EQ(sizeof(int), cudaPtrSize); }); }); } -TEST_F(CudaInteropGetNativeTests, interopTaskGetBufferMem) { +TEST_P(CudaInteropGetNativeTests, interopTaskGetBufferMem) { CUstream cudaStream = get_native(syclQueue_); syclQueue_.submit([&](handler &cgh) { cgh.interop_task([=](interop_handler ih) { @@ -97,3 +84,7 @@ TEST_F(CudaInteropGetNativeTests, interopTaskGetBufferMem) { }); }); } + +INSTANTIATE_TEST_CASE_P( + OnCudaPlatform, CudaInteropGetNativeTests, + ::testing::ValuesIn(pi::getPlatformsWithName("CUDA BACKEND")), ); diff --git a/sycl/unittests/pi/cuda/test_primary_context.cpp b/sycl/unittests/pi/cuda/test_primary_context.cpp index 244033757fa1c..656f277b7de86 100644 --- a/sycl/unittests/pi/cuda/test_primary_context.cpp +++ b/sycl/unittests/pi/cuda/test_primary_context.cpp @@ -10,75 +10,32 @@ #include -#include "TestGetPlugin.hpp" +#include "TestGetPlatforms.hpp" #include #include -#include #include #include using namespace cl::sycl; -struct CudaPrimaryContextTests : public ::testing::Test { +struct CudaPrimaryContextTests : public ::testing::TestWithParam { protected: device deviceA_; device deviceB_; - context context_; - - static bool isCudaDevice(const device &dev) { - const platform platform = dev.get_info(); - const std::string platformVersion = - platform.get_info(); - // If using PI_CUDA, don't accept a non-CUDA device - return platformVersion.find("CUDA BACKEND") != std::string::npos; - } - - class cuda_device_selector : public device_selector { - public: - int operator()(const device &dev) const { - return isCudaDevice(dev) ? 1 : -1; - } - }; - - class other_cuda_device_selector : public device_selector { - public: - other_cuda_device_selector(const device &dev) : excludeDevice{dev} {} - - int operator()(const device &dev) const { - if (!isCudaDevice(dev)) { - return -1; - } - if (dev.get() == excludeDevice.get()) { - // Return only this device if it is the only available - return 0; - } - return 1; - } - - private: - const device &excludeDevice; - }; void SetUp() override { + std::vector CudaDevices = GetParam().get_devices(); - try { - context context_; - } catch (device_error &e) { - std::cout << "Failed to create device for context" << std::endl; - } - - deviceA_ = cuda_device_selector().select_device(); - deviceB_ = other_cuda_device_selector(deviceA_).select_device(); - - ASSERT_TRUE(isCudaDevice(deviceA_)); + deviceA_ = CudaDevices[0]; + deviceB_ = CudaDevices.size() > 1 ? CudaDevices[1] : deviceA_; } void TearDown() override {} }; -TEST_F(CudaPrimaryContextTests, piSingleContext) { +TEST_P(CudaPrimaryContextTests, piSingleContext) { std::cout << "create single context" << std::endl; context Context(deviceA_, async_handler{}, /*UsePrimaryContext=*/true); @@ -93,7 +50,7 @@ TEST_F(CudaPrimaryContextTests, piSingleContext) { cuDevicePrimaryCtxRelease(CudaDevice); } -TEST_F(CudaPrimaryContextTests, piMultiContextSingleDevice) { +TEST_P(CudaPrimaryContextTests, piMultiContextSingleDevice) { std::cout << "create multiple contexts for one device" << std::endl; context ContextA(deviceA_, async_handler{}, /*UsePrimaryContext=*/true); context ContextB(deviceA_, async_handler{}, /*UsePrimaryContext=*/true); @@ -104,18 +61,25 @@ TEST_F(CudaPrimaryContextTests, piMultiContextSingleDevice) { ASSERT_EQ(CudaContextA, CudaContextB); } -TEST_F(CudaPrimaryContextTests, piMultiContextMultiDevice) { +TEST_P(CudaPrimaryContextTests, piMultiContextMultiDevice) { + if (deviceA_ == deviceB_) + return; + CUdevice CudaDeviceA = deviceA_.get_native(); CUdevice CudaDeviceB = deviceB_.get_native(); - if (isCudaDevice(deviceB_) && CudaDeviceA != CudaDeviceB) { - std::cout << "create multiple contexts for multiple devices" << std::endl; - context ContextA(deviceA_, async_handler{}, /*UsePrimaryContext=*/true); - context ContextB(deviceB_, async_handler{}, /*UsePrimaryContext=*/true); + ASSERT_NE(CudaDeviceA, CudaDeviceB); - CUcontext CudaContextA = ContextA.get_native(); - CUcontext CudaContextB = ContextB.get_native(); + std::cout << "create multiple contexts for multiple devices" << std::endl; + context ContextA(deviceA_, async_handler{}, /*UsePrimaryContext=*/true); + context ContextB(deviceB_, async_handler{}, /*UsePrimaryContext=*/true); - ASSERT_NE(CudaContextA, CudaContextB); - } + CUcontext CudaContextA = ContextA.get_native(); + CUcontext CudaContextB = ContextB.get_native(); + + ASSERT_NE(CudaContextA, CudaContextB); } + +INSTANTIATE_TEST_CASE_P( + OnCudaPlatform, CudaPrimaryContextTests, + ::testing::ValuesIn(pi::getPlatformsWithName("CUDA BACKEND")), );