Boost Functional compile error

Hi,

I’ve been having a problem compiling a code I have that uses the Boost libraries, and fails to compile straight C++ (no CUDA) code.

I’ve searched the forums and couldn’t find any reference to it.

I’ve managed to trace it to the following minimal example (filename boostTestFunc.cu)

[codebox]

// Testing Boost Functional with CUDA

#include <boost/functional/hash.hpp>

int main(void)

{

boost::hash float_hash;

return 0;

}

[/codebox]

My code uses more general Boost libraries, in particular the Functional library, which end up including this one, so it’s not just a matter of working around this one include file.

I am using Ubuntu 10.4, with nvcc 3.2RC, and this gives the following error:

[codebox]

$ nvcc boostTestFunc.cu -o boostTestFunc -I /opt/boost-1.44.0-gcc/include/

boostTestFunc.cu(7): warning: variable “float_hash” was declared but never referenced

/usr/include/c++/4.4/cmath(500): error: identifier “__builtin_fpclassify” is undefined

      detected during:

        instantiation of "__gnu_cxx::__enable_if<std::__is_arithmetic<_Tp>::__value, int>::__type std::fpclassify(_Tp) [with _Tp=float]" 

/opt/boost-1.44.0-gcc/include/boost/functional/hash/detail/hash_float.hpp(65): here

        instantiation of "size_t boost::hash_detail::float_hash_value(T) [with T=float]" 

/opt/boost-1.44.0-gcc/include/boost/functional/hash/hash.hpp(315): here

/usr/include/c++/4.4/cmath(500): error: identifier “__builtin_fpclassify” is undefined

      detected during:

        instantiation of "__gnu_cxx::__enable_if<std::__is_arithmetic<_Tp>::__value, int>::__type std::fpclassify(_Tp) [with _Tp=double]" 

/opt/boost-1.44.0-gcc/include/boost/functional/hash/detail/hash_float.hpp(65): here

        instantiation of "size_t boost::hash_detail::float_hash_value(T) [with T=double]" 

/opt/boost-1.44.0-gcc/include/boost/functional/hash/hash.hpp(320): here

/usr/include/c++/4.4/cmath(500): error: identifier “__builtin_fpclassify” is undefined

      detected during:

        instantiation of "__gnu_cxx::__enable_if<std::__is_arithmetic<_Tp>::__value, int>::__type std::fpclassify(_Tp) [with _Tp=long double]" 

/opt/boost-1.44.0-gcc/include/boost/functional/hash/detail/hash_float.hpp(65): here

        instantiation of "size_t boost::hash_detail::float_hash_value(T) [with T=long double]" 

/opt/boost-1.44.0-gcc/include/boost/functional/hash/hash.hpp(325): here

3 errors detected in the compilation of “/tmp/tmpxft_00004137_00000000-4_boostTestFunc.cpp1.ii”.

[/codebox]

This uses the default Ubuntu 10.4 compiler - gcc 4.4.3 (Ubuntu 4.4.3-4ubuntu5)

However, if I use gcc 4.3.4 (Ubuntu 4.3.4-10ubuntu1), then:

[codebox]

$ nvcc boostTestFunc.cu -o boostTestFunc -I /opt/boost-1.44.0-gcc/include/ --compiler-bindir=/opt/gcc-4.3

boostTestFunc.cu(7): warning: variable “float_hash” was declared but never referenced

boostTestFunc.cu(7): warning: variable “float_hash” was declared but never referenced

[/codebox]

Note: /opt/gcc-4.3 just contains a symlink to the appropriate gcc binary, and I’m using Boost version 1.44.0, built with the gcc toolset.

Are there any known workarounds/solutions to this, or is this a problem with nvcc compatibility with gcc 4.4, or with the Boost libraries?

Hi,

I’ve been having a problem compiling a code I have that uses the Boost libraries, and fails to compile straight C++ (no CUDA) code.

I’ve searched the forums and couldn’t find any reference to it.

I’ve managed to trace it to the following minimal example (filename boostTestFunc.cu)

[codebox]

// Testing Boost Functional with CUDA

#include <boost/functional/hash.hpp>

int main(void)

{

boost::hash float_hash;

return 0;

}

[/codebox]

My code uses more general Boost libraries, in particular the Functional library, which end up including this one, so it’s not just a matter of working around this one include file.

I am using Ubuntu 10.4, with nvcc 3.2RC, and this gives the following error:

[codebox]

$ nvcc boostTestFunc.cu -o boostTestFunc -I /opt/boost-1.44.0-gcc/include/

boostTestFunc.cu(7): warning: variable “float_hash” was declared but never referenced

/usr/include/c++/4.4/cmath(500): error: identifier “__builtin_fpclassify” is undefined

      detected during:

        instantiation of "__gnu_cxx::__enable_if<std::__is_arithmetic<_Tp>::__value, int>::__type std::fpclassify(_Tp) [with _Tp=float]" 

/opt/boost-1.44.0-gcc/include/boost/functional/hash/detail/hash_float.hpp(65): here

        instantiation of "size_t boost::hash_detail::float_hash_value(T) [with T=float]" 

/opt/boost-1.44.0-gcc/include/boost/functional/hash/hash.hpp(315): here

/usr/include/c++/4.4/cmath(500): error: identifier “__builtin_fpclassify” is undefined

      detected during:

        instantiation of "__gnu_cxx::__enable_if<std::__is_arithmetic<_Tp>::__value, int>::__type std::fpclassify(_Tp) [with _Tp=double]" 

/opt/boost-1.44.0-gcc/include/boost/functional/hash/detail/hash_float.hpp(65): here

        instantiation of "size_t boost::hash_detail::float_hash_value(T) [with T=double]" 

/opt/boost-1.44.0-gcc/include/boost/functional/hash/hash.hpp(320): here

/usr/include/c++/4.4/cmath(500): error: identifier “__builtin_fpclassify” is undefined

      detected during:

        instantiation of "__gnu_cxx::__enable_if<std::__is_arithmetic<_Tp>::__value, int>::__type std::fpclassify(_Tp) [with _Tp=long double]" 

/opt/boost-1.44.0-gcc/include/boost/functional/hash/detail/hash_float.hpp(65): here

        instantiation of "size_t boost::hash_detail::float_hash_value(T) [with T=long double]" 

/opt/boost-1.44.0-gcc/include/boost/functional/hash/hash.hpp(325): here

3 errors detected in the compilation of “/tmp/tmpxft_00004137_00000000-4_boostTestFunc.cpp1.ii”.

[/codebox]

This uses the default Ubuntu 10.4 compiler - gcc 4.4.3 (Ubuntu 4.4.3-4ubuntu5)

However, if I use gcc 4.3.4 (Ubuntu 4.3.4-10ubuntu1), then:

[codebox]

$ nvcc boostTestFunc.cu -o boostTestFunc -I /opt/boost-1.44.0-gcc/include/ --compiler-bindir=/opt/gcc-4.3

boostTestFunc.cu(7): warning: variable “float_hash” was declared but never referenced

boostTestFunc.cu(7): warning: variable “float_hash” was declared but never referenced

[/codebox]

Note: /opt/gcc-4.3 just contains a symlink to the appropriate gcc binary, and I’m using Boost version 1.44.0, built with the gcc toolset.

Are there any known workarounds/solutions to this, or is this a problem with nvcc compatibility with gcc 4.4, or with the Boost libraries?

  1. Unfortunately I don’t have a solution to this, but can confirm it with nvcc 3.2, gcc-4.4 (Debian 4.4.5-10) on Debian GNU/Linux 6.0 (squeeze). It seems to be more related to libstdc++ 4.4 than directly related to boost (since it differs between gcc versions but is consistent with boost 1.42.0 and 1.45.0)

There’s a related thread not concerning nvcc but icc compatibility (and the icc issue seems to be fixed with boost 1.45.0) on the boost users mailinglist.

Did you get any further on this? For you it seems using 4.3 as host compiler seems to solve the issue.


  1. I see another issue with a different boost header (on any combination of gcc 4.2, 4.3, 4.4 and boost 1.42.0, 1.45.0). Minimal working example:
#include <boost/unordered/detail/move.hpp>

int main(void)

{

  return 0;

}

yields

/usr/include/boost/unordered/detail/move.hpp:60: error: `&' cannot appear in a constant-expression

/usr/include/boost/unordered/detail/move.hpp:60: error: template argument 1 is invalid

/usr/include/boost/unordered/detail/move.hpp:60: error: invalid type in declaration before ‘;’ token

  1. Yet another issue with libstdc++ in gcc 4.3 and above (not boost related). Minimal working example:
#include <cmath>

int main(void)

{

  return std::isnormal(0);

}

yields (on 4.3, same on 4.4)

/usr/include/c++/4.3/cmath(549): error: identifier "__builtin_isnormal" is undefined

          detected during instantiation of "__gnu_cxx::__enable_if<std::__is_arithmetic<_Tp>::__value, int>::__type std::isnormal(_Tp) [with _Tp=int]" 

boostTestFunc.cu(5): here

I couldn’t find any version of gcc as the host compiler that will compile my code. Are there any know workarounds? I don’t quite know how to proceed, since it’s not easily possible to isolate the code such that nvcc doesn’t see it.

Any hints appreciated!

I’m afraid I haven’t got any further with this as this is somewhat of a side-project for me. However, thanks for reminding me about this, as I’ve just submitted my original bug via the NVIDIA Developer interface, which ought to at least get a reply from NVIDIA, if not an immediate fix.

Great! What’s the bug ID so I can monitor the progress on this?


Following up on my own questions, I could work around them as follows:

  1. Use gcc-4.3 as the host compiler, couldn’t find any solution for 4.4

  2. Define BOOST_UNORDERED_NO_HAS_MOVE_ASSIGN by adding -Xcompiler -DBOOST_UNORDERED_NO_HAS_MOVE_ASSIGN to the nvcc flags. Note that this boost feature is thereby disabled.

  3. Disable the built-in by adding -Xcompiler -D"__builtin_isnormal=isnormal" to the nvcc flags. This does not work for 1) in the same way.

All of these workarounds are mere hacks and it’s a major inconvenience and headache to debug these issues. I hope the NVIDIA devs could take a look at this and try to improve nvcc compatibility with the STL and boost further. Both are essential for many CUDA developers.

Bug ID: 781456 (Division: GPU Computing)

I’ve just had confirmation from NVIDIA that this bug has been fixed in a recent build, so this should work with the next release of the toolkit.

Hi Philip,

I also tried to mix boost and CUDA. But most boost headers will produce error messages when included in CUDA code. The same is true for blitz++ and possibly other C++ libraries. My explanation to this is that ‘CUDA C’ is a standalone programming language with its own compiler (nvcc) which is compatible to ‘C’ but not to ‘C++’ as it only implements a subset of ‘C++’. This is a matter for all the code you compile with ‘nvcc’ - not just for the device code. My way to deal with this is not to use any C++ libraries in the CUDA code and provide a C interface for all CUDA stuff. Then I call my CUDA stuff with C interface from the C++ code. This implies to have wrapper code on the C++ side, e.g. to extract data from blitz++ arrays, from std::vector’s, etc. This is annoying. Maybe a solution would be to use the ‘CUDA API’ instead of ‘CUDA C’ but I haven’t had a closer look on this.

Regards,
enuhtac

BTW: may it be that you are working at DAMTP at the university of Cambridge?

Hi enuhtac,

I tend to see CUDA as an extension to the C subset of C++ and, increasingly, as an extension to C++, allowing existing C++ code to be compiled to run on GPUs with a minimum of effort. NVIDIA appear to be moving towards supporting all of C++ in device code, including the extra support of memory space with the Fermi cards, and it would therefore be useful to have all of Boost’s (or, indeed, blitz’s) functionality available within device code (although the slight problem of having to add device to lots of functions currently causes problems for this).

I appreciate that one solution to my problem would be to separate device code from host code, but I’m dealing with a fairly large project (many source files) that is already written and optimized for CPU, and it would take a lot of refactoring to move all the CPU-intensive routines into one source file, while having the same code compile optimally for CPU and GPU. This is my other main problem with nvcc at the moment, that there is no CUDA-aware linker, although I realise that writing one would probably take a lot of effort. I think I would have the same issue with using the CUDA API as well, since different objects files cannot (I think) communicate (easily).

The way that NVIDIA and other many-core supporting companies seem to be moving is to allow code (but not necessarily object-files or specific optimizations) to be processor-agnostic and still attain very good performance (if not perhaps quite optimal) on all platforms, so I think it’s right that the difference between host and device language/code should be as little as possible, while allowing for different optimizations for different processor-types/memory layouts. Indeed, this is the route that developers of higher-level CUDA wrappers/libraries are moving in.

Philip

BTW: Nearly right, but I’m now working in the Physics Department at Cambridge, not DAMTP…