Skip to content

Commit 082929a

Browse files
authored
[SYCL][CUDA] Ignore cuda prefetch hint if not supported (#5043)
Specific devices and OS's, like Windows, do not support concurrent managed memory. cudaPrefetchAsync requires concurrent managed access for unified memory. This PR removes the windows error message and replaces it with a check for concurrent managed access. As the SYCL prefetch operation is a hint, this can return a success. Let me know if there is a preferred error code to throw. Also, if it is best that a user warning is printed to indicate that the hint is being ignored as the device does not support the operation.
1 parent 0be594f commit 082929a

File tree

12 files changed

+160
-7
lines changed

12 files changed

+160
-7
lines changed

sycl/include/CL/sycl/detail/pi.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ _PI_API(piextKernelSetArgSampler)
136136

137137
_PI_API(piextPluginGetOpaqueData)
138138

139+
_PI_API(piPluginGetLastError)
140+
139141
_PI_API(piTearDown)
140142

143+
141144
#undef _PI_API

sycl/include/CL/sycl/detail/pi.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ typedef enum {
117117
PI_IMAGE_FORMAT_NOT_SUPPORTED = CL_IMAGE_FORMAT_NOT_SUPPORTED,
118118
PI_MEM_OBJECT_ALLOCATION_FAILURE = CL_MEM_OBJECT_ALLOCATION_FAILURE,
119119
PI_LINK_PROGRAM_FAILURE = CL_LINK_PROGRAM_FAILURE,
120+
PI_PLUGIN_SPECIFIC_ERROR = -996, ///< PI_PLUGIN_SPECIFIC_ERROR indicates
121+
///< that an backend spcific error or
122+
///< warning has been emitted by the plugin.
120123
PI_COMMAND_EXECUTION_FAILURE =
121124
-997, ///< PI_COMMAND_EXECUTION_FAILURE indicates an error occurred
122125
///< during command enqueue or execution.
@@ -1796,6 +1799,18 @@ __SYCL_EXPORT pi_result piextPluginGetOpaqueData(void *opaque_data_param,
17961799
/// \param PluginParameter placeholder for future use, currenly not used.
17971800
__SYCL_EXPORT pi_result piTearDown(void *PluginParameter);
17981801

1802+
/// API to get Plugin specific warning and error messages.
1803+
/// \param message is a returned address to the first element in the message the
1804+
/// plugin owns the error message string. The string is thread-local. As a
1805+
/// result, different threads may return different errors. A message is
1806+
/// overwritten by the following error or warning that is produced within the
1807+
/// given thread. The memory is cleaned up at the end of the thread's lifetime.
1808+
///
1809+
/// \return PI_SUCCESS if plugin is indicating non-fatal warning. Any other
1810+
/// error code indicates that plugin considers this to be a fatal error and the
1811+
/// runtime must handle it or end the application.
1812+
__SYCL_EXPORT pi_result piPluginGetLastError(char **message);
1813+
17991814
struct _pi_plugin {
18001815
// PI version supported by host passed to the plugin. The Plugin
18011816
// checks and writes the appropriate Function Pointers in

sycl/plugins/cuda/pi_cuda.cpp

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,24 @@ pi_result map_error(CUresult result) {
5757
}
5858
}
5959

60+
// Global variables for PI_PLUGIN_SPECIFIC_ERROR
61+
constexpr size_t MaxMessageSize = 256;
62+
thread_local pi_result ErrorMessageCode = PI_SUCCESS;
63+
thread_local char ErrorMessage[MaxMessageSize];
64+
65+
// Utility function for setting a message and warning
66+
static void setErrorMessage(const char *message, pi_result error_code) {
67+
assert(strlen(message) <= MaxMessageSize);
68+
strcpy(ErrorMessage, message);
69+
ErrorMessageCode = error_code;
70+
}
71+
72+
// Returns plugin specific error and warning messages
73+
pi_result cuda_piPluginGetLastError(char **message) {
74+
*message = &ErrorMessage[0];
75+
return ErrorMessageCode;
76+
}
77+
6078
// Iterates over the event wait list, returns correct pi_result error codes.
6179
// Invokes the callback for the latest event of each queue in the wait list.
6280
// The callback must take a single pi_event argument and return a pi_result.
@@ -4729,13 +4747,20 @@ pi_result cuda_piextUSMEnqueuePrefetch(pi_queue queue, const void *ptr,
47294747
const pi_event *events_waitlist,
47304748
pi_event *event) {
47314749

4732-
// CUDA has an issue with cuMemPrefetchAsync returning cudaErrorInvalidDevice
4733-
// for Windows machines
4734-
// TODO: Remove when fix is found
4735-
#ifdef _MSC_VER
4736-
cl::sycl::detail::pi::die(
4737-
"cuda_piextUSMEnqueuePrefetch does not currently work on Windows");
4738-
#endif
4750+
// Certain cuda devices and Windows do not have support for some Unified
4751+
// Memory features. cuMemPrefetchAsync requires concurrent memory access
4752+
// for managed memory. Therfore, ignore prefetch hint if concurrent managed
4753+
// memory access is not available.
4754+
int isConcurrentManagedAccessAvailable = 0;
4755+
cuDeviceGetAttribute(&isConcurrentManagedAccessAvailable,
4756+
CU_DEVICE_ATTRIBUTE_CONCURRENT_MANAGED_ACCESS,
4757+
queue->get_context()->get_device()->get());
4758+
if (!isConcurrentManagedAccessAvailable) {
4759+
setErrorMessage("Prefetch hint ignored as device does not support "
4760+
"concurrent managed access",
4761+
PI_SUCCESS);
4762+
return PI_PLUGIN_SPECIFIC_ERROR;
4763+
}
47394764

47404765
// flags is currently unused so fail if set
47414766
if (flags != 0)
@@ -5083,6 +5108,7 @@ pi_result piPluginInit(pi_plugin *PluginInit) {
50835108

50845109
_PI_CL(piextKernelSetArgMemObj, cuda_piextKernelSetArgMemObj)
50855110
_PI_CL(piextKernelSetArgSampler, cuda_piextKernelSetArgSampler)
5111+
_PI_CL(piPluginGetLastError, cuda_piPluginGetLastError)
50865112
_PI_CL(piTearDown, cuda_piTearDown)
50875113

50885114
#undef _PI_CL

sycl/plugins/esimd_emulator/pi_esimd_emulator.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,25 @@ static std::mutex *PiESimdSurfaceMapLock = new std::mutex;
141141
// For PI_DEVICE_INFO_DRIVER_VERSION info
142142
static char ESimdEmuVersionString[32];
143143

144+
// Global variables for PI_PLUGIN_SPECIFIC_ERROR
145+
constexpr size_t MaxMessageSize = 256;
146+
thread_local pi_result ErrorMessageCode = PI_SUCCESS;
147+
thread_local char ErrorMessage[MaxMessageSize];
148+
149+
// Utility function for setting a message and warning
150+
[[maybe_unused]] static void setErrorMessage(const char *message,
151+
pi_result error_code) {
152+
assert(strlen(message) <= MaxMessageSize);
153+
strcpy(ErrorMessage, message);
154+
ErrorMessageCode = error_code;
155+
}
156+
157+
// Returns plugin specific error and warning messages
158+
pi_result piPluginGetLastError(char **message) {
159+
*message = &ErrorMessage[0];
160+
return ErrorMessageCode;
161+
}
162+
144163
using IDBuilder = sycl::detail::Builder;
145164

146165
template <int NDims>

sycl/plugins/hip/pi_hip.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,25 @@ pi_result map_error(hipError_t result) {
112112
}
113113
}
114114

115+
// Global variables for PI_PLUGIN_SPECIFIC_ERROR
116+
constexpr size_t MaxMessageSize = 256;
117+
thread_local pi_result ErrorMessageCode = PI_SUCCESS;
118+
thread_local char ErrorMessage[MaxMessageSize];
119+
120+
// Utility function for setting a message and warning
121+
[[maybe_unused]] static void setErrorMessage(const char *message,
122+
pi_result error_code) {
123+
assert(strlen(message) <= MaxMessageSize);
124+
strcpy(ErrorMessage, message);
125+
ErrorMessageCode = error_code;
126+
}
127+
128+
// Returns plugin specific error and warning messages
129+
pi_result hip_piPluginGetLastError(char **message) {
130+
*message = &ErrorMessage[0];
131+
return ErrorMessageCode;
132+
}
133+
115134
// Iterates over the event wait list, returns correct pi_result error codes.
116135
// Invokes the callback for the latest event of each queue in the wait list.
117136
// The callback must take a single pi_event argument and return a pi_result.
@@ -4989,6 +5008,7 @@ pi_result piPluginInit(pi_plugin *PluginInit) {
49895008

49905009
_PI_CL(piextKernelSetArgMemObj, hip_piextKernelSetArgMemObj)
49915010
_PI_CL(piextKernelSetArgSampler, hip_piextKernelSetArgSampler)
5011+
_PI_CL(piPluginGetLastError, hip_piPluginGetLastError)
49925012
_PI_CL(piTearDown, hip_piTearDown)
49935013

49945014
#undef _PI_CL

sycl/plugins/level_zero/pi_level_zero.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,25 @@ inline void zeParseError(ze_result_t ZeError, const char *&ErrorString) {
589589
} // switch
590590
}
591591

592+
// Global variables for PI_PLUGIN_SPECIFIC_ERROR
593+
constexpr size_t MaxMessageSize = 256;
594+
thread_local pi_result ErrorMessageCode = PI_SUCCESS;
595+
thread_local char ErrorMessage[MaxMessageSize];
596+
597+
// Utility function for setting a message and warning
598+
[[maybe_unused]] static void setErrorMessage(const char *message,
599+
pi_result error_code) {
600+
assert(strlen(message) <= MaxMessageSize);
601+
strcpy(ErrorMessage, message);
602+
ErrorMessageCode = error_code;
603+
}
604+
605+
// Returns plugin specific error and warning messages
606+
pi_result piPluginGetLastError(char **message) {
607+
*message = &ErrorMessage[0];
608+
return ErrorMessageCode;
609+
}
610+
592611
ze_result_t ZeCall::doCall(ze_result_t ZeResult, const char *ZeName,
593612
const char *ZeArgs, bool TraceError) {
594613
zePrint("ZE ---> %s%s\n", ZeName, ZeArgs);

sycl/plugins/opencl/pi_opencl.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,25 @@ CONSTFIX char clGetDeviceFunctionPointerName[] =
7171

7272
#undef CONSTFIX
7373

74+
// Global variables for PI_PLUGIN_SPECIFIC_ERROR
75+
constexpr size_t MaxMessageSize = 256;
76+
thread_local pi_result ErrorMessageCode = PI_SUCCESS;
77+
thread_local char ErrorMessage[MaxMessageSize];
78+
79+
// Utility function for setting a message and warning
80+
[[maybe_unused]] static void setErrorMessage(const char *message,
81+
pi_result error_code) {
82+
assert(strlen(message) <= MaxMessageSize);
83+
strcpy(ErrorMessage, message);
84+
ErrorMessageCode = error_code;
85+
}
86+
87+
// Returns plugin specific error and warning messages
88+
pi_result piPluginGetLastError(char **message) {
89+
*message = &ErrorMessage[0];
90+
return ErrorMessageCode;
91+
}
92+
7493
// USM helper function to get an extension function pointer
7594
template <const char *FuncName, typename T>
7695
static pi_result getExtFuncFromContext(pi_context context, T *fptr) {
@@ -1543,6 +1562,7 @@ pi_result piPluginInit(pi_plugin *PluginInit) {
15431562

15441563
_PI_CL(piextKernelSetArgMemObj, piextKernelSetArgMemObj)
15451564
_PI_CL(piextKernelSetArgSampler, piextKernelSetArgSampler)
1565+
_PI_CL(piPluginGetLastError, piPluginGetLastError)
15461566
_PI_CL(piTearDown, piTearDown)
15471567

15481568
#undef _PI_CL

sycl/source/detail/common.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@ const char *stringifyErrorCode(cl_int error) {
218218
*/
219219
case PI_FUNCTION_ADDRESS_IS_NOT_AVAILABLE:
220220
return "Function exists but address is not available";
221+
case PI_PLUGIN_SPECIFIC_ERROR:
222+
return "The plugin has emitted a backend specific error";
221223
case PI_COMMAND_EXECUTION_FAILURE:
222224
return "Command failed to enqueue/execute";
223225
default:

sycl/source/detail/plugin.hpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <CL/sycl/detail/pi.hpp>
1313
#include <CL/sycl/detail/type_traits.hpp>
1414
#include <CL/sycl/stl.hpp>
15+
#include <detail/config.hpp>
1516
#include <detail/plugin_printers.hpp>
1617
#include <memory>
1718
#include <mutex>
@@ -113,11 +114,35 @@ class plugin {
113114
/// \throw Exception if pi_result is not a PI_SUCCESS.
114115
template <typename Exception = cl::sycl::runtime_error>
115116
void checkPiResult(RT::PiResult pi_result) const {
117+
if (pi_result == PI_PLUGIN_SPECIFIC_ERROR) {
118+
char *message = nullptr;
119+
pi_result = call_nocheck<PiApiKind::piPluginGetLastError>(&message);
120+
121+
// If the warning level is greater then 2 emit the message
122+
if (detail::SYCLConfig<detail::SYCL_RT_WARNING_LEVEL>::get() >= 2)
123+
std::clog << message << std::endl;
124+
125+
// If it is a warning do not throw code
126+
if (pi_result == PI_SUCCESS)
127+
return;
128+
}
116129
__SYCL_CHECK_OCL_CODE_THROW(pi_result, Exception);
117130
}
118131

119132
/// \throw SYCL 2020 exception(errc) if pi_result is not PI_SUCCESS
120133
template <sycl::errc errc> void checkPiResult(RT::PiResult pi_result) const {
134+
if (pi_result == PI_PLUGIN_SPECIFIC_ERROR) {
135+
char *message = nullptr;
136+
pi_result = call_nocheck<PiApiKind::piPluginGetLastError>(&message);
137+
138+
// If the warning level is greater then 2 emit the message
139+
if (detail::SYCLConfig<detail::SYCL_RT_WARNING_LEVEL>::get() >= 2)
140+
std::clog << message << std::endl;
141+
142+
// If it is a warning do not throw code
143+
if (pi_result == PI_SUCCESS)
144+
return;
145+
}
121146
__SYCL_CHECK_CODE_THROW_VIA_ERRC(pi_result, errc);
122147
}
123148

sycl/test/abi/pi_level_zero_symbol_check.dump

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ piSamplerCreate
7878
piSamplerGetInfo
7979
piSamplerRelease
8080
piSamplerRetain
81+
piPluginGetLastError
8182
piTearDown
8283
piclProgramCreateWithSource
8384
piextContextCreateWithNativeHandle

sycl/test/abi/pi_opencl_symbol_check.dump

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ piProgramCreateWithBinary
2626
piProgramLink
2727
piQueueCreate
2828
piSamplerCreate
29+
piPluginGetLastError
2930
piTearDown
3031
piclProgramCreateWithSource
3132
piextContextCreateWithNativeHandle

sycl/tools/sycl-trace/pi_trace_collector.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ static std::string getResult(pi_result Res) {
111111
return "PI_COMMAND_EXECUTION_FAILURE";
112112
case PI_FUNCTION_ADDRESS_IS_NOT_AVAILABLE:
113113
return "PI_FUNCTION_ADDRESS_IS_NOT_AVAILABLE";
114+
case PI_PLUGIN_SPECIFIC_ERROR:
115+
return "PI_PLUGIN_SPECIFIC_ERROR";
114116
case PI_ERROR_UNKNOWN:
115117
return "PI_ERROR_UNKNOWN";
116118
}

0 commit comments

Comments
 (0)