When I try to compile a simple CUDA program, e.g. the vectorAdd sample, I get errors about incompatible exception specifications:
$ nvcc -I ../../../Common/ -ccbin g++-13 -Wno-deprecated-gpu-targets vectorAdd.cu
/usr/include/x86_64-linux-gnu/bits/mathcalls.h(79): error: exception specification is incompatible with that of previous function "cospi" (declared at line 2601 of /usr/local/cuda/bin/../targets/x86_64-linux/include/crt/math_functions.h)
extern double cospi (double __x) noexcept (true); extern double __cospi (double __x) noexcept (true);
^
/usr/include/x86_64-linux-gnu/bits/mathcalls.h(81): error: exception specification is incompatible with that of previous function "sinpi" (declared at line 2556 of /usr/local/cuda/bin/../targets/x86_64-linux/include/crt/math_functions.h)
extern double sinpi (double __x) noexcept (true); extern double __sinpi (double __x) noexcept (true);
^
/usr/include/x86_64-linux-gnu/bits/mathcalls.h(79): error: exception specification is incompatible with that of previous function "cospif" (declared at line 2623 of /usr/local/cuda/bin/../targets/x86_64-linux/include/crt/math_functions.h)
extern float cospif (float __x) noexcept (true); extern float __cospif (float __x) noexcept (true);
^
/usr/include/x86_64-linux-gnu/bits/mathcalls.h(81): error: exception specification is incompatible with that of previous function "sinpif" (declared at line 2579 of /usr/local/cuda/bin/../targets/x86_64-linux/include/crt/math_functions.h)
extern float sinpif (float __x) noexcept (true); extern float __sinpif (float __x) noexcept (true);
^
4 errors detected in the compilation of "vectorAdd.cu".
This didn't use to happen on my system before... what's going on?
System information:
As @RobertCrovella said on the NVIDIA developer forums - this is due to your system using glibc version 2.41. You can overcome this by patching the relevant header (math_functions.h) to bring the noexcept specification in line with your system's glibc header. Here's a patch with the necessary changes, up to line numbers; thanks goes to stefantalparau at the aforementioned forum:
--- a/math_functions.h 00:02:30.815134398 +0300
+++ b/math_functions.h 00:03:30.815134398 +0300
@@ -2547,7 +2547,7 @@
*
* \note_accuracy_double
*/
-extern __DEVICE_FUNCTIONS_DECL__ __device_builtin__ double sinpi(double x);
+extern __DEVICE_FUNCTIONS_DECL__ __device_builtin__ double sinpi(double x) noexcept (true);
/**
* \ingroup CUDA_MATH_SINGLE
* \brief Calculate the sine of the input argument
@@ -2570,7 +2570,7 @@
*
* \note_accuracy_single
*/
-extern __DEVICE_FUNCTIONS_DECL__ __device_builtin__ float sinpif(float x);
+extern __DEVICE_FUNCTIONS_DECL__ __device_builtin__ float sinpif(float x) noexcept (true);
/**
* \ingroup CUDA_MATH_DOUBLE
* \brief Calculate the cosine of the input argument
@@ -2592,7 +2592,7 @@
*
* \note_accuracy_double
*/
-extern __DEVICE_FUNCTIONS_DECL__ __device_builtin__ double cospi(double x);
+extern __DEVICE_FUNCTIONS_DECL__ __device_builtin__ double cospi(double x) noexcept (true);
/**
* \ingroup CUDA_MATH_SINGLE
* \brief Calculate the cosine of the input argument
@@ -2614,7 +2614,7 @@
*
* \note_accuracy_single
*/
-extern __DEVICE_FUNCTIONS_DECL__ __device_builtin__ float cospif(float x);
+extern __DEVICE_FUNCTIONS_DECL__ __device_builtin__ float cospif(float x) noexcept (true);
/**
* \ingroup CUDA_MATH_DOUBLE
* \brief Calculate the sine and cosine of the first input argument
You need to apply this patch in the directory in which the math_functions.h file is located; or alternatively, do this:
pushd /usr/local/cuda/include/crt
patch < /path/to/cuda_glibc_241_compat.diff
popd
assuming CUDA is installed under /usr/local/cuda; that you've saved this patch as /path/to/cuda_glibc_241_compat.diff; and that you're root and have write access to that directory.
Note: Some commenters suggest there may be additional functions which need to be marked noexcept (true), like rsqrt() - but possibly only with other combinations of CUDA and glibc versions, respectively. At any rate, the principle would be the same as for these trigonometric functions.
Q: But is that safe to do?
A: Umm... I think so. That's because noexcept does not distinguish between functions - unlike the function name and the parameter types; and these are device builtin functions, which would not throw an exception anyway. So, it should still be the "same" function. I believe it should not matter whether or not you device-link together code compiled using the different versions of this header. But - I'm not 100% sure. edit: Remember to watch out for snags if you later update your glibc or CUDA version.