Boost logo

Boost :

Subject: Re: [boost] [parallel_sort] Proposal
From: vicente.botet (vicente.botet_at_[hidden])
Date: 2009-02-02 17:49:51


Hi,

----- Original Message -----
From: "Edouard A." <edouard_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Monday, February 02, 2009 7:21 PM
Subject: Re: [boost] [parallel_sort] Proposal

> On Mon, 02 Feb 2009 17:41:58 +0000, "Phil Endecott"
> <spam_from_boost_dev_at_[hidden]> wrote:
>
>> So basically it's something like this:
>>
>> thread t( sort(begin,mid) );
>> sort(mid,end);
>> t.join();
>> merge(begin,mid,end); // [*]
>
> Exactly, with some differences as I do a memory copy before the thread and
> I run two threads.
>
> Working on different buffers allows to prevent hidden system locks when
> you reach the middle.

Please could you be more precise, which kind of hidden system locks?
 
> so it's more like
>
> buffer = new [];
> copy(...)
> thread t1(sort(buffer,...);
>
> buffer2 = new [];
> copy(...)
> thread t2(sort(buffer2, ...);
>
> t2.join();
> t1.join();
>
> merge(buffer, buffer2, result);

The second thread is not realy useful, as noted by Phil.

I would like to be able to write something more generic, something like:

template <
    typename DirectSolver,
    typename Composer,
    typename AsynchronousExecutor,
    typename Input>
void inplace_solve(AsynchronousExecutor& ae, Problem& input) {
  // if (problem is small)
    if (size(range) < concurrency_threshold) {
    // directly solve problem
        DirectSolver()(input);
    } else {
        // split problem into independent parts
        BOOST_AUTO(partition, partition_view(input));
        // evaluates asynchronously inplace_solve on each element of the partition
        // using the asynchronous executor as scheduler
        wait_for_all(ae, inplace_solve, partition);
        // compose the result in place from subresults
        Composer()(partition);
    }
}

So parallel sort could be

template <typename Range>
void parallel_sort(range& range) {
    boost::tp::pool<> ae;
    parallel::inplace_solve<sort, merge>(ae, input);
}

I'm working on a Asynchronous Execution framework that you can get from http://www.boostpro.com/vault/index.php?action=downloadfile&filename=interthreads.zip&directory=Concurrent%20Programming&. It provides a wait_for_all function which will fork each function except the last one which will be executed in the current thread. So if you make 4 partitions you need to use it as

        wait_for_all(ae, bind(inplace_solve, at_c<0>(partition)),
                                    bind(inplace_solve, at_c<1>(partition)),
                                    bind(inplace_solve, at_c<2>(partition)),
                                    bind(inplace_solve, at_c<3>(partition)),
        );

I'll try to implement this overloading.

    template< typename AE, typename F, typename Sequence>
    typename result_of::wait_for_all<AE, F,Sequence >::type
    wait_for_all( AE& ae, F f, Sequence seq );

HTH,
Vicente


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk