ddemidov / vexcl

VexCL is a C++ vector expression template library for OpenCL/CUDA/OpenMP
http://vexcl.readthedocs.org
MIT License
702 stars 82 forks source link

Compiling with vexcl boost::compute backend fails on OSX #222

Closed chrism0dwk closed 7 years ago

chrism0dwk commented 7 years ago

On OSX 10.12.6 with Boost 1.64.0 installed, programs using VexCL fail to compile if boost::compute backend is requested.

Minimal reproducible example:

#include <boost/compute.hpp>
#define VEXCL_BACKEND_COMPUTE
#include <vexcl/vexcl.hpp>
int main(int argc, char* argv[]) { return 0; }

fails on compiling with

$ g++ -I$BOOSTDIR/include -I$VEXCLDIR -std=c++11 -o vexcl_text vexcl_test.cpp -framework OpenCL -L$BOOSTDIR/lib -lboost_system -lboost_filesystem

giving this output.

This error does not occur on my Linux system (CentOS 7.5) with either GCC-4.8.5 or Clang-3.4.2, and AMDAPPSDK-3.0 OpenCL library (the OpenCL library is likely irrelevant).

ddemidov commented 7 years ago

It looks like the problem is that on OSX compute::is_fundamental<unsigned long> type is equal to false_type, which is strange, because of this line in boost/compute/type_traits/is_fundamental.hpp.

Can you please check the output of the following example?

#include <iostream>
#include<boost/compute.hpp>

int main(int argc, char* argv[]) {
#define CHECK_TYPE(t) \
    std::cout << #t ": " << boost::compute::is_fundamental<t>::value << std::endl

    CHECK_TYPE(unsigned long);
    CHECK_TYPE(size_t);
}

On my linux system this gives me

unsigned long: 1
size_t: 1
ddemidov commented 7 years ago

Pinging @jszuppe just in case.

chrism0dwk commented 7 years ago

@ddemidov ho hum, I get the following output on OSX: unsigned long: 0 size_t: 0

...which I guess is different to Linux (I can verify both are true on my Linux machine).

ddemidov commented 7 years ago

I guess OSX needs a workaround similar to this one for Boost.Compute. I am just not yet sure how exactly to do this.

jszuppe commented 7 years ago

I'll look into it soon.

ddemidov commented 7 years ago

@chrism0dwk , would something like this compile for you on OSX?

#include <iostream>
#include <boost/compute.hpp>

// size_t and ptrdiff_t on OSX are not synonyms to long and ulong
#if defined(__APPLE__)
namespace boost {
namespace compute {

template <> struct is_fundamental<size_t>    : boost::true_type {};
template <> struct is_fundamental<ptrdiff_t> : boost::true_type {};

namespace detail {

template <> struct type_name_trait<size_t>
    : type_name_trait< boost::mpl::if_c<sizeof(size_t) == sizeof(cl_uint), cl_uint, cl_ulong>::type >
{};

template <> struct type_name_trait<ptrdiff_t>
    : type_name_trait< boost::mpl::if_c<sizeof(ptrdiff_t) == sizeof(cl_int), cl_int, cl_long>::type >
{};

inline meta_kernel& operator<<(meta_kernel &k, size_t v) {
    std::ostringstream s;
    s << v;
    return k << s.str();
}

inline meta_kernel& operator<<(meta_kernel &k, ptrdiff_t v) {
    std::ostringstream s;
    s << v;
    return k << s.str();
}

} // namespace detail
} // namespace compute
} // namespace boost
#endif

#define VEXCL_BACKEND_COMPUTE
#include <vexcl/vexcl.hpp>

int main() { }
chrism0dwk commented 7 years ago

Hi Denis,

So all but two errors are now fixed:

$ g++ -std=c++11 -I/usr/local/include -Ivexcl -o testbug testbug.cpp -L/usr/local/lib -lboost_system
testbug.cpp:15:7: error: implicit instantiation of undefined template
      'boost::compute::detail::type_name_trait<boost::mpl::if_c<false, unsigned int,
      unsigned long long> >'
    : type_name_trait< boost::mpl::if_c<sizeof(size_t) == sizeof(cl_uint), cl_uint...
      ^
/usr/local/include/boost/compute/type_traits/type_name.hpp:24:8: note: template is declared
      here
struct type_name_trait;
       ^
testbug.cpp:19:7: error: implicit instantiation of undefined template
      'boost::compute::detail::type_name_trait<boost::mpl::if_c<false, int, long long> >'
    : type_name_trait< boost::mpl::if_c<sizeof(ptrdiff_t) == sizeof(cl_int), cl_int...
      ^
/usr/local/include/boost/compute/type_traits/type_name.hpp:24:8: note: template is declared
      here
struct type_name_trait;
       ^
2 errors generated.
ddemidov commented 7 years ago

Sorry, I've made an error in my snippet (now updated). Should be mpl::if_c<...>::type instead of mpl::if_c<...>.

chrism0dwk commented 7 years ago

Yup that's sorted it! All compiles well now. Thanks :)

(I really must improve my C++ metaprogramming...)

ddemidov commented 7 years ago

@jszuppe, would you accept a PR into Boost.Compute with the above changes?

jszuppe commented 7 years ago

Yes, of course :) I'm a little bit busy (first week after vacations), but I should be able to review it and accept today or tomorrow (if you post it today).

ddemidov commented 7 years ago

boostorg/compute#737

ddemidov commented 7 years ago

Fixed on the boost.compute side.