【问题标题】:Need advice for Memory usage in perl需要关于 perl 中的内存使用的建议
【发布时间】:2012-12-19 00:35:31
【问题描述】:

我对 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 双数组的“内存不足”错误

期待您的宝贵建议!

【问题讨论】:

    标签: perl memory-management


    【解决方案1】:

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

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

    【讨论】:

    • 是的。我现在可以理解这个问题了。所以我正在寻找任何其他中间解决方案(如Inline::CInline。是否可以将数据全局存储在 Inline::C 中?
    • 不,原始数据占用您拥有的更多内存。切换语言不会有帮助。您需要切换到 64 位进程,或者想办法不一次将所有数据都保存在内存中。
    【解决方案2】:

    这将为每个元素创建一个 perl 值,这将是相当沉重的。您可能希望查看将值存储为双精度值的内容,例如 Tie::CArrayTie::Array::PackedC

    【讨论】:

    • 另外,您可能不想在此过程中创建数百万个临时值。在循环中初始化可能更可行。
    【解决方案3】:

    这是我在使用 ActiveState Perl 5.14.2 的 Windows XP SP3 系统上得到的结果。当我运行以下脚本时,任务管理器显示 Commit charge: 778M/3958M

    #!/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;
    }
    

    输出:

    C:\temp> 是
    0:224
    1:448
    2:672
    3:896
    4:1120
    5:1344
    6:1568
    7:1792
    内存不足!
    8:

    另一方面,下面的 C 程序做得更好:

    #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;
    }
    

    输出:

    1:成功!
    2:成功!
    3:成功!
    …
    26:成功!
    27:成功!

    对于相同的 1.7GB 占用空间。

    【讨论】:

    • 我正在寻找任何其他中间解决方案(如Inline::CInline)。是否可以将数据全局存储在 Inline::C 中?
    猜你喜欢
    • 1970-01-01
    • 2021-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多