Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux Perl内存不足,但有大量可用内存_Linux_Perl_Memory - Fatal编程技术网

Linux Perl内存不足,但有大量可用内存

Linux Perl内存不足,但有大量可用内存,linux,perl,memory,Linux,Perl,Memory,我运行的perl脚本因内存不足错误而崩溃。 该脚本在UbuntuLinux下运行,机器内存为128GB。在提交时,大部分内存都可用,但是由于脚本使用的内存超过了略高于8Gb的值,因此脚本将死亡。机器(和操作系统)是64位的 我一直在网上搜索perl中的内存分配限制,但我发现唯一的限制是机器内存,在这种情况下,即使不考虑交换分区,也有很多限制 这是我第二次遇到这个问题。我第一次使用不同的脚本时,同样的事情发生了。有人有解释吗?我看到的唯一可能性是perl对内存分配有一些限制,但我在网上搜索的所有结

我运行的perl脚本因内存不足错误而崩溃。 该脚本在UbuntuLinux下运行,机器内存为128GB。在提交时,大部分内存都可用,但是由于脚本使用的内存超过了略高于8Gb的值,因此脚本将死亡。机器(和操作系统)是64位的

我一直在网上搜索perl中的内存分配限制,但我发现唯一的限制是机器内存,在这种情况下,即使不考虑交换分区,也有很多限制

这是我第二次遇到这个问题。我第一次使用不同的脚本时,同样的事情发生了。有人有解释吗?我看到的唯一可能性是perl对内存分配有一些限制,但我在网上搜索的所有结果似乎都与这种可能性相矛盾

提前谢谢

编辑1: 操作系统是FedoraLinux,而不是Ubuntu Linux。对不起,我弄糊涂了

编辑2: 以下是导致错误的代码部分:

open( $psFullInput, "<", "fullPsIn.dat" );
$counter = <$psFullInput>;  # First element is counter of spectra
while ($line = <$psFullInput>)  {
  @elems = split(" ",$line);
  $xx = shift(@elems);
  $yy = shift(@elems);
  $freq = shift(@elems);
  $psStored[$xx][$yy] = [];
  push( @{$psStored[$xx][$yy]}, @elems );
}
close( $psFullInput );
编辑4: 下面是一个简短的代码,重现了这个问题。 正如你所看到的,我只是在填满记忆

use strict;
use warnings;

my ($xx,$yy);  # Coordinate variables
my (@elems);   # Array of elements to be stored on each matrix position

# Generate an array of 3000 floating point values.
# The list will be added to each array element. In the true script
# of course, each element has a list of completely different values.
# Here I use the same list of values for simplicity.
for ($xx = 1; $xx < 3000; $xx++)  {
  push( @elems, 1+$xx/10000 );
}

# Fill in each matrix element with the generated array
my @psStored;
for ($xx = 0; $xx < 300; $xx++)  {
  print "Row [$xx]\n";
  for ($yy = 0; $yy < 300; $yy++)  {
    push( @{$psStored[$xx][$yy]}, @elems );
  }
}
更新1

我进一步调查。正如建议的那样,我使用了Devel::Size并检查了$psStored的大小。输出的最后几行(以$yy为单位打印每个周期结束时的大小)为:

脚本给出错误时的进程大小为: 病毒:8943960,分辨率:8.406g

但是,我尝试了以下脚本,该脚本按照命令行上的指定分配给定大小(以GB为单位)的字符串:

use strict;
use warnings;

my $size = $ARGV[0];
print "$size GB ";
$size = int($size * 1000000000);
print "($size bytes)...\n";
my $var = "x" x $size;
print "Allocated\n";
此脚本对于大型分配没有问题。例如,我可以请求30 GB,在脚本完成之前,我从“top”获得以下输出: 病毒:56.004g,分辨率:0.054t


因此,在处理数组时,有一些东西会干扰分配,但我不明白发生了什么。我也尝试过哈希,但我得到了8-9GB左右的相同限制。

我怀疑
$xx
$yy
的值相当大且稀疏(即它们之间存在很大的差距)。这意味着Perl必须为所有中间值创建数组元素,即使其中没有数据

数据结构的设计主要取决于您在构建数据结构后想对其做什么,以及需要如何访问它。最节省空间的方法是使用散列,以便

$xx = 1024
$yy = 2048
然后将频率存储在
$ps_storage[1024][2048]
中(创建
$ps_storage[0]
$ps_storage[1023]
$ps_storage[1024][0]
$ps_storage[1024][2047]
并将其保留为空),而不是将其存储在散列中完全不浪费空间

因为你没有说你将如何使用这些数据,所以我无法判断它是否像这样可行,但是这里有一些代码来代替你的,以这种方式构建散列

use strict;
use warnings;
use autodie;

my %ps_stored;

open my $ps_full_input, '<', 'fullPsIn.dat';
my $counter = <$ps_full_input>;  # First element is counter of spectra

while (<$ps_full_input>)  {
  my @elems = split;
  my ($xx, $yy, $freq) = @elems;
  push @{ $ps_stored{"$xx,$yy"} }, \@elems;
}

close $ps_full_input;
或者,您可以在程序的顶部使用autodie,如果代码中有多个
open
调用,这将非常有用

  • 您必须始终在每个Perl程序的顶部
    使用strict
    使用warnings
    ,并使用
    my
    声明所有变量,使其尽可能接近其第一个使用点。因为您的代码是一个示例,所以不清楚您是否有
    strict
    warnings
    ,但根本没有声明,所以出现了一些问题

  • 习惯使用Perl的人会感谢您在本地标识符中只使用小写字母、数字和下划线。为包和模块名称保留大写字母,如
    Data::Dumper

  • 在将推到空数组上之前,无需为空数组的引用预设标量值。只要标量仍然
    undef
    ,第一次使用
    push
    时,数组将自动激活。比如说

    my $aref;
    push @{ $aref }, 1, 2, 3;
    
    具有与相同的效果

    my $aref;
    $aref = [];
    push @{ $aref }, 1, 2, 3;
    
  • 我已将对
    @elems
    数组的引用推送到
    ps\u存储的
    列表中。我不知道
    $xx
    $yy
    的特定值是否会出现多次,但如果它们出现了,那么您的方法只会将所有不同的
    @elems
    集合推到一个列表中,这可能会很难再拆分为单独的集合。如果您推送一个引用,则它们保持分离


  • 我希望这有帮助,你能用一个很短的测试脚本复制这个问题吗?也许你可以发布测试脚本,我会在我的机器上运行它。也许你没有写的一个模块是不可靠的


    请使用哈希值尝试此代码

    use strict;
    use warnings;
    
    my ($xx,$yy);  # Coordinate variables
    my (@elems);   # Array of elements to be stored on each matrix position
    
    # Generate an array of 3000 floating point values.
    # The list will be added to each array element. In the true script
    # of course, each element has a list of completely different values.
    # Here I use the same list of values for simplicity.
    for ($xx = 1; $xx < 3000; $xx++)  {
      push( @elems, 1+$xx/10000 );
    }
    
    # Fill in each matrix element with the generated array
    my %psStored;
    my $s;
    $s=join('=',@elems);
    for ($xx = 0; $xx < 300; $xx++)  {
      print "Row [$xx]\n";
      for ($yy = 0; $yy < 300; $yy++)  {
        $psStored{$xx,$yy} = $s; # Here I join all elements and store them as a string.
        #push( @{$psStored[$xx][$yy]}, @elems );
      }
    }
    
    使用严格;
    使用警告;
    我的($xx,$yy)#坐标变量
    我的(@elems);#存储在每个矩阵位置上的元素数组
    #生成3000个浮点值的数组。
    #该列表将添加到每个数组元素中。照原样
    #当然,每个元素都有一个完全不同的值列表。
    #为了简单起见,这里我使用相同的值列表。
    对于($xx=1;$xx<3000;$xx++){
    推送(@elems,1+xx美元/10000);
    }
    #用生成的数组填充每个矩阵元素
    我的%s存储;
    我的$s;
    $s=join('=',@elems);
    对于($xx=0;$xx<300;$xx++){
    打印“行[$xx]\n”;
    对于($yy=0;$yy<300;$yy++){
    $psStored{$xx,$yy}=$s;#这里我将所有元素连接起来,并将它们存储为字符串。
    #推送(@{$psStored[$xx][$yy]},@elems);
    }
    }
    
    你的意思是GB(字节)而不是GB(位),对吗?你能告诉我们这个脚本使用的8GB中的大部分是为什么分配的吗?是很多小块还是几个大块?知道它在mo上要分配多少内存吗
    open my $ps_full_input, '<', 'fullPsIn.dat' or die $!;
    
    my $aref;
    push @{ $aref }, 1, 2, 3;
    
    my $aref;
    $aref = [];
    push @{ $aref }, 1, 2, 3;
    
    use strict;
    use warnings;
    
    my ($xx,$yy);  # Coordinate variables
    my (@elems);   # Array of elements to be stored on each matrix position
    
    # Generate an array of 3000 floating point values.
    # The list will be added to each array element. In the true script
    # of course, each element has a list of completely different values.
    # Here I use the same list of values for simplicity.
    for ($xx = 1; $xx < 3000; $xx++)  {
      push( @elems, 1+$xx/10000 );
    }
    
    # Fill in each matrix element with the generated array
    my %psStored;
    my $s;
    $s=join('=',@elems);
    for ($xx = 0; $xx < 300; $xx++)  {
      print "Row [$xx]\n";
      for ($yy = 0; $yy < 300; $yy++)  {
        $psStored{$xx,$yy} = $s; # Here I join all elements and store them as a string.
        #push( @{$psStored[$xx][$yy]}, @elems );
      }
    }