Boost logo

Boost Users :

Subject: Re: [Boost-users] [mapreduce] Prim Calculator
From: Christian Henning (chhenning_at_[hidden])
Date: 2009-08-21 16:32:19


Where in the sandbox is mapreduce? Thanks for all your comments! I'll
get back to you once I can run the prime calculator.

On Fri, Aug 21, 2009 at 3:52 PM, Craig
Henderson<cdm.henderson_at_[hidden]> wrote:
>> -----Original Message-----
>> From: boost-users-bounces_at_[hidden] [mailto:boost-users-
>> bounces_at_[hidden]] On Behalf Of Christian Henning
>> Sent: 21 August 2009 15:05
>> To: boost-users_at_[hidden]
>> Subject: Re: [Boost-users] [mapreduce] Prim Calculator
>>
>> Hi Craig, what you're suggesting is exactly what I do. For reasons I
>> don't understand I'm getting the following assertion:
>>
>> Running Parallel Prime_Calculator MapReduce...Assertion failed:
>> map_key != typename map_task_type::key_type(), file
>> c:\chh\boost\boost\mapreduce\job.hpp, line 210
>>
>> I don't understand why that happens? Can you help me out here.
>>
>
> Hi Christian
> The assertion is an incorrect error condition which meant that the key could
> not be a default constructed valued (in the case of your numeric key, zero).
> I have updated the sandbox - thanks for finding this. Get the latest version
> of job.hpp & in_memory.hpp from the sandbox.
>
> There are a couple other problems in your implementation, too.
> * number_source constructor should initialize _current to be start, not
> zero.
> * using a global to hold prime_numbers isn't thread-safe, and adding locking
> will introduce contention. The MapReduce library provides mechanisms to
> avoid this. In reduce_task::reduce, replace the line
>    copy( it, ite, back_inserter( prime_numbers ));
> with
>    for_each(it, ite, boost::bind(&Runtime::emit, &runtime, _1, 0));
> which will emit the final results.
>
> To display the results:
>    for (prime_calculator::job::const_result_iterator
> it=job.begin_results(); it!=job.end_results(); ++it)
>        std::cout << it->first << " ";
>
> For performance, the datasource should return a range of integers so each
> task tests many prime numbers rather than one at a time. This will reduce
> lock contention in retrieving map keys.
>
> Finally, 0 & 1 are not prime numbers - this is a bug in your is_prime
> function.
>
> Regards
> -- Craig
>
> #include <algorithm>
> #include <cmath>
> #include <numeric>
>
> #include <boost/mapreduce.hpp>
>
> namespace prime_calculator
> {
>
> std::size_t is_prime( std::size_t number ) {
>    long n = static_cast<long>( number );
>
>    if( number == 0 )
>        return 1;
>
>    n = std::abs( n );
>    std::size_t sqrt_number = static_cast< std::size_t >( std::sqrt(
> static_cast< double >( n )));
>
>    for( std::size_t i = 2; i <= sqrt_number; i++ )
>    {
>        if( n % i == 0 )
>            return 0;
>    }
>
>    return 1;
> }
>
> template< typename MapTask >
> class number_source : boost::noncopyable {
> public:
>
>    number_source( std::size_t start
>                 , std::size_t end
>                 )
>    : _start( start )
>    , _end  ( end   )
>    , _current( start )     // CH
>    {}
>
>    const bool setup_key( typename MapTask::key_type& key ) const
>    {
>        if( _current < _end )
>        {
>            key = _current;
>            return true;
>        }
>        else
>        {
>            return false;
>        }
>    }
>
>    const bool get_data( typename MapTask::key_type&   key
>                       , typename MapTask::value_type& value
>                       )
>    {
>        if( _current < _end )
>        {
>            value.first  = _current;
>            value.second = _current;
>            _current++;
>
>            return true;
>        }
>        else
>        {
>            return false;
>        }
>    }
>
> private:
>
>    std::size_t _start;
>    std::size_t _end;
>    std::size_t _current;
> };
>
> struct map_task : public boost::mapreduce::map_task< std::size_t
>     // MapKey
>                                                   , std::pair< std::size_t
>                                                              , std::size_t
>                                                              >
>     // MapValue
>                                                   > {
>    template<typename Runtime>
>    static void map( Runtime& runtime
>                   , const std::size_t& /*key*/
>                   , value_type&        value
>                   )
>    {
>        runtime.emit_intermediate( is_prime( value.first ), value.first );
>    }
> };
>
> //std::vector< std::size_t > prime_numbers;     // CH
>
> struct reduce_task : public boost::mapreduce::reduce_task< std::size_t
>                                                         , unsigned
>                                                         > {
>    template< typename Runtime
>            , typename It
>            >
>    static void reduce( Runtime&           runtime
>                      , const std::size_t& key
>                      , It                 it
>                      , const It           ite
>                      )
>    {
>        if( key > 0 )
>        {
> //            copy( it, ite, back_inserter( prime_numbers ));       // CH
>            for_each(it, ite, boost::bind(&Runtime::emit, &runtime, _1, 0));
> // CH
>        }
>    }
> };
>
> typedef
> boost::mapreduce::job< prime_calculator::map_task
>                     , prime_calculator::reduce_task
>                     , boost::mapreduce::null_combiner
>                     , prime_calculator::number_source<
> prime_calculator::map_task >
>> job;
>
> } // namespace prime_calculator
>
> int main(int argc, char* argv[])
> {
>    boost::mapreduce::specification spec;
>
>    boost::mapreduce::results result;
>    prime_calculator::job::datasource_type datasource( 0, 1000 );
>
>    spec.map_tasks    = 0;
>    spec.reduce_tasks = std::max( 1U, boost::thread::hardware_concurrency()
> );
>
>    std::cout << "\nRunning Parallel Prime_Calculator MapReduce...";
>    prime_calculator::job job( datasource, spec );
>    job.run<
> boost::mapreduce::schedule_policy::cpu_parallel<prime_calculator::job> >(
> result );
>    std::cout << "\nMapReduce Finished.";
>
>    for (prime_calculator::job::const_result_iterator
> it=job.begin_results(); it!=job.end_results(); ++it)
>        std::cout << it->first << " ";
>
>        return 0;
> }
>
>
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net