4

我对 perl 并不陌生,但我无法解决这个用例。

这是我的问题陈述:

我正在使用 Activestate perl 5.12 32 位。我想一次在内存中保存一些 32 x 8MB 的 double 数组。不幸的是,在这种情况下,我遇到了“内存不足”错误。例如,下面的代码会导致内存不足。

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)];

有什么方法可以有效处理吗?

注意:无论如何,在执行的任何时候都需要尽可能快地访问数组(因为用户不能等待太久)

我尝试过的选项:

  1. DBM::Deep - 需要更多时间
  2. PDL - 给出 32 x 8MB 双精度数组的“内存不足”错误

期待您的宝贵建议!

4

3 回答 3

11

32 个数组 * 8 个 Mi-doubles/数组 * 8 个字节/double = 2 GiB。

Windows 上的 32 位进程只有 2GiB 的可用地址空间。您的原始数据将占用所有可用的地址空间,而不会为数据结构的开销perl、您的程序和其他变量留下任何东西。它适合内存的唯一方法是切换到 64 位 Perl。否则,您将不得不面对一个必然较慢的解决方案。

于 2012-12-19T00:55:26.900 回答
3

这将为每个元素创建一个 perl 值,这将非常繁重。您可能想查看将值存储为双精度值的东西,例如Tie::CArrayTie::Array::PackedC

于 2012-12-19T00:42:27.147 回答
2

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.

于 2012-12-19T15:48:55.477 回答