【问题标题】:Perl, cmd, $ARGV[0], slowPerl, cmd, $ARGV[0], 慢
【发布时间】:2013-08-01 21:22:02
【问题描述】:

[Strawberry Perl v5.16.3,Windows 7 x64,通过cmd执行,例如c:\strawberry> perl test.pl 100000]

症状:以下代码:foreach (1..$ARGV[0]) { foo($_); },执行速度比我在它之前包含此额外行时慢大约 20%:my $num = $ARGV[0];

问题:谁能帮我理解为什么?

注意,在第二种情况下,在我初始化并设置$num 之后,我不会在循环参数中使用$num。如果是这种情况,我可能会确信在 forloop 中反复测试 $ARGV[0] 会比我自己定义的变量慢...但事实并非如此。

为了跟踪时间,我在脚本顶部使用:use Time::HiRes; my $time = [Time::HiRes::gettimeofday()];,在底部使用:print "\n1: ", Time::HiRes::tv_interval($time);

困惑!

谢谢,

迈克尔

编辑

我包含了整个脚本,并在违规行之前添加了注释...有趣的是,时间差异似乎至少部分取决于我对 %h@chain 的冗余初始化。 . 这越来越奇怪了。

    use Time::HiRes; my $time = [Time::HiRes::gettimeofday()];

    #my $max=$ARGV[0];
    my %h = (1=>1,89=>89);
    $h{1}=1;
    $h{89}=89;
    my @chain=();
    my $ans=0;

    sub sum{my $o=0; foreach (@_){$o+=$_}; return $o;}

    foreach (1..$ARGV[0]-1){
        my $x=$_;
        my @chain = ();
        while(!exists($h{$x})){
            push(@chain,$x);
            $x = sum(map {$_**2} split('',$x));
        }
        foreach (@chain){$h{$_}=$h{$x} if !exists($h{$_});}
    }

    print "\n1: ", Time::HiRes::tv_interval($time);
    foreach (1..$ARGV[0]){$ans++ if ($h{$_}==89);}
    print "\n2: ", Time::HiRes::tv_interval($time);

【问题讨论】:

  • 无法最终重现。您能否发布完整的基准测试代码和状态 perl 版本/操作系统?
  • 感谢您的反馈。帖子已编辑以包含一些信息。仍在尝试包含重要代码而不使我的帖子变得丑陋...
  • 您的代码似乎产生了 1E-5 秒(10 微秒)范围内的计时。这对于提供可用的结果来说太小了。此外,您的代码并不清楚您的时间安排。当以足够的迭代次数运行benchmark 时,看不到真正的区别。
  • 尝试 100,000 的参数。在未注释该行的情况下,我得到的时间约为 0.83 秒。评论,我得到 1.20 秒。增加了 50%。
  • 我添加了一个分析作为答案。收集多个时间后我无法检测到任何差异。如果您可以使用我的工具提供可重现的数据,那么我会非常感兴趣。

标签: performance perl cmd argv


【解决方案1】:

在我的系统(GNU/Linux 上的 perl 5.16.3)上没有可测量的差异。时序的标准偏差大于不同版本测量之间的差异。

对于脚本的每个变体,执行了 10 次。 $ARGV[0] 在所有情况下都是 3.5E5 (350000)。

没有my $num = $ARGV[0]

$ perl measure.pl 
2.369921 2.38991 2.380969 4.419895 2.398861 2.420928 2.388721 2.368144 2.387212 2.386347
mean:  2.5910908
sigma: 0.609763793801797

my $num = $ARGV[0]:

$ perl measure.pl 
4.435764 2.419485 2.403696 2.401771 2.411345 2.466776 4.408127 2.416889 2.389191 2.397409
mean:  2.8150453
sigma: 0.803721101668365

measure.pl 脚​​本:

use strict; use warnings; use 5.016;
use List::Util 'sum';

my @times = map qx/perl your-algorithm.pl 3.5E5/, 1..10;
chomp @times;

say "@times";
say "mean:  ", mean(@times);
say "sigma: ", sigma(@times);


sub mean { sum(@_)/@_ }

sub sigma {
    my $mean = mean(@_);
    my $variance = sum(map { ($_-$mean)**2 } @_) / @_;
    sqrt $variance;
}

减少your-algorithm.pl 以便只打印一个时间:

foreach (1..$ARGV[0]){$ans++ if ($h{$_}==89);}
print Time::HiRes::tv_interval($time), "\n";

【讨论】:

  • 当我删除第二个 foreach 和第二个 print 时,正如你所做的那样,我也发现速度没有明显差异。但这没有用,因为我的脚本确实包含了第二个 foreach 和第二个 print,这确实会产生速度差异。
  • 好的,我更新了,以便我的计时也包括该循环。两个版本的 1-sigma-range 仍然重叠。因此我们不能推断出版本有不同的运行时间。
  • 我猜我们的系统对脚本的解释不同。我仍然有非常不同的时间,始终如一。谢谢。
  • 它们在我的系统上的运行时间也非常相似。我同意 amon 的观点,如果我们无法重现您的时间问题,我们将无法弄清楚为什么一次运行需要更长的时间
  • Matt,你的操作系统和 Perl 版本是多少?我想知道草莓解释器或 Win 7 x64 是否是罪魁祸首。
猜你喜欢
  • 2014-09-22
  • 1970-01-01
  • 2011-01-02
  • 2017-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-11
  • 2013-08-31
相关资源
最近更新 更多