Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Re: Product of a list of numbers?

by Popcorn Dave (Abbot)
on Jan 23, 2004 at 05:59 UTC ( [id://323459]=note: print w/replies, xml ) Need Help??


in reply to Product of a list of numbers?

Just out of curiosity, is there a speed issue when using map or would it really depend on the size of the array being mapped over?

Given:

use strict; my @list = (1,2,3,4,5); my $result = 1; map {$result *= $_} @list; print $result;

I realize that TIMTOWTDI, but is this a good place to use map, is the loop preferable, or are they about the same?

There is no emoticon for what I'm feeling now.

Replies are listed 'Best First'.
Re: Re: Product of a list of numbers?
by Roger (Parson) on Jan 23, 2004 at 06:07 UTC
    Why don't you Benchmark it?

    Updated: Added my own Benchmark result.

    use strict; use Benchmark qw/ cmpthese timethese /; use List::Util qw/ reduce /; my @list = 1..10; cmpthese( timethese(1000000, { 'map_void' => '&map_void', 'for_loop' => '&for_loop', 'list_reduce' => '&list_reduce', })); # printf "%d, %d, %d\n", map_void(), for_loop(), list_reduce(); sub map_void { my $result = 1; map {$result *= $_} @list; return $result; } sub for_loop { my $result = 1; $result *= $_ foreach @list; return $result; } sub list_reduce { return reduce { $a * $b } @list; } __END__ Benchmark: timing 1000000 iterations of for_loop, list_reduce, map_voi +d... for_loop: 4 wallclock secs ( 5.43 usr + 0.00 sys = 5.43 CPU) @ 18 +4229.92/s (n=1000000) list_reduce: 9 wallclock secs ( 8.46 usr + 0.00 sys = 8.46 CPU) @ 1 +18175.37/s (n=1000000) map_void: 5 wallclock secs ( 4.52 usr + 0.00 sys = 4.52 CPU) @ 22 +1385.88/s (n=1000000) Rate list_reduce for_loop map_void list_reduce 118175/s -- -36% -47% for_loop 184230/s 56% -- -17% map_void 221386/s 87% 20% --

      Ok....

      use strict; use warnings; use Benchmark; my @list = ( 1 .. 500 ); my $count = 25000; timethese ( $count, { 'Map' => sub { my $result = 1; map { $result *= $_ } @list; }, 'For' => sub { my $result = 1; $result *= $_ for @list; } } ); __OUTPUT__ Benchmark: timing 25000 iterations of For, Map... For: 11 wallclock secs (10.62 usr + 0.00 sys = 10.62 CPU) @ 2355.16/s + (n=25000) Map: 11 wallclock secs (11.18 usr + 0.00 sys = 11.18 CPU) @ 2236.94/s + (n=25000)

      The moral... There's no way to perform a mathematical operation based on the value of each element of a list of arbitrary values, without looking at each element of the list. And that implies (and requires) some from of iteration. map and for seem to be pretty close to each other in terms of efficiency in iterating over the list.

      On the other hand, if the list consists of a known sequence, it is possible to break out the math-fu to derive a non-iterative solution. Brute force is necessary in the absence of a known mathematical sequence though.


      Dave

      I'm quite surprised by your results. It shows the reduce version to be the slowests, and it suggests that using a map with a block is faster than a for statement modifier. The former needs to enter/leave a block for each iteration, and the latter doesn't. A benchmark on my box shows different results:
      #!/usr/bin/perl use strict; use warnings; use Benchmark qw /cmpthese timethese/; use List::Util qw /reduce/; our @list = 1 .. 50; our ($map_b, $map_e, $for_m, $for_b, $red, $bc, $eval); print "Perl version: $].\n"; system "cat /proc/version"; cmpthese -10 => { map_block => '$::map_b = 1; map {$::map_b *= $_} @::list', map_expr => '$::map_e = 1; map $::map_e *= $_, @::list', for_mod => '$::for_m = 1; $::for_m *= $_ for @::list', for_block => '$::for_b = 1; foreach (@::list) {$::for_b *= $_}', reduce => '$::red = reduce {$a * $b} @::list', bc => q !local $" = "*"; $::bc = `echo '@::list' | bc`!, eval => '$::eval = eval join "*" => @::list', }; print "Map block: $map_b\n"; print "Map expres: $map_e\n"; print "For modifier: $for_m\n"; print "For block: $for_b\n"; print "Reduce: $red\n"; print "bc: $bc\n"; print "Eval: $eval\n"; __END__ Perl version: 5.008003. Linux version 2.4.18-3 (bhcompile@daffy.perf.redhat.com) (gcc version +2.96 20000731 (Red Hat Linux 7.3 2.96-110)) #1 Thu Apr 18 07:37:53 ED +T 2002 Rate bc eval map_block for_block map_expr for_m +od reduce bc 2779/s -- -55% -88% -94% -95% -9 +5% -95% eval 6199/s 123% -- -73% -87% -88% -8 +8% -89% map_block 22904/s 724% 269% -- -53% -55% -5 +7% -60% for_block 49041/s 1664% 691% 114% -- -3% - +9% -13% map_expr 50669/s 1723% 717% 121% 3% -- - +6% -11% for_mod 53638/s 1830% 765% 134% 9% 6% +-- -5% reduce 56651/s 1938% 814% 147% 16% 12% +6% -- Map block: 3.0414093201713378e+64 Map expres: 3.0414093201713378e+64 For modifier: 3.0414093201713378e+64 For block: 3.0414093201713378e+64 Reduce: 3.0414093201713378e+64 bc: 30414093201713378043612608166064768844377641568960512000 +000000000 Eval: 3.0414093201713378e+64

      Abigail

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://323459]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (7)
As of 2024-04-24 06:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found