优化的第一条规则是不要做得太早(即在不分析代码的情况下过早地得出结论)。
第二条规则可能是指缓存。
你的File2
不是很大。我会说我们将它加载到内存中。这具有以下优点:
- 我们只做一次解析。
- 该文件不是很大,因此空间不是什么大问题。
- 我们可以创建一个使查找变得非常简单的数据结构。
关于第一点:您将每一行拆分三千多次。这些周期本来可以更好地度过。
关于第三点:您似乎进行了索引转换:
1 → 1, 2 → 2, 0 → 3
代替使用 if/elsif 开关(线性复杂度)测试所有值,我们可以使用一个数组来进行这种转换(恒定时间查找):
my @conversion = (3, 1, 2);
...;
print OUT $value[$conversion[$data[$RS++]]];
如果这个索引转换是恒定的,我们可以在解析时只做一次File2
。这看起来像
use strict; use warnings;
use autodie; # automatic error handling
my @file2;
{
open my $file2, "<", "File2.txt";
while (<$file2>) {
my (undef, @vals) = split;
# do the reordering. This is equivalent to @vals = @vals[2, 0, 1];
unshift @vals, pop @vals;
push @file2, \@vals;
}
}
现在我们可以继续迭代File1
. 从现在开始打印相应的条目File2
看起来像
open my $file1, "<", "File1.txt";
<$file1>; # remove header
while (<$file1>) {
my ($id, @indices) = split;
print $id, map $file2[$_][$indices[$_]], 0 .. $#indices;
# but I guess you'd want some separator in between
# If so, set the $, variable
}
这个算法仍然是二次的(这map
只是一个for
变相的循环),但这应该有一个更好的常数因子。给定您的示例输入,上述代码的输出是
23 A F G
34 B E I
45 A D I
23 C F H
10 B D G
(与$, = " "; $\ = "\n"
)。
从这往哪儿走
最后一步(循环通过 File1)可以并行化,但这不太可能有太大帮助:IO 很慢,线程之间的通信很昂贵(IPC 更是如此),并且输出将是随机顺序的。我们可以生成一堆工人,并在队列中传递未解析的行:
use threads; # should be 1st module to be loaded
use Thread::Queue;
use constant NUM_THREADS => 4; # number of cores
# parse the File2 data here
my $queue = Thread::Queue->new;
my @threads = map threads->new(\&worker), 1 .. NUM_THREADS;
# enqueue data
$queue->enqueue($_) while <$file1>;
# end the queue
$queue->enqueue((undef) x NUM_THREADS); # $queue->end in never versions
# wait for threads to complete
$_->join for @threads;
sub worker {
while(defined(my $_ = $queue->dequeue)) {
my ($id, @indices) = split;
print $id, map $file2[$_][$indices[$_]], 0 .. $#indices;
}
}
请注意,这会将 复制@file2
到所有线程中。有趣的事实:对于示例数据,这个线程解决方案大约需要 4 倍的时间。这主要是线程创建的开销,因此这对您的数据来说不是什么问题。
在任何情况下,分析您的代码以查看您可以最有效地优化的地方。我推荐优秀的Devel::NYTProf
。例如,对于我使用这些非常有限的数据运行的非线程测试,autodie
和朋友暗示的开销比实际处理花费的时间更多。对你来说,最昂贵的线路可能是
print $id, map $file2[$_][$indices[$_]], 0 .. $#indices;
但是在 Perl 中我们无能为力。