数据缓慢::随机

时间:2014-09-11 04:48:39

标签: perl

您好我使用 Data::Random 模块生成随机日期,但生成 1百万的样本数据非常慢。如何提高速度呢?这是我尝试过的代码。

#!/usr/bin/perl -w

use Data::Random qw(:all);

my $randDate_Start = '1900-01-01';
my $randDate_End = '2010-12-31';

open Outfile, ">", "D:/Test.txt";

for(0..1000000)
{
     my $randDate = rand_date( min=>$randDate_Start, max=>$randDate_End);
     print Outfile $randDate."\n";
}

close Outfile;

还有其他方法可以生成随机日期

3 个答案:

答案 0 :(得分:2)

我建议使用Time::Piece

如下面的基准所示,它显示性能提高了6倍。

如果您缓存可能的日期值,您可以获得所有100万个值的即时结果:

#!/usr/bin/perl -w
use strict;
use warnings;
use autodie;

use Benchmark;
use Data::Random qw(:all);
use Time::Piece;
use Time::Seconds;

my $randDate_Start = '1900-01-01';
my $randDate_End   = '2010-12-31';

my $tp_start = Time::Piece->strptime( "$randDate_Start 12:00:00", "%Y-%m-%d %T" );
my $tp_end   = Time::Piece->strptime( "$randDate_End 12:00:00",   "%Y-%m-%d %T" );
my $tp_days  = ( $tp_end - $tp_start )->days;

my @tp_cached = map { ( $tp_start + ONE_DAY * $_ )->strftime('%Y-%m-%d') } ( 0 .. $tp_days );

# Compare Data Methods
timethese(
    1_000_000,
    {   'Data::Random'         => sub { rand_date( min => $randDate_Start, max => $randDate_End ) },
        'Time::Piece'          => sub { ( $tp_start + ONE_DAY * int rand $tp_days )->strftime('%Y-%m-%d') },
        'Time::Piece (cached)' => sub { $tp_cached[ rand $tp_days ] },
    }
);

输出:

Benchmark: timing 1000000 iterations of Data::Random, Time::Piece, Time::Piece (cached)...
Data::Random: 61 wallclock secs (60.20 usr +  0.07 sys = 60.27 CPU) @ 16592.00/s (n=1000000)
Time::Piece: 10 wallclock secs ( 9.95 usr +  0.01 sys =  9.96 CPU) @ 100401.61/s (n=1000000)
Time::Piece (cached):  0 wallclock secs ( 0.08 usr +  0.00 sys =  0.08 CPU) @ 12500000.00/s (n=1000000)
            (warning: too few iterations for a reliable count)

答案 1 :(得分:1)

使用@Glenn推荐的第二种技术,没有任何优化

use 5.010;
use strict;
use warnings;
use Date::Calc qw(Delta_Days Add_Delta_Days);

#create an array for each day
my $numdays = Delta_Days(1900,1,1, 2010,12,31) + 1;
my @dates = map { sprintf("%d-%02d-%02d", Add_Delta_Days(1900,1,1, $_)) } 0..$numdays; 

say $dates[ rand($numdays) ] for(1..100_000_000);

运行

$ time perl dat | wc -l
 100000000

real    0m32.227s
user    0m31.439s
sys     0m1.159s

代表100_000_000。 1百万是1.2秒......

答案 2 :(得分:0)

我首先要展开循环。您可能无法将其展开一百万次,但您可以展开大量次并循环少一些。这将有助于加快速度,因为它不必为下一个项目分支。我做了一个简短的测试,它的速度提高了5到10倍。这是我建议的100万循环(如果我的数学正确:))

# Declare the variable before the loop
my $randDate;
# Statement is what we want to execute a number of times
my $statement = "$randDate = rand_date( min=>$randDate_Start, max=>$randDate_End);print Outfile \$randDate.\"\\n\";"
# Replicate the statement 1000 times 
$statement = $statement x 1000;
# Get the time we started (to the second)
my $start = time();
# Loop 1000 times to make a 1 million items
for(0..1000)
{
  # Evaluate the 1000 statements
  eval($statement);
}
# Determine the amount of time it took
my $diff = time() - $start;
# Print out the time
print "Time taken is: $diff\n";

当我这样做时,如果我循环一百万次,则需要107秒,如果我使用上述方法生成一百万个项目,则需要28秒。

如果速度不够,那么您可能需要制定例程来生成日期。考虑到范围,每年将有111年和365.25天,这将是40543日期的范围。这可以在开始时生成一次。您可以使用时间范围的每个日期创建一个数组。然后使用rand,你可以生成一个0到40543之间的数字。这将给你和索引到数组中选择日期。如果上面提供足够的加速,这比上面的工作多一点。