Unable to use boost::bind with intel MIC in a function with comparison operators

Unable to use boost::bind with intel MIC in a function with comparison operators

Hi

I am using a test program for compiling a boost::bind in intel MIC. Here are the details of the code and platform on which it is compiled.  I am using thread building blocks in my code, but the following code does not contain any TBB threads. The errors in my test code below and original code are same.

Compiler : Intel 13.0.1. I am using our lab's compiler installed on a cluster. The TBB is installed in my home directory. boost 1.55 is also installed in my home location.

Compiled for MIC: icpc -mmic -L/home/aniketnp/tbb42_20140122oss/lib/mic -std=c++11 -I/home/aniketnp/boost_1_55_0 -I/home/aniketnp/tbb42_20140122oss/include    test.cpp

Scenario: a functor takes 2 arguments in its operator()() by using a boost::bind() method. The operator()() method contains a function which uses comparisons ( < or > ) using if-else logic. The error pops up here. Here is the following code.

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

using namespace std;

struct Info_t {
 int start;
 int end;
 Info_t(int s=0,int e=0) : start(s), end(e) {  }
};

template <typename T, typename time>
void process_info(const T& info1, const T& info2, const time& t) {

  //the below gives compiler error
  if ((info1.start < info2.end) && (info2.end > info1.end) && (info1.end < info2.start) )
   std::cout << "yess error with mic" << std::endl;

  //the below if works fine
  if ((info1.start < info2.end) && (info2.end > info1.end))
   std::cout << "no error at all" << std::endl;
}

template<typename Time>
struct my_functor {
 public:
  my_functor() {  }
  my_functor(Time&  time_) : time(time_) {   }

 typedef void result_type;

 template<typename info_t>
 void operator()(const info_t& info1, const info_t& info2) {
   const auto& i1 = info1;
   const auto& i2 = info2;
   process_info<info_t, Time> (i1,i2, time);
 }

 private:
  Time&  time;
};

int main() {
Info_t  i1(10,2);
Info_t  i2(2,10);
int t = 1;
auto func = boost::bind( my_functor<int>(t), _1, _2 );
func(i1,i2);
return 0;
}

 

Compilation Error :  See the "  ^   "  at 3 places below.

test.cpp(16): error: expression must have a constant value
    if ((info1.start < info2.end) && (info2.end > info1.end) && (info1.end < info2.start) )
                                                                             ^
          detected during:
            instantiation of "void my_functor<Time>::operator()(const info_t &, const info_t &) [with Time=int, info_t=Info_t]" at line 313 of "/home/aniketnp/boost_1_55_0/boost/bind/bind.hpp"
            instantiation of "void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F &, A &, int) [with A1=boost::arg<1>, A2=boost::arg<2>, F=my_functor<int>, A=boost::_bi::list2<Info_t &, Info_t &>]" at line 61 of "/home/aniketnp/boost_1_55_0/boost/bind/bind_template.hpp"
            instantiation of "boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()(A1 &, A2 &) [with R=boost::_bi::unspecified, F=my_functor<int>, L=boost::_bi::list2<boost::arg<1>, boost::arg<2>>, A1=Info_t, A2=Info_t]" at line 48

test.cpp(16): error: this operator is not allowed in a template argument expression
    if ((info1.start < info2.end) && (info2.end > info1.end) && (info1.end < info2.start) )
                                                                                  ^
          detected during:
            instantiation of "void my_functor<Time>::operator()(const info_t &, const info_t &) [with Time=int, info_t=Info_t]" at line 313 of "/home/aniketnp/boost_1_55_0/boost/bind/bind.hpp"
            instantiation of "void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F &, A &, int) [with A1=boost::arg<1>, A2=boost::arg<2>, F=my_functor<int>, A=boost::_bi::list2<Info_t &, Info_t &>]" at line 61 of "/home/aniketnp/boost_1_55_0/boost/bind/bind_template.hpp"
            instantiation of "boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()(A1 &, A2 &) [with R=boost::_bi::unspecified, F=my_functor<int>, L=boost::_bi::list2<boost::arg<1>, boost::arg<2>>, A1=Info_t, A2=Info_t]" at line 48

test.cpp(16): error: expected a ">"
    if ((info1.start < info2.end) && (info2.end > info1.end) && (info1.end < info2.start) )
                                                                                        ^
          detected during:
            instantiation of "void my_functor<Time>::operator()(const info_t &, const info_t &) [with Time=int, info_t=Info_t]" at line 313 of "/home/aniketnp/boost_1_55_0/boost/bind/bind.hpp"
            instantiation of "void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F &, A &, int) [with A1=boost::arg<1>, A2=boost::arg<2>, F=my_functor<int>, A=boost::_bi::list2<Info_t &, Info_t &>]" at line 61 of "/home/aniketnp/boost_1_55_0/boost/bind/bind_template.hpp"
            instantiation of "boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()(A1 &, A2 &) [with R=boost::_bi::unspecified, F=my_functor<int>, L=boost::_bi::list2<boost::arg<1>, boost::arg<2>>, A1=Info_t, A2=Info_t]" at line 48

 

 

Now, if I compile it without  " -mmic " flag, then there is no compiler errors.

I compile with this : icpc -L/home/aniketnp/tbb42_20140122oss/lib/intel64/gcc4.4 -std=c++11 -I/home/aniketnp/boost_1_55_0 -I/home/aniketnp/tbb42_20140122oss/include test.cpp

I dont get any error. It compiles and runs fine.

 

Please help me figure out why is that. I understand the platforms are different. The mic version runs on the xeon phi card. while intel64 is for standard 8/12/16 core processors. Because of this there is no generic-ness left in my code. and I have to change my code every now and then.

11 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Is there a requirement for using such an old compiler?  I think that was from before the time when MIC went to market (even though the "official" advice on boost doesn't indicate any updates in 18 months).

The compilers in our clusters are not updated so I have only icc 13.0.1 compiler from intel. However, the above code compiles correctly for non-mic  compilation. I tried splitting the if()  loop as follows :

 if ((info2.start < info2.end) && (info2.end > info1.end) ) 
 {
     if ( info1.end < info2.start)
        //do something
  }

// error is propagated towards inner if  loop

test.cpp(17): error: expression must have a constant value
       if ( info1.end < info2.start) 
                        ^
          detected during:
            instantiation of "void my_functor<Time>::operator()(const info_t &, const info_t &) [with Time=int, info_t=Info_t]" at line 313 of "/home/aniketnp/boost_1_55_0/boost/bind/bind.hpp"
            instantiation of "void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F &, A &, int) [with A1=boost::arg<1>, A2=boost::arg<2>, F=my_functor<int>, A=boost::_bi::list2<Info_t &, Info_t &>]" at line 61 of "/home/aniketnp/boost_1_55_0/boost/bind/bind_template.hpp"
            instantiation of "boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()(A1 &, A2 &) [with R=boost::_bi::unspecified, F=my_functor<int>, L=boost::_bi::list2<boost::arg<1>, boost::arg<2>>, A1=Info_t, A2=Info_t]" at line 49

test.cpp(17): error: this operator is not allowed in a template argument expression
       if ( info1.end < info2.start) 
                             ^
          detected during:
            instantiation of "void my_functor<Time>::operator()(const info_t &, const info_t &) [with Time=int, info_t=Info_t]" at line 313 of "/home/aniketnp/boost_1_55_0/boost/bind/bind.hpp"
            instantiation of "void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F &, A &, int) [with A1=boost::arg<1>, A2=boost::arg<2>, F=my_functor<int>, A=boost::_bi::list2<Info_t &, Info_t &>]" at line 61 of "/home/aniketnp/boost_1_55_0/boost/bind/bind_template.hpp"
            instantiation of "boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()(A1 &, A2 &) [with R=boost::_bi::unspecified, F=my_functor<int>, L=boost::_bi::list2<boost::arg<1>, boost::arg<2>>, A1=Info_t, A2=Info_t]" at line 49

test.cpp(17): error: expected a ">"
       if ( info1.end < info2.start) 
                                   ^
          detected during:
            instantiation of "void my_functor<Time>::operator()(const info_t &, const info_t &) [with Time=int, info_t=Info_t]" at line 313 of "/home/aniketnp/boost_1_55_0/boost/bind/bind.hpp"
            instantiation of "void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F &, A &, int) [with A1=boost::arg<1>, A2=boost::arg<2>, F=my_functor<int>, A=boost::_bi::list2<Info_t &, Info_t &>]" at line 61 of "/home/aniketnp/boost_1_55_0/boost/bind/bind_template.hpp"
            instantiation of "boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()(A1 &, A2 &) [with R=boost::_bi::unspecified, F=my_functor<int>, L=boost::_bi::list2<boost::arg<1>, boost::arg<2>>, A1=Info_t, A2=Info_t]" at line 49

compilation aborted for test.cpp (code 2)

 

I tried with intel composer xe 2013 update 3 (sp1) ( trial version as well). It gives me the same error. When I try this, it gives me no error.

 

template <typename T, typename Time>
void process_info(const T info1, const T info2, const Time& t)  {

   const auto& i1s = info1.start;
   const auto& i2s = info2.start;
   const auto& i1e = info1.end;
   const auto& i2e = info2.end;

   if ((i2s < i2e) && (i2e > i1s) ) {
     if ( i1e < i2s)
       std::cout << "no error" << std::endl;
  }

 

I reproduced the error but I do not know why it fails with -mmic so I have submitted this to Development (see internal tracking id below) for further analysis. I will post another reply when I learn more.

(Internal tracking id: DPD200358195)

Hi Kevin, It looks like a possible compiler bug. I have asked this in the below topic. It may be because the compiler asks for a  " > " as it treats it as member template. if you compile without  " -mmic " flag, it works okay. 

https://software.intel.com/en-us/forums/topic/517626

Kindly confirm. 

Aniket

Yes, I reproduced the error using the Composer XE 2013 SP1 Update 3 and a newer Beta (15.0) compiler and forwarded it to Development for further investigation as indicated. I will let you know what I hear.

Hi Aniket,

Development replied that this is not a compiler defect and noted that GNU gives the same error. They did not (yet) provide an explanation why only the -mmic compilation suffers errors. In their explanation they wrote:

<quote>

The problem can be shown here:

// from <initializer_list> header file
namespace std
{
  template<class _E> class initializer_list {};

  template<class _Tp>
    constexpr const _Tp*
    end(initializer_list<_Tp> __ils) noexcept;
}

using namespace std;

struct Info_t {
 int start;
 int end;
};

template <typename T>
void process_info(const T& info1, const T& info2) {
  if (info1.end < info2.start) ;
//  if ((info1.start < info2.end) && (info2.end > info1.end)) ;
}

int main() {
 Info_t i1, i2;
 process_info(i1,i2);
 return 0;
}

The name "end" is being brought in via the using declaration from the std namespace.
Since std::end is a template the compiler and info1 is dependent name it thinks "end <" is the start of a call to std::end (note that std::end is a template so having the start of a template argument list be the token < instead of less than makes sense) -- hence the error.

Suggested workaround:
(1) Change the name "end" inside Info_t to some other name so it doesn't conflict with std::end
(2) Fix the code to put parenthesis in to prevent the parser from thinking that end is a template name, i.e.:

#ifdef OK
  if ((info1.start < info2.end) && (info2.end > info1.end) && ((info1.end) < info2.start) )
#else
  if ((info1.start < info2.end) && (info2.end > info1.end) && (info1.end < info2.start) )
#endif

<end quote>

I will let you know the explanation for why the host compilation did not throw similar errors once I hear from them about that.

Thanks for the update Kevin. I have used a workaround by changing the " > " sign in the if() logic. This compiles ok for mic and non-mic versions as well so that i have consistency in my code.

I compile my generic code using gcc4.7.2 / gcc 4.9 / intel 13.0 / intel 14.0 (trial) compilers. I use intel compilers to compile for mic. 

I also use Intel TBB in my codes. Is there any specific difference between standalone TBB release and TBB provided in intel suite ?

Also Is it possible to compile a simple test code (containing TBB threads) for  intel mic  using GCC ?,

I read this post here (  https://software.intel.com/en-us/blogs/2012/06/05/knights-corner-open-so...  )  which mention low performance if compiled with gcc. But it is still possible right?

The final 13.1 and 14.0 compilers are fairly reliable (aside from a few bugs such as you happened upon here), but there were more problems in earlier versions.

I haven't heard of anyone checking whether TBB can be built using the MIC gcc.  As the URL you quoted mentions, it doesn't support any KNC vector instructions.  There is avx-512f in current gcc, but nothing to run it on yet except the SDE simulator, so it seems no one signed up to improve support of gcc on KNC.

To close on the original issue, Development indicates compilation can succeed on the host (as both of us observed) when using a version of the standard library before the c++11 std::initializer_list class was added or a version of <iostream.h> that does not automatically include <initializer_list>.  The initializer_list class existed in GNU 4.4 and 4.5 but it was not until GNU 4.6 that the std::begin() and std::end() functions were added. My host system has GNU 4.4.6.

Standalone versions of TBB (and performance libs too) and those bundled in the Intel suite are the same where version numbers match.

I cannot speak to building code using TBB with the MIC GCC since I do not have any knowledge/experience with that either, sorry.

Leave a Comment

Please sign in to add a comment. Not a member? Join today