in reply to how can I speed this up?

I quite liked this problem at first, and like TheoPetersen my reaction was to try unpack and map. Adding unpack was easy, and I even squeezed in a map or two, but not avoiding a for loop. Now the strange thing is that all my efforts are actually slower than rbi's original. I'll add code if anyone wants but it's basically what was posted here:

Alba_1 is almost exactly TheoPetersen's solution (I didn't bother posting after seeing his)
Alba_2 is a variant that does the unpacking this way:

my @fractions = unpack('A5'x$nt, substr($record, 0, 5*$nt)); my @exps = unpack('A2'x$nt, substr($record, 5*$nt, 2*$nt));
rbi_fortran is rbi's code (though made strict compliant). And the result are (based on 7 fields in $record):
Benchmark: running Alba_1, Alba_2, rbi_fortran, each for at least 5 CP +U seconds... Alba_1: 6 wallclock secs ( 5.31 usr + 0.00 sys = 5.31 CPU) @ 39 +94.16/s (n=21217) Alba_2: 6 wallclock secs ( 5.41 usr + 0.00 sys = 5.41 CPU) @ 47 +89.68/s (n=25893) rbi_fortran: 5 wallclock secs ( 5.26 usr + 0.00 sys = 5.26 CPU) @ 5 +211.78/s (n=28266)
So what gives? I could have sworn unpack was faster. One thing I tried is the effect of the number of fields to extract, so here it is with 28 fields in $record:
Benchmark: running Alba_1, Alba_2, rbi_fortran, each for at least 5 CP +U seconds... Alba_1: 5 wallclock secs ( 5.39 usr + 0.00 sys = 5.39 CPU) @ 12 +14.06/s (n=6545) Alba_2: 6 wallclock secs ( 5.41 usr + 0.00 sys = 5.41 CPU) @ 14 +25.64/s (n=7707) rbi_fortran: 5 wallclock secs ( 5.37 usr + 0.00 sys = 5.37 CPU) @ 1 +540.09/s (n=8278)
Basically no effect. Any other ideas?

--
I'd like to be able to assign to an luser

Replies are listed 'Best First'.
Re: Re: how can I speed this up?
by rbi (Monk) on Feb 24, 2001 at 03:00 UTC
    Thanks for the answers and comments so far.
    I did test all the suggestions too, and I found that the things were worsening about 20% (no profiles, I still have to learn that, just used ps...) with:
    1. use of unpack (quite clean coding though)
    2. extracting the strings from $record and "printing" the exponetial format with, more or less, this code:
    ... foreach $it (1..$nt) { $x11 = substr($record,$lmina,1); $x12 = substr($record,$lmina+1,4); $ib = substr($record,$lminb,2); if ($x11 == 0 and $x12 == 0 and $ib == 99) { $values[$it-1] = $val_missing; } else { if (($ib % 2) == 0) { $x2 = $ib/2; } else { $x2 = -($ib+1)/2; } $values[$it-1] = sprintf "%u.%4.4uE%3.3d\n",$x11,$x12,$x2; } $lmina = $lmina + 5; $lminb = $lminb + 2; } return @values; }
    There is a 20% improvement by removing the subtractions when indexing (avoiding things like $values[$it-1])
    There is no gain by preparing a @tmp array and make just one printing per record
    Roberto