I'm working on an application using both GLib and CUDA in C. It seems that there's a conflict when importing both glib.h and cuda_runtime.h for a .cu file.
7 months ago GLib made a change to avoid a conflict with pixman's macro. They added __
before and after the token noinline
in gmacros.h: https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2059
That should have worked, given that gcc claims:
You may optionally specify attribute names with
__
preceding and following the name. This allows you to use them in header files without being concerned about a possible macro of the same name. For example, you may use the attribute name__noreturn__
instead of noreturn.
However, CUDA does use __
in its macros, and __noinline__
is one of them. They acknowledge the possible conflict, and add some compiler checks to ensure it won't conflict in regular c files, but it seems that in .cu files it still applies:
#if defined(__CUDACC__) || defined(__CUDA_ARCH__) || defined(__CUDA_LIBDEVICE__)
/* gcc allows users to define attributes with underscores,
e.g., __attribute__((__noinline__)).
Consider a non-CUDA source file (e.g. .cpp) that has the
above attribute specification, and includes this header file. In that case,
defining __noinline__ as below would cause a gcc compilation error.
Hence, only define __noinline__ when the code is being processed
by a CUDA compiler component.
*/
#define __noinline__ \
__attribute__((noinline))
I'm pretty new to CUDA development, and this is clearly a possible issue that they and gcc are aware of, so am I just missing a compiler flag or something? Or is this a genuine conflict that GLib would be left to solve?
Environment: glib 2.70.2, cuda 10.2.89, gcc 9.4.0
CodePudding user response:
GCC's documentation states:
You may optionally specify attribute names with
__
preceding and following the name. This allows you to use them in header files without being concerned about a possible macro of the same name. For example, you may use the attribute name__noreturn__
instead ofnoreturn
.
Now, that's only assuming you avoid double-underscored names the compiler and library use; and they may use such names. So, if you're using NVCC - NVIDIA could declare "we use noinline and you can't use it".
... and indeed, this is basically the case: The macro is protected as follows:
#if defined(__CUDACC__) || defined(__CUDA_ARCH__) || defined(__CUDA_LIBDEVICE__)
#define __noinline__ __attribute__((noinline))
#endif /* __CUDACC__ || __CUDA_ARCH__ || __CUDA_LIBDEVICE__ */
__CUDA_ARCH__
- only defined for device-side code, where NVCC is the compiler (ignoring clang CUDA support here).__CUDA_LIBDEVICE__
- Don't know where this is used, but you're certainly not building it, so you don't care about that.__CUDACC__
defined when NVCC is compiling the code.
So in regular host-side code, including this header will not conflict with Glib's definitions.
Bottom line: NVIDIA is (basically) doing the right thing here and it shouldn't be a real problem.
CodePudding user response:
As you now, all .cu files are to be compiled using nvcc, and __CUDACC__
macro will be defined automatically when nvcc is compiling any dependencies of the passed .cu files. This macro is usually used to distinguish between nvcc and gcc compiler in sources which is visible to your Cuda source. All in all, this macro is specifically useful when you want to hide some specific definitions from nvcc!
To your answer, I think same macro definitions in glib and Cuda does not matter, because this libs were compiled separately beforehand and you are just linking with them. As for the __noinline__
definition which is visible to your .cu file, it will be the same as the one (either glib.h or cuda_runtime.h) you have included later.