在Perl子例程中定义局部临时变量的位置?

asc*_*ltz 3 perl scope

我花了太长时间才使用警告; 严格 在Perl,但现在我做了,我看到了优点.

我还不确定的一件事是何时定义一个临时变量.这似乎是一件微不足道的事情,但我运行了很多蒙特卡罗模拟,其中失去一点时间加起来超过10000次迭代.我一直懒得在更快的模拟上使用严格/警告,但它们变得更加复杂,所以我真的需要.

所以(切掉代码来计算东西)我想知道是否

sub doStuff
{
  my $temp;
  for my $x (1..50)
  {
    $temp = $x**2;
  }
  for my $x (1..50)
  {
    $temp = $x**3;
  }
}
Run Code Online (Sandbox Code Playgroud)

要么

sub doStuff
{
  for my $x (1..50)
  {
    my $temp = $x**2;
  }
  for my $x (1..50)
  {
    my $temp = $x**3;
  }
}
Run Code Online (Sandbox Code Playgroud)

效率更低/更高,或者如果违反了一些我还不知道的Perl编码.

zdi*_*dim 6

这两者之间的效率足够接近,任何实际处理都相形见绌.所以我会通过代码 - 如果$tmp确实是临时的并且在循环之后不需要,那么由于所有其他原因,最好将其保持在内部(作用域).

由于这是关于优化我想离题.这些微问题可能会产生影响.但是,您真正获得的地方首先是算法级别,然后适当选择数据结构和技术.低级调整是最后要考虑的事情,并且通常有语言功能和库使它们无关紧要.也就是说,人们应该知道一个人的工具而不是浪费时间.

此外,通常在代码清晰度和效率之间进行权衡.如果是这样,我建议编码的正确性和清晰度.然后,如果需要,谨慎和逐步地进行分析和优化,并在两者之间进行大量测试.

这是一个比较,作为核心模块Benchmark的基本使用示例.我抛出一个额外的操作,并添加其他没有临时的情况.

use warnings 'all';
use strict;    
use Benchmark qw(cmpthese);

my $x;

sub tmp_in {
    for (1..10_000) {
        my $tmp = 2 * $_;
        $x = $tmp + $_;
    }
    return $x;
}

sub tmp_out {
    my $tmp;
    for (1..10_000) {
        $tmp = 2 * $_;
        $x = $tmp + $_;
    }
    return $x;
}

sub no_tmp {
    for (1..10_000) { $x = 2 * $_ + $_ }
    return $x;
}

sub base {
    for (1..10_000) { $x += $_ }
    return $x;
}

sub calc { 
    for (1..10_000) { $x += sin sqrt(rand()) }
    return $x;
}         

cmpthese(-10, {
    tmp_in  => sub { tmp_in  },
    tmp_out => sub { tmp_out },
    no_tmp  => sub { no_tmp  },
    base    => sub { base    },        
    calc    => sub { calc    },
});
Run Code Online (Sandbox Code Playgroud)

输出(在v5.16上)

          Rate    calc  tmp_in tmp_out  no_tmp    base
calc     623/s      --    -11%    -26%    -44%    -59%
tmp_in   698/s     12%      --    -17%    -37%    -54%
tmp_out  838/s     34%     20%      --    -25%    -44%
no_tmp  1117/s     79%     60%     33%      --    -26%
base    1510/s    142%    116%     80%     35%      --

所以它们不同,显然是循环中的声明成本.但是tmp版本在列表中.而且,这通常只是开销,所以它被夸大了.还有其他方面 - no_tmp例如,在一个语句中运行.只有当您的处理主要是迭代时,这些事情才有意义.仅生成(高质量)伪随机数是昂贵的.

这也可能在不同的硬件和软件版本上(疯狂地)不同.我在更好的机器上使用v5.10的结果有点不同.将样本"计算"替换为您的处理,并在实际硬件上运行,以获取是否重要的​​相关度量.