>>>>> "XL" == Xi Liu <jason.li...@gmail.com> writes:

  XL> Thanks for your help!
  XL> I am sorry I missed something important in the code snippet.
  XL>  for($i = 0; $i < @lines; $i++)
  XL> {
  XL>      $sum = 0;
  XL>      $sum += $lines[$_]->{foo_value} for ($i - $n + 1 .. $i);
  XL>      push @res, $sum;
  XL> }
  XL> this is what I intend.I try to make it clear and removed something so that
  XL> change the original intend without noticing it, sorry.

a good rule to all newbies here. post all the relevent code. removing
lines can obscure your real intent as this did here.


  XL> I write a little program:

  XL> #!/usr/bin/perl
  XL> use warnings;
  XL> use List::Util qw(sum);

the best way to time code is with the Benchmark module. 

  XL> push @lines, {foo_value => 6000 + int rand(4000)} for 0 .. 60000;
  XL> my $n = 100;
  XL> for my $i (99 .. 60000)
  XL> {
  XL>     my ($sum1, $sum2, $sum3);
  XL>     $sum1 += $lines[$_]->{foo_value} for ($i - $n + 1 .. $i);
  XL>     map {$sum2 += $_->{foo_value}} @lines[$i - $n + 1 .. $i];
  XL>     $sum3 = sum (map {$_->{foo_value}} @lines[$i - $n + 1 .. $i]);
  XL> }

none of those do the push you mentioned. and if they did, they could use
the saved sums to shorten the later summing loops as they sum
overlapping values. that is the key to saving time here.

  XL> and profile it, it turns out the result
  XL> 3.00s $sum1 += $lines[$_]->{foo_value} for ($i - $n + 1 .. $i);
  XL> 1.71s map {$sum2 += $_->{foo_value}} @lines[$i - $n + 1 .. $i];

that map is not cool. it isn't using the resulting list of the map. even
though it is the fastest one here, i wouldn't use it.

  XL> 2.10s $sum3 = sum (map {$_->{foo_value}} @lines[$i - $n + 1 .. $i]);

  XL> using map on sliced list makes it better but still not acceptable.Any more
  XL> ideas?

what i said above. you are doing the same work multiple times by not
keeping the earlier sums and using them.

  XL> and I used to think the "foreach $i (0..$#lines)" and "for($i = 0; $i <
  XL> @lines; $i++)" are the same.
  XL> but the prior cost 66µs , a great victory compared to the second's 50ms.
  XL> how should I suppose to know they have efficiency  differences?  *:-)*

it is fairly obvious on the surface. the .. just builds a list and
internally gets the next one. the c style ++ loop has to execute several
perl operations for each iteration. a rule of thumb in perl speed (not
always true but most often it is) is the more perl code the slower. the
more you stay inside perl's guts (in c) the faster. the perl operator
loop is slow so use fewer perl ops. the c style loop uses perl ops. the
foreach loop doesn't.

another idea is to loop over the lines themselves and not their
indexes. again, your math eludes me and i won't get into it. you seem to
be summing the 100 lines at each possible point in the main array. so
that means you are just summing he first and last 100 lines in a
triangle way and ALL the other lines are just 60,000 x 100 times added
in to the sum. so you could short circuit the whole middle with a single
loop and sum them up and then multiply that by 59,900 and get the same
value. that will blow your time away since you removed all the double
and slow looping stuff. again this is from a very cursory analysis of
the math which still makes NO sense to me. why are you summing
overlapping segments of the main array? if you know you are going to do
that, factor out the parts that i said and it will speed up massively.

rule: a better algorithm usually beats better code.

uri

-- 
Uri Guttman  ------  u...@stemsystems.com  --------  http://www.sysarch.com --
-----  Perl Code Review , Architecture, Development, Training, Support ------
---------  Gourmet Hot Cocoa Mix  ----  http://bestfriendscocoa.com ---------

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to