|
Boost : |
Subject: Re: [boost] [threadpool] version 22 with default pool
From: Edouard A. (edouard_at_[hidden])
Date: 2009-03-08 14:48:11
I have implemented a parallel_sort that is a bit slower than tbb with
threadpool (see below for the code).
Benchmark results:
std::fill 0..1000000 ok : 1 elapsed: 0.01
tbb::parallel_for fill 0..1000000 ok : 1 elapsed: 0.01
std::sort reverse 0..1000000 ok : 1 elapsed: 0.11
tbb::parallel_sort reverse 0..1000000 ok : 1 elapsed: 0.037
boost::tp::sort reverse 0..1000000 ok : 1 elapsed: 0.048
Machine: Q6600 - 4 GiB Ram - Running Vista 64 - x64 release build with full
optimizations.
Some remarks:
* shutdown() renders the thread pool unusable (marks it terminated). This
is not what I was looking for. Ideally, a wait() method that just waits for
the pool to have no tasks left to process would be better. I would find it
cumbersome to manually wait for the result of each task. My 2c.
* It's difficult to properly benchmark the two on my development machine
that is probably using one core to do things background work
* Instrumentation seems to show that the _entry method of the pool is
extremely slow. I have not investigated further.
* boost::tp::sort benchmark includes thread destruction... Probably eats up
some micro secs
* My code is probably sub-optimal
The code:
template <typename RandomIterator>
RandomIterator pivot_partition(RandomIterator first, RandomIterator last)
{
typedef RandomIterator iterator_type;
typedef typename iterator_type::difference_type difference_type;
typedef typename iterator_type::value_type value_type;
iterator_type pivot = first + std::distance(first, last) / 2;
// we partition
value_type pivot_value = *pivot;
// we "save" the pivot in putting it to the first place
std::iter_swap(first, pivot);
// we skip the pivot otherwise the partitioning won't work as
expected
iterator_type par_start = first + 1;
std::less<value_type> pred;
pivot = std::partition(par_start, last, std::bind2nd(pred,
pivot_value));
// we restore the pivot
std::iter_swap(--pivot, first);
return pivot;
}
template <typename RandomIterator, typename Pool>
void rec_pivot_partition(RandomIterator first, RandomIterator last, Pool &
p)
{
if (std::distance(first, last) > 1000)
{
RandomIterator pivot = pivot_partition(first, last);
rec_pivot_partition(first, pivot, p);
rec_pivot_partition(pivot, last, p);
}
else
{
p.submit(boost::bind(&std::sort<iterator_type>, first,
last));
}
};
template <typename RandomIterator>
void parallel_tp(RandomIterator first, RandomIterator last)
{
typedef RandomIterator iterator_type;
typedef typename iterator_type::difference_type difference_type;
typedef typename iterator_type::value_type value_type;
difference_type n = std::distance(first, last);
RandomIterator l = first;
const difference_type block_size = 1000;
// we partition until we have "atoms", ie block of size < block_size
boost::tp::default_pool & p = boost::tp::get_default_pool();
rec_pivot_partition(first, last, p);
p.shutdown();
}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk