Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Alexander_N_1
Beginner
42 Views

Problems with using parallel_do

Hello. I've got next problem with using parallel_do: it even fails to compile if i pass std::bind result:

In file included from D:\Projects\MyProject\src\server.cpp:4:0:

D:/libs/tbb43_20150209/include/tbb/parallel_do.h: In instantiation of 'void tbb::parallel_do(Iterator, Iterator, const Body&) [with Iterator = long long unsigned int; Body = std::_Bind<void (*(std::_Placeholder<1>))(int&)>]':

D:/libs/tbb43_20150209/include/tbb/parallel_do.h:492:74: required from 'void tbb::parallel_do(const Range&, const Body&) [with Range = tbb::blocked_range<long long unsigned int>; Body = std::_Bind<void (*(std::_Placeholder<1>))(int&)>]'

D:\Projects\MyProject\src\server.cpp:50:71: required from here

D:/libs/tbb43_20150209/include/tbb/parallel_do.h:482:9: error: no matching function for call to 'select_parallel_do(long long unsigned int&, long long unsigned int&, const std::_Bind<void (*(std::_Placeholder<1>))(int&)>&, <unresolved overloaded function type>, tbb::task_group_context&)'

);

^

D:/libs/tbb43_20150209/include/tbb/parallel_do.h:482:9: note: candidates are:

D:/libs/tbb43_20150209/include/tbb/parallel_do.h:412:10: note: template<class Iterator, class Body, class Item> void tbb::internal::select_parallel_do(Iterator, Iterator, const Body&, void (Body::*)(Item) const, tbb::task_group_context&)

void select_parallel_do( Iterator first, Iterator last, const Body& body, void (Body::*)(Item) const

^

D:/libs/tbb43_20150209/include/tbb/parallel_do.h:412:10: note: template argument deduction/substitution failed:

D:/libs/tbb43_20150209/include/tbb/parallel_do.h:482:9: note: couldn't deduce template parameter 'Item'

);

^

D:/libs/tbb43_20150209/include/tbb/parallel_do.h:429:10: note: template<class Iterator, class Body, class Item, class _Item> void tbb::internal::select_parallel_do(Iterator, Iterator, const Body&, void (Body::*)(Item, tbb::parallel_do_feeder<_Item>&) const, tbb::task_group_context&)

void select_parallel_do( Iterator first, Iterator last, const Body& body, void (Body::*)(Item, parallel_do_feeder<_Item>&) const

^

D:/libs/tbb43_20150209/include/tbb/parallel_do.h:429:10: note: template argument deduction/substitution failed:

D:/libs/tbb43_20150209/include/tbb/parallel_do.h:482:9: note: couldn't deduce template parameter 'Item'

);

That's what my code do:

void print_item(int32_t& value) {
    //I know using iostreams like that is not thread safe i was just testing
    std::cout  << "value: " << value << std::endl;
}

int main(int argc, char** argv) {
    std::vector<int32_t> test;
    for(int i = 1; i <= 100; ++i) {
        test.push_back(i);
    }
    auto print_value = std::bind(&print_item,std::placeholders::_1); //this have special type _Bind
    std::function<void(int32_t&)> print_value_function = std::bind(&print_item,std::placeholders::_1); //this have special type _Bind
    tbb::parallel_do(test,print_value); //fails to compile
    tbb::parallel_do(test,print_value_function ); //compiles fine
}

Of course i can wrap those into std::function but that would add unnesessary overhead. Also i've found a problem in code using automatic argument type deduction in this code(and also in another places where it used):

    //! For internal use only.
    /** Detects types of Body's operator function arguments.
        @ingroup algorithms **/
    template<typename Iterator, typename Body, typename Item>
    void select_parallel_do( Iterator first, Iterator last, const Body& body, void (Body::*)(Item) const
#if __TBB_TASK_GROUP_CONTEXT
        , task_group_context& context 
#endif // __TBB_TASK_GROUP_CONTEXT 
        )
    {
        run_parallel_do<Iterator, Body, typename strip<Item>::type>( first, last, body
#if __TBB_TASK_GROUP_CONTEXT
            , context
#endif // __TBB_TASK_GROUP_CONTEXT 
            );
    }

    //! For internal use only.
    /** Detects types of Body's operator function arguments.
        @ingroup algorithms **/
    template<typename Iterator, typename Body, typename Item, typename _Item>
    void select_parallel_do( Iterator first, Iterator last, const Body& body, void (Body::*)(Item, parallel_do_feeder<_Item>&) const
#if __TBB_TASK_GROUP_CONTEXT
        , task_group_context& context 
#endif // __TBB_TASK_GROUP_CONTEXT
        )
    {
        run_parallel_do<Iterator, Body, typename strip<Item>::type>( first, last, body
#if __TBB_TASK_GROUP_CONTEXT
            , context
#endif // __TBB_TASK_GROUP_CONTEXT
            );
    }

I tried to use functional object where operator() is inherited from base class and Body type is different so that code fails to compile

0 Kudos
1 Reply
RafSchietekat
Black Belt
42 Views

What overhead are you concerned about: performance-wise (presumed or measured?) or just syntactical? For the latter, it's probably doable (no pun intended) to use std::is_bind_expression to differentiate and std::function (from what you've found) to pick up operator(), and then maybe something more efficient if still desirable, but I haven't tried anything yet.

Did you use the keyword "override" for the overridden operator()? It might have alerted you about declaring the operator as "const". Only the "const" is required, though.

Reply