Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Re: Summing Up Array Elements By Group

by ivancho (Hermit)
on Jan 21, 2009 at 07:30 UTC ( [id://737764]=note: print w/replies, xml ) Need Help??


in reply to Summing Up Array Elements By Group

Is
$output[int($_/3)] += $arr[$_] for 0..@arr-1;
efficient enough, or is there something I am missing? Too many "int()"s? My guess is that
my $k = @arr / 3; for (0..$k) { $output[$_] += $arr[3*$_] + $arr[3*$_+1] + $arr[3*$_ +2]; }
is about as efficient as you'd get.
Edit
Actually, it seems to me that
my $k = @arr / 3; my $b = 0; for (0..$k) { $output[$_] = $arr[$b] + $arr[$b+1] + $arr[$b +2]; $b += 3; }
is probably a tad faster. Although if your problem really is as big as to make a difference between those 2 versions, then you shouldn't really be using Perl.

Replies are listed 'Best First'.
Re^2: Summing Up Array Elements By Group
by ikegami (Patriarch) on Jan 21, 2009 at 13:10 UTC
    Even faster:
    tin4=> sub { my $b = 0; $output[$_] = $arr[$b++] + $arr[$b++] + $arr[$b++] for 0..@arr/3; }, tin5=> sub { my $b = -1; $output[$_] = $arr[++$b] + $arr[++$b] + $arr[++$b] for 0..@arr/3; },
    Rate tin1 tin2 tin3 tin4 tin5 tin1 10.2/s -- -54% -59% -65% -68% tin2 22.2/s 118% -- -9% -23% -30% tin3 24.5/s 141% 10% -- -15% -23% tin4 28.8/s 183% 30% 17% -- -9% tin5 31.7/s 211% 43% 29% 10% --
      ikegami, this one knocks me down! Did you know in advance that ++$b would be faster than $b++? Do you know why that is?

        $b++ makes a copy so that it can return the previous value. ++$b does not need to.

        I have run into this issue before in C++, but it was normally not a problem for integers. Scalars on the other hand are a different beast.

        G. Wade

        $b++ needs to create a new anonymous scalar because the result is different than the $b.

        ++$b just returns a pointer to $b.

        $ perl -le'my $b = 4; $r = \( $b++ ); $$r = 20; print $b' 5 $ perl -le'my $b = 4; $r = \( ++$b ); $$r = 20; print $b' 20
Re^2: Summing Up Array Elements By Group
by repellent (Priest) on Jan 21, 2009 at 09:23 UTC
    Nice. The int is not necessary:
    $output[$_/3] += $arr[$_] for 0 .. $#arr;
Re^2: Summing Up Array Elements By Group
by imrags (Monk) on Jan 21, 2009 at 08:57 UTC
    The first one you wrote was the fastest:
    Benchmark: timing 1000000 iterations of tin1, tin2, tin3... tin1: 1 wallclock secs ( 0.59 usr + 0.00 sys = 0.59 CPU) @ 16 +86340.64/s (n=1000000) tin2: 1 wallclock secs ( 0.75 usr + 0.00 sys = 0.75 CPU) @ 13 +33333.33/s (n=1000000) tin3: 3 wallclock secs ( 2.22 usr + 0.00 sys = 2.22 CPU) @ 45 +0450.45/s (n=1000000) Rate tin3 tin2 tin1 tin3 450450/s -- -66% -73% tin2 1333333/s 196% -- -21% tin1 1686341/s 274% 26% --
    the input to get this was:
    $results = timethese(1000000,{ tin1 => '$output[int($_/3)] += $arr[$_] for 0..@arr-1;', tin2 =>'$out[$_] = ($arr[(3*$_)]+$arr[(3*$_+1)]+$arr[(3*$_+2)]) for 0. +.(scalar(@arr)/3 - 1);', tin3=>'for (0..$k) { $output[$_] = $arr[$b] + $arr[$b+1] + $arr[$b +2]; $b += 3; } '}); Benchmark::cmpthese( $results );
    Raghu
      clearly the massive differences between tin2 and tin3 must at least alert you that something is wrong with the benchmark... Frankly I have no idea what goes on once you start eval-ing strings in the Benchmark module, but from the presented examples, something seems suspicious.

      Here is a benchmark by me

      use Benchmark qw(cmpthese); my @arr = map {rand} 0..900000; my @output = map {rand} 0..300000;; Benchmark::cmpthese(10,{ tin1 => sub { $output[int($_/3)] += $arr[$_] for 0..@arr-1; }, tin2 => sub { $output[$_] = $arr[3*$_] + $arr[3*$_+1] + $arr[3*$_+2] for 0..@arr/3; }, tin3=> sub { my $b = 0; for (0..@arr /3) { $output[$_] = $arr[$b] + $arr[$b+1] + $arr[$b +2]; $b += 3; } } });
      With result
      $ perl ../../../perlmonks/bench-trip.pl Rate tin1 tin2 tin3 tin1 1.81/s -- -41% -46% tin2 3.08/s 70% -- -9% tin3 3.39/s 87% 10% --

        clearly the massive differences between tin2 and tin3 must at least alert you that something is wrong with the benchmark...

        The problem is that his $b kept growing. You fixed it by readding my $b = 0;.

        Which leads to two the second problem: He didn't use warnings. They don't add a penalty, so use them! If they did add a penalty, all the more reason to use them just like in the real code.

        By the way,
        $output[int($_/3)]
        can be written as
        $output[$_/3]

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (3)
As of 2024-04-19 17:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found