CUDA on Ubuntu: unsupported GNU version! gcc versions later than 5 are not supported!

https://carterturn.com/h/Guides/NVIDIA%20CUDA%208.0%20with%20GCC%207

After updating my system to Fedora 26, I was pleased to find that I had a shiny new GCC version, GCC 7.1.1. Unfortuntely, the most recent version of NVIDIA’s CUDA, CUDA 8.0, which I also enjoy using, is only compatible with GCC 5. There are documented attempts of getting CUDA 8.0 to work nicely with GCC 6.x, but I want to start using GCC 7’s features. Here, I will document my workaround for this, which allows one to use most of CUDA’s features with GCC 7.1.1 and C++ 11.
Install CUDA 8.0

I have had more luck using the runfile installer for CUDA, although NVIDIA does provide rpm instalers. The installation process is nearly the same, but we do need an additional flag, the –override flag. The command is thus:
sudo ./cuda_8.0.61_375.26_linux-run –override
Say yes when it asks to install in an unsupported configuration (that is the entire point of this, right?).
Modify host_config.h

On the first run of nvcc, you will be presented with this error message:
In file included from /usr/local/cuda/bin/..//include/cuda_runtime.h:78:0,
from :0:
/usr/local/cuda/bin/..//include/host_config.h:119:2: error: #error – unsupported GNU version! gcc versions later than 5 are not supported!
#error – unsupported GNU version! gcc versions later than 5 are not supported!
This will be the easiest error to fix. Simply open /usr/local/cuda/include/host_config.h, go to line 117 (M-g M-g 117 RET in emacs), and replace #if GNUC > 5 with #if GNUC > 9000 (or simply comment out lines 117-121, which will lead to slightly faster compiling). Lines 117-121 should go from:

if GNUC > 5

  • @ingroup utilities
    */

error – unsupported GNU version! gcc versions later than 5 are not supported!

endif /* GNUC > 5 */

to

if GNUC > 1000

  • @ingroup utilities
    */

error – unsupported GNU version! gcc versions later than 5 are not supported!

endif /* GNUC > 5 */

That should work for a long time.
Start using -std=c++11

Now if you run nvcc, you will be presented with over 100 errors. Add the -std=c++11 flag, and most of these will go away.
Fix math_functions.h

The two errors that remain looked like
/usr/local/cuda/bin/..//include/math_functions.h(8897): error: cannot overload functions distinguished by return type alone

/usr/local/cuda/bin/..//include/math_functions.h(8901): error: cannot overload functions distinguished by return type alone
When I looked at those functions, they were isnan and isinf. I am guessing that in GCC 5.x those were only accessible via std::, and GCC 6.x made them more accessible. I decided to rename them in math_functions.h. This is where CUDA features start being sacrificed.
Goto line 8897 in /usr/local/cuda/include/math_functions.h and change isnan to cuisnan. Goto line 8901 in /usr/local/cuda/include/math_functions.h and change isinf to cuisinf.
Lines 8887-8905 should now look like this:

if GNUC > 5 && __cplusplus >= 201103L

namespace std {
DEVICE_FUNCTIONS_DECL cudart_builtin constexpr bool signbit(float x);
DEVICE_FUNCTIONS_DECL cudart_builtin constexpr bool signbit(double x);
DEVICE_FUNCTIONS_DECL cudart_builtin constexpr bool signbit(long double x);
DEVICE_FUNCTIONS_DECL cudart_builtin constexpr bool isfinite(float x);
DEVICE_FUNCTIONS_DECL cudart_builtin constexpr bool isfinite(double x);
DEVICE_FUNCTIONS_DECL cudart_builtin constexpr bool isfinite(long double x);
DEVICE_FUNCTIONS_DECL cudart_builtin constexpr bool isnan(float x);
/* GCC 6.1 uses ::isnan(double x) for isnan(double x) */
DEVICE_FUNCTIONS_DECL cudart_builtin int cuisnan(double x) throw();
DEVICE_FUNCTIONS_DECL cudart_builtin constexpr bool isnan(long double x);
DEVICE_FUNCTIONS_DECL cudart_builtin constexpr bool isinf(float x);
/* GCC 6.1 uses ::isinf(double x) for isinf(double x) */
DEVICE_FUNCTIONS_DECL cudart_builtin int cuisinf(double x) throw();
DEVICE_FUNCTIONS_DECL cudart_builtin constexpr bool isinf(long double x);
}

else /* !(GNUC > 5 && __cplusplus >= 201103L) */

Modify move.h

How if you run nvcc, you will be presented with 4 errors, all containing /usr/include/c++/7/bits/move.h(48): error: identifier “__builtin_addressof” is undefined.
If we go to line 48 of /usr/include/c++/7/bits/move.h, we see that it is in a function that attempts to define __addressof.
// Used, in C++03 mode too, by allocators, etc.
/**
* @brief Same as C++11 std::addressof
* @ingroup utilities
*/
template
inline _GLIBCXX_CONSTEXPR _Tp*
__addressof(_Tp& __r) _GLIBCXX_NOEXCEPT
{ return __builtin_addressof(__r); }
Unfortunately, we can not simply surround this with a check for CUDA and remove it if we are using CUDA, other parts of C++ need it. However, it is possible to add an additional (probably less optimized) piece of code, such as the one from this stackoverflow post.
Lines 36-60 of /usr/include/c++/7/bits/move.h should now be
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

// Used, in C++03 mode too, by allocators, etc.
/**
* @brief Same as C++11 std::addressof
* @ingroup utilities
*/

ifndef CUDACC

template
inline _GLIBCXX_CONSTEXPR _Tp*
__addressof(_Tp& __r) _GLIBCXX_NOEXCEPT
{ return __builtin_addressof(__r); }

else

template
inline _Tp*
__addressof(_Tp& __r) _GLIBCXX_NOEXCEPT
{
return reinterpret_cast<_Tp*>
(&const_cast(reinterpret_cast(__r)));
}

endif

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace

Modify STL

Several header files in the C++ STL also need to be modified, just surround lines with an error with #ifndef CUDACC and #endif
Conclusion

It is possible to make CUDA 8.0 work with GCC 7.1.1, but some features of CUDA are lost. This may not be too much of a problem for you; it seems to be working for me.

猜你喜欢

转载自blog.csdn.net/StreamRock/article/details/80925619