Reputation: 660
I am not new to perl , but I couldn't able to solve this usecase.
Here is my problem statement:
I am using Activestate perl 5.12 32-bit. I want to hold some 32 x 8MB array of double in Memory at a time. unfortunately, I am getting 'out of memory' error in this case. for example, the code below will lead to out of memory.
my $aref1 = [(.25) x (8*1024*1024)];
my $aref2 = [(.25) x (8*1024*1024)];
my $aref3 = [(.25) x (8*1024*1024)];
my $aref4 = [(.25) x (8*1024*1024)];
my $aref5 = [(.25) x (8*1024*1024)];
my $aref6 = [(.25) x (8*1024*1024)];
my $aref7 = [(.25) x (8*1024*1024)];
my $aref8 = [(.25) x (8*1024*1024)];
my $aref9 = [(.25) x (8*1024*1024)];
my $aref10 = [(.25) x (8*1024*1024)];
Is there any way to efficiently handle it?
Note: In any case, the access to the arrays is needed at any time of execution as fast as possible (since the user cannot wait soo long)
the options I have tried:
Awaiting your valuable suggestions!
Upvotes: 4
Views: 274
Reputation: 118156
Here is what I get on my Windows XP SP3 system using ActiveState Perl 5.14.2. Task manager was showing Commit charge: 778M/3958M
when I ran the following script:
#!/usr/bin/env perl
use strict;
use warnings;
use Devel::Size qw(total_size);
my $unit = 1024 * 1024;
my $topj = (8 * $unit) - 1;
my @data;
for my $i (0 .. 31) {
print "$i: ";
my @row;
$#row = $topj;
for my $j (0 .. $topj) {
$row[$j] = 0.25;
}
push @data, \@row;
printf "%.0f\n", total_size(\@data)/$unit;
}
Output:
C:\temp> yy 0: 224 1: 448 2: 672 3: 896 4: 1120 5: 1344 6: 1568 7: 1792 Out of memory! 8:
On the other hand, the following C program does better:
#include <stdlib.h>
#include <stdio.h>
#define ROWSIZE 8*1024*1024
int main(void) {
int n = 1;
while (calloc(ROWSIZE, sizeof(double))) {
printf("%d: success!\n", n);
n += 1;
}
return 0;
}
Output:
1: success! 2: success! 3: success! … 26: success! 27: success!
for the same 1.7GB footprint.
Upvotes: 2
Reputation: 386551
32 arrays * 8 Mi-doubles/array * 8 bytes/double = 2 GiB.
32-bit processes on Windows only have 2GiB of usable address space. Your raw data would take up all available address space, leaving nothing for the data structure's overhead, perl
, your program and other variables. The only way it's going to fit in memory is if you switch to a 64-bit Perl. Otherwise, you will have to contend with a necessarily slower solution.
Upvotes: 11
Reputation: 30235
This will create a perl value for each element, which will be quite heavy. You might want to look at something that stores the values as doubles, such as Tie::CArray or Tie::Array::PackedC.
Upvotes: 3