I guess I should provide some real code.
below is a tiny module I grabbed from my project which is not that privacy
but sufficient for discussion.

#/usr/bin/perl
use warnings;
use 5.010;
use Carp;
use DB_File;

{
    my %sum_cache;
    my %deviation_cache;
    tie %sum_cache => 'DB_File', "sum_cache_tmp", O_RDWR|O_CREAT, 0666 or
croak "can not create cache file!";
    tie %deviation_cache => 'DB_File', "deviation_cache_tmp",
O_RDWR|O_CREAT, 0666 or croak "can not create cache file!";


    sub get_sum
    {
my ($i, $n, $opens_ref) = @_;
my $key = join ',', $i, $n;
unless(exists $sum_cache{$key})
{
    my $inner_key = join ',', $i - 1, $n;
    my $sum = 0;
    if(exists $sum_cache{$inner_key})
    {
        $sum = $sum_cache{$inner_key} - ${$opens_ref}[$i - $n] +
${$opens_ref}[$i];
    }else
    {
$sum += $_ foreach @{$opens_ref}[$i - $n + 1 .. $i];
    }
    $sum_cache{$key} = $sum;
}
return $sum_cache{$key};
    }

    sub get_deviation
    {
my ($i, $n, $mean, $opens_ref) = @_;
my $key = join ',', $i, $n;
unless(exists $deviation_cache{$key})
{
    my $sum = 0;
    $sum += ($_ - $mean) ** 2 foreach @{$opens_ref}[$i - $n + 1 .. $i];
    $deviation_cache{$key} = sqrt($sum / ($n - 1));
}
return $deviation_cache{$key};
    }

    sub cal_using_simple_scheme
    {
my($n1, $n2, $n3, $klines_ref) = @_;
my @opens = map {$_->{open}} @$klines_ref;
croak "Wrong argnument. Should all be positive values" if ($n1 <= 0 || $n2
<= 0 || $n3 <= 0);
return [(0) x @opens] if $n2 <= 1;
my $n = $n1 > $n2 ? $n1 : $n2;
my @res;
my @upper_bound;
my @lower_bound;
 for my $i (0 .. $#opens)
{
    if($i < $n - 1)
    {
push @upper_bound, undef;
push @lower_bound, undef;
next;
    }

    my $sum1 = get_sum($i, $n1, \@opens);
    my $mid = $sum1 / $n1;

    my $sum2 = get_sum($i, $n2, \@opens);
    my $mean = $sum2 / $n2;
    my $std_deviation = get_deviation($i, $n2, $mean, \@opens);

    push @upper_bound, $mid + $n3 * $std_deviation;
    push @lower_bound, $mid - $n3 * $std_deviation;
}
for my $i (0 .. $#opens)
{
    if(!defined($upper_bound[$i]))
    {
push @res, 0;
next;
    }
    given( $opens[$i])
    {
when($_ > $upper_bound[$i]) {push @res, 1; break}
when($_ < $lower_bound[$i]) {push @res, -1; break}
default {push @res, $res[-1]; break}
    }
}
return \@res;
    }

}

1;

and it's called like this:
my $klines_ref;
for my $n1 (1..200)
{
for my $n2 (1..200)
{
for my $n3 (1,3,5,7)
{
my $res = cal_using_simple_scheme($n1, $n2, $n3, $klines_ref);
#using the result to do something, omitted here.
}
}
}

$klines_ref is a reference to an array which contains at least 60000+
elements.
the module is simple, the main time consuming part is calculating sum and
standard deviation part. I cached the results for both sum and
std_deviation. but since the input array is so big that during the first
call of the cal_using_stupid_scheme the program crashes because of out of
memory. So I tie the two hashes to local files, and as I predicted, the
speed is unacceptable. maybe this is the kind of problem perl is good at?
I still use index because I really don't know how to avoid it. would some
body point out the wrong and not perlish part of the program above?
Thank you all.

Reply via email to