-
Notifications
You must be signed in to change notification settings - Fork 788
[SYCL][CUDA] Improvements to CUDA device selection #1689
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
Changes from all commits
7f4646c
0451bd6
aedaacc
255af95
ec971f9
8fd3208
6697fff
bcd9a41
5c92d5f
1a56184
76b279b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,7 +41,8 @@ context_impl::context_impl(const vector_class<cl::sycl::device> Devices, | |
DeviceIds.push_back(getSyclObjImpl(D)->getHandleRef()); | ||
} | ||
|
||
if (MPlatform->is_cuda()) { | ||
const auto Backend = getPlugin().getBackend(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From the link you reference:
In this case the type is obvious from the context. |
||
if (Backend == backend::cuda) { | ||
#if USE_PI_CUDA | ||
const pi_context_properties props[] = {PI_CONTEXT_PROPERTIES_CUDA_PRIMARY, | ||
UseCUDAPrimaryContext, 0}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,33 @@ __SYCL_INLINE_NAMESPACE(cl) { | |
namespace sycl { | ||
namespace detail { | ||
|
||
static bool IsBannedPlatform(platform Platform) { | ||
// The NVIDIA OpenCL platform is currently not compatible with DPC++ | ||
// since it is only 1.2 but gets selected by default in many systems | ||
// There is also no support on the PTX backend for OpenCL consumption, | ||
// and there have been some internal reports. | ||
// To avoid problems on default users and deployment of DPC++ on platforms | ||
// where CUDA is available, the OpenCL support is disabled. | ||
// | ||
auto IsNVIDIAOpenCL = [](platform Platform) { | ||
if (Platform.is_host()) | ||
return false; | ||
|
||
const bool HasCUDA = Platform.get_info<info::platform::name>().find( | ||
"NVIDIA CUDA") != std::string::npos; | ||
s-kanaev marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const auto Backend = | ||
detail::getSyclObjImpl(Platform)->getPlugin().getBackend(); | ||
const bool IsCUDAOCL = (HasCUDA && Backend == backend::opencl); | ||
if (detail::pi::trace(detail::pi::TraceLevel::PI_TRACE_ALL) && IsCUDAOCL) { | ||
std::cout << "SYCL_PI_TRACE[all]: " | ||
<< "NVIDIA CUDA OpenCL platform found but is not compatible." | ||
<< std::endl; | ||
} | ||
return IsCUDAOCL; | ||
}; | ||
return IsNVIDIAOpenCL(Platform); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like you unconditionally ban OpenCL CUDA forever. Why is it OK? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The intention is to disable NVIDIA OpenCL platform for the foreseeable future, among many reasons, because its not really needed when having the CUDA backend. See #1665 for a longer discussion about this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for pointing to the discussion. Should we at least check that PI CUDA backend is available before shooting the OpenCL CUDA backend? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So you mean, if the DPCPP is not built with CUDA support, the NVIDIA OpenCL should still be available for device selection? That is still untested. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't we use existing whitelist functionality to filter/ban this? I am OK with doing it separately.
Ruyk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
vector_class<platform> platform_impl::get_platforms() { | ||
vector_class<platform> Platforms; | ||
vector_class<plugin> Plugins = RT::initialize(); | ||
|
@@ -39,7 +66,8 @@ vector_class<platform> platform_impl::get_platforms() { | |
platform Platform = detail::createSyclObjFromImpl<platform>( | ||
std::make_shared<platform_impl>(PiPlatform, Plugins[i])); | ||
// Skip platforms which do not contain requested device types | ||
if (!Platform.get_devices(ForcedType).empty()) | ||
if (!Platform.get_devices(ForcedType).empty() && | ||
!IsBannedPlatform(Platform)) | ||
Platforms.push_back(Platform); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -86,29 +86,10 @@ static RT::PiProgram createBinaryProgram(const ContextImplPtr Context, | |
|
||
RT::PiProgram Program; | ||
|
||
bool IsCUDA = false; | ||
|
||
// TODO: Implement `piProgramCreateWithBinary` to not require extra logic for | ||
// the CUDA backend. | ||
Comment on lines
89
to
90
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe you didn't remove this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, the |
||
#if USE_PI_CUDA | ||
// All devices in a context are from the same platform. | ||
RT::PiDevice Device = getFirstDevice(Context); | ||
RT::PiPlatform Platform = nullptr; | ||
Plugin.call<PiApiKind::piDeviceGetInfo>(Device, PI_DEVICE_INFO_PLATFORM, sizeof(Platform), | ||
&Platform, nullptr); | ||
size_t PlatformNameSize = 0u; | ||
Plugin.call<PiApiKind::piPlatformGetInfo>(Platform, PI_PLATFORM_INFO_NAME, 0u, nullptr, | ||
&PlatformNameSize); | ||
std::vector<char> PlatformName(PlatformNameSize, '\0'); | ||
Plugin.call<PiApiKind::piPlatformGetInfo>(Platform, PI_PLATFORM_INFO_NAME, | ||
PlatformName.size(), PlatformName.data(), nullptr); | ||
if (PlatformNameSize > 0u && | ||
std::strncmp(PlatformName.data(), "NVIDIA CUDA", PlatformNameSize) == 0) { | ||
IsCUDA = true; | ||
} | ||
#endif // USE_PI_CUDA | ||
|
||
if (IsCUDA) { | ||
const auto Backend = Context->getPlugin().getBackend(); | ||
if (Backend == backend::cuda) { | ||
// TODO: Reemplace CreateWithSource with CreateWithBinary in CUDA backend | ||
const char *SignedData = reinterpret_cast<const char *>(Data); | ||
Plugin.call<PiApiKind::piclProgramCreateWithSource>(Context->getHandleRef(), 1 /*one binary*/, &SignedData, | ||
|
@@ -259,6 +240,13 @@ RetT *getOrBuild(KernelProgramCache &KPCache, KeyT &&CacheKey, | |
|
||
static bool isDeviceBinaryTypeSupported(const context &C, | ||
RT::PiDeviceBinaryType Format) { | ||
const backend ContextBackend = | ||
detail::getSyclObjImpl(C)->getPlugin().getBackend(); | ||
|
||
// The CUDA backend cannot use SPIRV | ||
if (ContextBackend == backend::cuda && Format == PI_DEVICE_BINARY_TYPE_SPIRV) | ||
return false; | ||
v-klochkov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// All formats except PI_DEVICE_BINARY_TYPE_SPIRV are supported. | ||
if (Format != PI_DEVICE_BINARY_TYPE_SPIRV) | ||
return true; | ||
|
@@ -272,8 +260,7 @@ static bool isDeviceBinaryTypeSupported(const context &C, | |
} | ||
|
||
// OpenCL 2.1 and greater require clCreateProgramWithIL | ||
backend CBackend = (detail::getSyclObjImpl(C)->getPlugin()).getBackend(); | ||
if ((CBackend == backend::opencl) && | ||
if ((ContextBackend == backend::opencl) && | ||
C.get_platform().get_info<info::platform::version>() >= "2.1") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just curious does this really work as it's intended to? |
||
return true; | ||
|
||
|
@@ -337,7 +324,7 @@ RT::PiProgram ProgramManager::createPIProgram(const RTDeviceBinaryImage &Img, | |
|
||
if (!isDeviceBinaryTypeSupported(Context, Format)) | ||
throw feature_not_supported( | ||
"Online compilation is not supported in this context", | ||
"SPIR-V online compilation is not supported in this context", | ||
PI_INVALID_OPERATION); | ||
|
||
// Load the image | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,28 +30,36 @@ static bool isDeviceOfPreferredSyclBe(const device &Device) { | |
|
||
device device_selector::select_device() const { | ||
vector_class<device> devices = device::get_devices(); | ||
int score = -1; | ||
int score = REJECT_DEVICE_SCORE; | ||
bader marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const device *res = nullptr; | ||
|
||
for (const auto &dev : devices) { | ||
int dev_score = (*this)(dev); | ||
|
||
if (detail::pi::trace(detail::pi::TraceLevel::PI_TRACE_ALL)) { | ||
string_class PlatformVersion = dev.get_info<info::device::platform>() | ||
.get_info<info::platform::version>(); | ||
string_class DeviceName = dev.get_info<info::device::name>(); | ||
std::cout << "SYCL_PI_TRACE[all]: " | ||
<< "select_device(): -> score = " << score << std::endl | ||
<< "select_device(): -> score = " << score | ||
<< ((score == REJECT_DEVICE_SCORE) ? "(REJECTED)" : " ") | ||
<< std::endl | ||
<< "SYCL_PI_TRACE[all]: " | ||
<< " platform: " << PlatformVersion << std::endl | ||
<< "SYCL_PI_TRACE[all]: " | ||
<< " device: " << DeviceName << std::endl; | ||
} | ||
|
||
// Device is discarded if is marked with REJECT_DEVICE_SCORE | ||
if (dev_score == REJECT_DEVICE_SCORE) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it is not quite correct. The SYCL spec(4.6.1.1 Device selector interface) says: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @romanovvlad, are you okay if we merge this PR and rebase #1751? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would prefer that we do not merge incorrect implementation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this patch makes it worse than it is today. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think either. |
||
continue; | ||
|
||
// SYCL spec says: "If more than one device receives the high score then | ||
// one of those tied devices will be returned, but which of the devices | ||
// from the tied set is to be returned is not defined". Here we give a | ||
// preference to the device of the preferred BE. | ||
// | ||
if (score < dev_score || | ||
if ((score < dev_score) || | ||
(score == dev_score && isDeviceOfPreferredSyclBe(dev))) { | ||
res = &dev; | ||
score = dev_score; | ||
|
@@ -79,7 +87,7 @@ device device_selector::select_device() const { | |
|
||
int default_selector::operator()(const device &dev) const { | ||
|
||
int Score = -1; | ||
int Score = REJECT_DEVICE_SCORE; | ||
|
||
// Give preference to device of SYCL BE. | ||
if (isDeviceOfPreferredSyclBe(dev)) | ||
|
@@ -102,7 +110,8 @@ int default_selector::operator()(const device &dev) const { | |
} | ||
|
||
int gpu_selector::operator()(const device &dev) const { | ||
int Score = -1; | ||
int Score = REJECT_DEVICE_SCORE; | ||
|
||
if (dev.is_gpu()) { | ||
Score = 1000; | ||
// Give preference to device of SYCL BE. | ||
|
@@ -113,7 +122,7 @@ int gpu_selector::operator()(const device &dev) const { | |
} | ||
|
||
int cpu_selector::operator()(const device &dev) const { | ||
int Score = -1; | ||
int Score = REJECT_DEVICE_SCORE; | ||
if (dev.is_cpu()) { | ||
Score = 1000; | ||
// Give preference to device of SYCL BE. | ||
|
@@ -124,7 +133,7 @@ int cpu_selector::operator()(const device &dev) const { | |
} | ||
|
||
int accelerator_selector::operator()(const device &dev) const { | ||
int Score = -1; | ||
int Score = REJECT_DEVICE_SCORE; | ||
if (dev.is_accelerator()) { | ||
Score = 1000; | ||
// Give preference to device of SYCL BE. | ||
|
@@ -135,7 +144,7 @@ int accelerator_selector::operator()(const device &dev) const { | |
} | ||
|
||
int host_selector::operator()(const device &dev) const { | ||
int Score = -1; | ||
int Score = REJECT_DEVICE_SCORE; | ||
if (dev.is_host()) { | ||
Score = 1000; | ||
// Give preference to device of SYCL BE. | ||
|
Uh oh!
There was an error while loading. Please reload this page.