Chinaunix首页 | 论坛 | 博客
  • 博客访问: 467731
  • 博文数量: 143
  • 博客积分: 6159
  • 博客等级: 准将
  • 技术积分: 1667
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-25 23:08
文章分类

全部博文(143)

文章存档

2013年(1)

2012年(11)

2011年(55)

2010年(76)

分类:

2010-11-27 10:33:59

第四课:parallel_reduce

前面的paralle_for只对单个element进行操作,是最容易进行并行化的问题,大多数问题并不是这样,比如要把所有的数加在一起:) 这个就是parallel_reduce发力的地方了。最简单的函数如下:

int serial_sum_foo (int a[], int n)
{
    int sum = 0;
    for (int i = 0; i < n; ++i) {
        sum += foo(a[i]);
    }
    return sum;
}


用parallel_reduce实现如下:

    SumFoo sf(a);
    parallel_reduce(blocked_size<size_t>(0, n), sf);
    return sf.sum_;


class SumFoo
{
    int *a_;
public:
    int sum_;
    void operator() (blocked_range& r) {
        int sum = sum_;        /* explicit internal */
        for (int i = r.begin(); i != r.end(); ++i) {
            sum += foo(a[i]);
        }
        sum_ = sum;
    }
    void join (const SumFoo& x) { sum_ += x.sum_; }

    SumFoo(SumFoo& x, split) : a_(x.a_), sum_(0) {}
    SumFoo(int a[]) : a_(a), sum_(0) {}
};


从上面可以看出parallel_reduce的functor比parallel_for多了一个join()。reduce是采用了split-join的方式,类似quick-sort首先将一个range split为两部分,然后递归处理,第一部分处理完成后等待第二部分的join,即x.join(y),最后return x;当然实际的情况比这个复杂,并不能保证一个SumFoo只完成一个range,由于可以临时无法创建worker,同一个SumFoo对多个split后的range作Operator(). 但是join的顺序是可以保证的,也就是对于strcat以上的paralle_reduce也是可以work的。

parallel_reduce的定义如下:

template<typename Range, typename Body>
void parallel_reduce(const Range& range, Body& body,
                     const auto_partitioner& partitioner)


阅读(829) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~