Perl 关于读取50GB文件(并将其重写为16K文件)的建议!

Perl 关于读取50GB文件(并将其重写为16K文件)的建议!,perl,Perl,我有一个巨大的文件(将近50GB,只是一个由360K行组成的ASCII矩阵,每个行有15K个数字),我需要对它进行转置。为了避免在内存中读取整个内容,我只编写了一个Perl脚本,它打开15K个文件(矩阵的每列一个),然后读取输入文件的一整行,并将每个数字写入相应文件的末尾(输出文件column0.txt的第一个数字,输出文件column1.txt的第二个数字,以此类推) 事情看起来很有希望:代码只使用了178MB的内存,并且只有部分输入文件的初始测试运行得很好:它在大约一分钟内处理了3600行,

我有一个巨大的文件(将近50GB,只是一个由360K行组成的ASCII矩阵,每个行有15K个数字),我需要对它进行转置。为了避免在内存中读取整个内容,我只编写了一个Perl脚本,它打开15K个文件(矩阵的每列一个),然后读取输入文件的一整行,并将每个数字写入相应文件的末尾(输出文件column0.txt的第一个数字,输出文件column1.txt的第二个数字,以此类推)

事情看起来很有希望:代码只使用了178MB的内存,并且只有部分输入文件的初始测试运行得很好:它在大约一分钟内处理了3600行,所以我希望在大约两个小时内完成整个工作,但当我运行真正的代码时,代码会在许多点停止。例如,在开始时它会处理sed~4600行非常快,然后停止了相当长的一段时间(可能5-10分钟),然后继续。现在,经过~10小时的计算,它已经处理了131K行,代码在处理了300-400行后停止了两到三分钟

我从未处理过如此大的输入文件或如此多的打开文件,因此我不确定问题是在于输入还是文件描述符的数量。关于如何诊断(并希望)解决速度问题,有什么建议吗?我在下面介绍了程序的相关部分

谢谢

==================================

for ($i=0 ; $i<$columnas ; $i++) {
    $column[$i]  = IO::File->new(">column$i.txt") or die $!;
}

while (<DATA>) {
    chomp;
    $cols = split;

    for ($col=0 ; $col<$cols ; $col++) {
        print { $column[$col] } "$_[$col] " ;
    }
}

close (DATA) or die $!;
($i=0;$inew(“>列$i.txt”)或die$!; } 而(){ 咀嚼; $cols=拆分;
对于($col=0;$col)来说,考虑到你得到了奇怪的结果,检查你的打印是否成功可能是一个好主意:

print { $column[$col] } "$_[$col] "
    or die "Error printing column $col: $! ";
尝试每隔500行左右刷新一次?
使用IO::Handle;
打印后:

if ( $. % 500 == 0 ) {
    $column[$col]->flush()
        or die "Flush of column $col failed: $! ";
}

检查/proc/sys/fs/file max以查看打开文件的最大数量。
您可能需要使用seek读取文件,以便相应地控制要读取的打开文件的数量。
最好是缓存x行,然后附加到所有文件。

一些想法

1.隐式拆分为@

$cols = split;
发出警告:

Use of implicit split to @_ is deprecated
如果您还没有这样做,您应该添加

use warnings;
use strict;
注意你的脚本。(注意那些警告。)

考虑将
$cols
更改为
@cols
,并在for循环中使用
$#cols

@cols = split;
for (my $col=0; $col <= $#cols; $col++)
ETA:
@column
此处包含从数据转换而来的列。使用以下命令代替打印:

$column[$col] .= $cols[$col] . " ";

你知道矩阵的尺寸吗?列的长度是可变的还是可变的?你使用的是哪种平台?嗨,是的,尺寸是根据linux(Fedora)上的post 300k行、15k列(始终固定长度)确定的。我现在做了一些测试,问题是打开的输出文件的数量。如果我将问题限制为只打开(并写入)前4000列的数据,看起来都正常,cPU使用率为100%。如果我尝试使用8000个文件,则问题(暂时)无法解决在第4660行,perl脚本进入D状态,cPU使用率为0%。对于4000个打开的文件,它也会被卡住,尽管稍后会在第10000行左右,然后它会继续运行,尽管速度要慢得多。(我想这与输出缓冲有关吗?)正常情况下,
print
w/o
“\n”
将不同步输出缓冲区。这可能是原因吗?(即,您运行正常一段时间后突然触发交换并必须写入磁盘)。我不确定它是否有效,但可能每4K行中有一次
$|=1
会有所帮助(别忘了将其重置,否则磁盘会崩溃)。是否将所有输出文件存储在一个目录中?
$column[$col] .= $cols[$col] . " ";