Bug 33488 - parallel v3: std::accumulate uses accumulator of wrong type
Summary: parallel v3: std::accumulate uses accumulator of wrong type
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 4.3.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2007-09-19 02:42 UTC by Wolfgang Bangerth
Modified: 2007-10-10 01:13 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2007-09-19 17:06:52


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Wolfgang Bangerth 2007-09-19 02:42:33 UTC
This little program
----------------------
#include <numeric>
void f () {
  bool *p, *q;
  std::accumulate (p, q, 0U);
}
----------------------
counts the 'true's in the range [p,q) but this doesn't work in parallel mode, 
the compiler says that it can't resolve a function call. It should as per 
26.4.1.

In particular, the error message is this:

4.3.0/parallel/par_loop.h: In function 'Op __gnu_parallel::for_each_template_random_access_ed(RandomAccessIterator, RandomAccessIterator, Op, Fu&, Red, Result, Result&, typename std::iterator_traits<_Iterator>::difference_type) [with RandomAccessIterator = bool*, Op = __gnu_parallel::nothing, Fu = __gnu_parallel::accumulate_selector<bool*>, Red = __gnu_parallel::accumulate_binop_reduct<std::plus<bool> >, Result = unsigned int]':
4.3.0/parallel/for_each.h:73:   instantiated from 'UserOp __gnu_parallel::for_each_template_random_access(InputIterator, InputIterator, UserOp, Functionality&, Red, Result, Result&, typename std::iterator_traits<_Iterator>::difference_type, __gnu_parallel::parallelism) [with InputIterator = bool*, UserOp = __gnu_parallel::nothing, Functionality = __gnu_parallel::accumulate_selector<bool*>, Red = __gnu_parallel::accumulate_binop_reduct<std::plus<bool> >, Result = unsigned int]'
4.3.0/parallel/numeric:103:   instantiated from 'T std::__parallel::accumulate_switch(_RAIter, _RAIter, T, _BinaryOper, std::random_access_iterator_tag, __gnu_parallel::parallelism) [with _RAIter = bool*, T = unsigned int, _BinaryOper = std::plus<bool>]'
4.3.0/parallel/numeric:83:   instantiated from 'T std::__parallel::accumulate(_IIter, _IIter, T, __gnu_parallel::parallelism) [with _IIter = bool*, T = unsigned int]'
x.cc:4:   instantiated from here
4.3.0/parallel/par_loop.h:103: error: no match for call to '(__gnu_parallel::accumulate_binop_reduct<std::plus<bool> >) (unsigned int&, bool)'
4.3.0/parallel/omp_loop.h: In function 'Op __gnu_parallel::for_each_template_random_access_omp_loop(RandomAccessIterator, RandomAccessIterator, Op, Fu&, Red, Result, Result&, typename std::iterator_traits<_Iterator>::difference_type) [with RandomAccessIterator = bool*, Op = __gnu_parallel::nothing, Fu = __gnu_parallel::accumulate_selector<bool*>, Red = __gnu_parallel::accumulate_binop_reduct<std::plus<bool> >, Result = unsigned int]':
4.3.0/parallel/for_each.h:75:   instantiated from 'UserOp __gnu_parallel::for_each_template_random_access(InputIterator, InputIterator, UserOp, Functionality&, Red, Result, Result&, typename std::iterator_traits<_Iterator>::difference_type, __gnu_parallel::parallelism) [with InputIterator = bool*, UserOp = __gnu_parallel::nothing, Functionality = __gnu_parallel::accumulate_selector<bool*>, Red = __gnu_parallel::accumulate_binop_reduct<std::plus<bool> >, Result = unsigned int]'
4.3.0/parallel/numeric:103:   instantiated from 'T std::__parallel::accumulate_switch(_RAIter, _RAIter, T, _BinaryOper, std::random_access_iterator_tag, __gnu_parallel::parallelism) [with _RAIter = bool*, T = unsigned int, _BinaryOper = std::plus<bool>]'
4.3.0/parallel/numeric:83:   instantiated from 'T std::__parallel::accumulate(_IIter, _IIter, T, __gnu_parallel::parallelism) [with _IIter = bool*, T = unsigned int]'
x.cc:4:   instantiated from here
4.3.0/parallel/omp_loop.h:78: error: no match for call to '(__gnu_parallel::accumulate_binop_reduct<std::plus<bool> >) (unsigned int&, bool)'
4.3.0/parallel/omp_loop.h:86: error: no match for call to '(__gnu_parallel::accumulate_binop_reduct<std::plus<bool> >) (unsigned int&, bool)'
4.3.0/parallel/workstealing.h: In function 'Op __gnu_parallel::for_each_template_random_access_workstealing(RandomAccessIterator, RandomAccessIterator, Op, Fu&, Red, Result, Result&, typename std::iterator_traits<_Iterator>::difference_type) [with RandomAccessIterator = bool*, Op = __gnu_parallel::nothing, Fu = __gnu_parallel::accumulate_selector<bool*>, Red = __gnu_parallel::accumulate_binop_reduct<std::plus<bool> >, Result = unsigned int]':
4.3.0/parallel/for_each.h:79:   instantiated from 'UserOp __gnu_parallel::for_each_template_random_access(InputIterator, InputIterator, UserOp, Functionality&, Red, Result, Result&, typename std::iterator_traits<_Iterator>::difference_type, __gnu_parallel::parallelism) [with InputIterator = bool*, UserOp = __gnu_parallel::nothing, Functionality = __gnu_parallel::accumulate_selector<bool*>, Red = __gnu_parallel::accumulate_binop_reduct<std::plus<bool> >, Result = unsigned int]'
4.3.0/parallel/numeric:103:   instantiated from 'T std::__parallel::accumulate_switch(_RAIter, _RAIter, T, _BinaryOper, std::random_access_iterator_tag, __gnu_parallel::parallelism) [with _RAIter = bool*, T = unsigned int, _BinaryOper = std::plus<bool>]'
4.3.0/parallel/numeric:83:   instantiated from 'T std::__parallel::accumulate(_IIter, _IIter, T, __gnu_parallel::parallelism) [with _IIter = bool*, T = unsigned int]'
x.cc:4:   instantiated from here
4.3.0/parallel/workstealing.h:204: error: no match for call to '(__gnu_parallel::accumulate_binop_reduct<std::plus<bool> >) (unsigned int&, bool)'


While 26.4.1 doesn't spell this out explicitly, one can only deduce that
what is mean is that the accumulator variable has the same type as
the initializer, which in the example is 'unsigned int'. Consequently,
the function should do something like
  while (p!=q)
    acc += *p++;
in which case the rhs is converted to int. The current implementation
attempts to use an accumulator of type 'bool'.

W.
Comment 1 Johannes Singler 2007-09-19 18:34:46 UTC
Instead of std::plus, a functor should be used that accepts two different types for LHS and RHS, Result and std::iterator_traits<RandomAccessIterator>::value_type, respectively.
Comment 2 Wolfgang Bangerth 2007-09-19 19:04:29 UTC
As I've said in the other report, I believe you shouldn't rely on the
existence of iterator_traits for the iterator type. You should use the
return type of dereferencing the iterator.

W.
Comment 3 Benjamin Kosnik 2007-10-09 20:52:45 UTC
Wolfgang, I think some of this is fixed, and for the rest (comment #2), there is another bug report (33490) that is focused just on that.

Is my understanding correct?

-benjamin
Comment 4 Wolfgang Bangerth 2007-10-10 01:12:53 UTC
(In reply to comment #3)
> Wolfgang, I think some of this is fixed, and for the rest (comment #2), there
> is another bug report (33490) that is focused just on that.
> 
> Is my understanding correct?

I believe so. In any case, by adding a few std:: to my call (which works
around PR 33486) I can now build my code. I'll see if it also works...

Thanks for your prompt work on all this!

Best
 W.
Comment 5 Wolfgang Bangerth 2007-10-10 01:13:28 UTC
I meant to close this one, as it appears fixed.