This was quite a sizable snippet, so I downloaded it, and commented everything.
My first concern would be the number of loops you have, and their placement:
# for each of the 9 $nvars,
# for each of the $nts
# For each of the $nts...
# And the for each of the $nvars...
# for each of the $nts...
you loop through 2 variables 5 times. I believe that it'd be possible to compress this to one nested loop, or to use (look away, JAPHY :) an intermediary variable to store the results of parts of your loops.
Consider the following snippet ( I have removed my comments :
foreach $it (1..$nt) { $tmp = sprintf "%s", $some_vector[$it-1]; foreach $k (1..$nvar) { $tmp = $tmp.sprintf " %11.4E", $field[$it-1][$k-1]; } $tmp = $tmp."\n"; print OUT $tmp;
This loop follows one similar to it, though the inner and outer loops are swapped. Consider printing $tmp as the last step of the firstforeach $k (1..$nvar) loop.
Also, I might try a little trickery with perl's definition of scalar values when computing the powers. The following snippet "reproduces" 10**n without ever using **. Though, I confess I don't know what the benchmark would be. The following snippet shows how to get the same results. This is only good for powers of ten though :
#--- powers $ib=10; $x2 = 10.**($ib/2); print "$x2\n"; $x2 = "1". "0"x($ib/2); print "$x2\n"; #--- negative power $ib=3; $x2 = 10.**(-($ib+1)/2); print "$x2\n"; $x2 = "0." . "0"x int($ib-1)/2 ."1"; print "$x2\n";
I'd like to hear from some other monks on whether this may be speedier, though.

Finally, whenever I need to speed up code, I'll document it, and more often than not, something will jump out at me. I've included the comments I made while running through your code, and I hope they prove useful.
---
.... $nvar = 9; .... foreach $k (1..$nvar) { # # for each of the 9 $nvars, # $record = <IN>; chomp($record); # # I will read in a record and clear trailing newline. # @values = &decode($record,$nt,$val_m); # # I will 'decode' a record, using $nt and $val_m. # # # for each of the $nts # foreach $it (1..$nt) { # # if the $it'th-1 element of $values is less than one # and is not equal to $val_m, I will die. if ($values[$it-1] < 0 and $values[$it-1] != $val_m) + { die "error: found negative value.\n"; } $field[$it-1][$k-1] = $values[$it-1]; # # I will put $values[$it-1] into $field[$it-1][k-1]. # } } foreach $it (1..$nt) { # # For each of the $nts... # $tmp = sprintf "%s", $some_vector[$it-1]; # # I will format $some_vector[$it-1]. # foreach $k (1..$nvar) { # # And the for each of the $nvars... # $tmp = $tmp.sprintf " %11.4E", $field[$it-1][$k-1]; } $tmp = $tmp."\n"; print OUT $tmp; # # I'll format it and print it. # } # (2) this is seems to go the same speed as the one above ... # # foreach $it (1..$nt) { # printf OUT "%s", $some_vector[$it-1]; # foreach $k (1..$nvar) { # printf OUT " %11.4E", $field[$it-1][$k-1]; # } # print OUT "\n"; # } .... sub decode() { # this routine should decode the $record where there are a series of # $nt decimal fractions in the first part of the string # (5*$nt characters),and exponents in the last decimal fractions are # written as 5-digit integers, and must be multiplied by 10.**(-5), # negative exponents are coded as 2-digit odd numbers, while positive # exponents are even numbers # 12345...01... where 01 are characters $nt*5 and $nt*5+1 will give # 1.234E-01 my $record = shift(); my $nt = shift(); my $val_missing = shift(); $lmina = 0; $lminb = 5 * $nt; foreach $it (1..$nt) { # # for each of the $nts... # $ia = substr($record,$lmina,5); $ib = substr($record,$lminb,2); # # I'll set ia and ib to be certain substrings of $record # if ($ia == 0 and $ib == 99) { $values[$it-1] = $val_missing; # # if $ia is exactly zero, and $ib is exactly 99, set $values[$it-1] +to $val_missing. # } else { $x1 = $ia * 10.**(-5); # # otherwise, set $x1 to $ia times 10 to the negative fifth power. # if (($ib % 2) == 0) { $x2 = 10.**($ib/2); } else { $x2 = 10.**(-($ib+1)/2); } # # if $ib is evenly divisible by two, set $x2 to # 10 to the (half of $ib'th) power, # otherwise, set $x2 to the negative (half of $ib'th+1) power. # $values[$it-1] = $x1 * $x2; # # set $values [$it-1] to the sum of $x1 and $x2. # } $lmina = $lmina + 5; $lminb = $lminb + 2; # increase the position of $lmina and $lminb. } return @values; }

In reply to (boo) Dissecting PerlTRAN by boo_radley
in thread how can I speed this up? by rbi

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.