繁体   English   中英

如何解决非常慢的 perl 脚本在一台服务器上运行得更快但在另一台服务器上运行缓慢

[英]How to troubleshoot very slow perl script that runs faster on one server but slow on another

我收到了一个 perl 脚本,该脚本应该过滤 Hi-C 数据的探针,但它运行速度非常慢(几天)。 给我脚本的人告诉我,在她以前的实验室的服务器上只花了几个小时,所以我想知道是什么导致了运行时间的这种差异,我该如何让它运行得更快? 我对 perl 的了解非常有限,但到目前为止我的谷歌搜索表明我可能需要更改一些 perl 配置文件? 下面是整个脚本中耗时最长的主要 function,输入文件包含染色体目标和位置。 任何帮助将不胜感激!

我曾尝试使用 perl 5.16 和 5.26 运行,看看版本是否太旧,但花了同样长的时间。

sub get_restriction_fragments_for_targets {

    my @targets = @_;

    # Split by chromsome and sort
    my %targets;

    foreach my $target (@targets) {
            push @{$targets{$target->{chr}}},$target;
    }

    foreach my $chr (keys %targets) {
            my @sorted = sort {$a -> {start} <=> $b -> {start}} @{$targets{$chr}};

            # We also need to merge overlapping capture regions

            my @merged;

            my $last_region;

            foreach my $region (@sorted) {
                    unless ($last_region) {
                            $last_region = $region;
                            next;
                    }

                    if ($region->{start} < $last_region -> {end}) {
                            # Merge
                            if ($region ->{end} > $last_region->{end}) {
                                    $last_region->{end} = $region->{end};
                            }
                            next;
                    }

                    push @merged,$last_region;
                    $last_region = $region;
            }

            push @merged,$last_region;

            $targets{$chr} = \@merged;
    }

    my @target_fragments;

    open (IN,'all_restriction_fragments.txt') or die $!;

    my $last_chr = "";
    my $last_index = 0;

    while (<IN>) {
            chomp;
            my $line = $_;

            my ($chr,$start,$end) = split(/\t/);

            if ($chr ne $last_chr) {
                    warn "Moving to $chr\n";
                    $last_chr = $chr;
                    $last_index = 0;
            }

            next unless (exists $targets{$chr});

            my @local_targets = @{$targets{$chr}};

            foreach my $index ($last_index .. $#local_targets) {
                    my $target = $local_targets[$index];

                    if ($target -> {end} < $start) {
                            $last_index = $index;
                            next;
                    }

                    if ($target -> {start} > $end) {
                            last;
                    }

                    push @target_fragments,{
                            id => $target->{id},
                            chr => $chr,
                            start => $start,
                            end => $end,
                    };
                    last;
            }
    }

    return @target_fragments;
}

如果不了解更多有关该问题的信息,首先是关于数据结构的大小和所处理文件的大小,就无法判断。

以下是关于代码似乎在做什么原则上最耗时的操作的一般评论,以(可能)重要性和/或可能性的递减顺序

  • 文件有多大? 那是磁盘访问,可能需要任何时间

  • 循环排序——排序的数据有多大? sort很耗时

  • @sorted周围有“踢踏舞”,这会导致数据复制——有多少数据?

  • 一般来说,有很多数据复制——@ @targets传递到例程中有多大?

如您所见,每个因素都伴随着数据有多大的问题。 磁盘访问当然成本很高,但程序中各种数据结构之间的大量数据复制同样重要。

因此,如果您能提供一些细节,这将有助于我们为您提供更详细的分析/猜测。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM