Perl эффективная конкатенация массива в хеш - PullRequest
0 голосов
/ 30 октября 2011
use strict;
use Time::HiRes qw[gettimeofday tv_interval];

my $start_index = int(rand(50))+100;#this value is arbitrary for this discussion
my $duration = 75;#also arbitrary but assume it will always be several times the size of the dataset

my $hash = {};
my @dataset = qw(foo bar baz qux bob joe sue tom);
my $partial = $duration % scalar(@dataset);
my $full = ($duration - $partial) / scalar(@dataset);

my $start = [gettimeofday()];
for my $index (0..$#dataset) {
    my $w = $dataset[$index];
    for (0..$full-1) {
        my $i = $start_index + $index + (scalar(@dataset) * $_);
        $hash->{$i} = $w;
    }
}
print "  full ".tv_interval($start)." secs\n";$start = [gettimeofday()];
for my $index (0..$partial-1) {
    my $w = $dataset[$index];
    my $s = $start_index + $index + (scalar(@dataset) * $full);
    $hash->{$s} = $w;
}
print "  part ".tv_interval($start)." secs\n";$start = [gettimeofday()];

При реализации с ( значительно ) большим набором данных и продолжительностью выполнение вышеуказанной логики в цикле "полный" занимает 60 ~ 120 секунд. Есть ли более эффективный метод достижения тех же результатов?

Edit:
Чтобы дать более точную информацию о размере набора данных, в котором он используется, эта оптимизация производительности предназначена для программы обработки сигналов.

Ответы [ 2 ]

0 голосов
/ 01 ноября 2011

вот решение:

use strict;
use warnings;
use Time::HiRes qw[gettimeofday tv_interval];

sub min ($$) {$_[$_[0] > $_[1]]}

my $start_index = int(rand(50))+100;#this value is arbitrary for this discussion
my $duration = 75;#also arbitrary but assume it will always be several times the size of the dataset

{
    my @dataset = qw(foo bar baz qux bob joe sue tom);
    my $hash = {};
    my $partial = $duration % scalar(@dataset);
    my $full = ($duration - $partial) / scalar(@dataset);

    my $start = [gettimeofday()];
    for my $index (0..$#dataset) {
        my $w = $dataset[$index];
        for (0..$full-1) {
            my $i = $start_index + $index + (scalar(@dataset) * $_);
            $hash->{$i} = $w;
        }
    }
    print "  full: ".tv_interval($start)." secs\n";$start = [gettimeofday()];
    for my $index (0..$partial-1) {
        my $w = $dataset[$index];
        my $s = $start_index + $index + (scalar(@dataset) * $full);
        $hash->{$s} = $w;
    }
    print "  part: ".tv_interval($start)." secs\n";$start = [gettimeofday()];

    #print "$_ => $hash->{$_}\n" foreach (sort {$a <=> $b} keys %$hash);
}

#############
print "\n\n";
#############

{
    my $dataset = [qw(foo bar baz qux bob joe sue tom)];
    my $hash;
    $hash //= {};

    my $remaining = $duration;
    my $phase = 0;#arbitrary
    my $start = [gettimeofday()];
    while (1) {
        last unless $remaining;
        my $chunk_size = min($remaining, scalar(@$dataset) - $phase);
        #print "$chunk_size   ".($start_index+$duration-$remaining)."..".($start_index+$duration-$remaining+$chunk_size-1)."   $phase..".($phase+$chunk_size-1)."\n";
        @{$hash}{($start_index + $duration - $remaining .. $start_index + $duration - $remaining + $chunk_size - 1)} = @{$dataset}[$phase .. $phase + $chunk_size - 1];
        $remaining -= $chunk_size;
        $phase = ($phase + $chunk_size) % scalar(@$dataset);
    }
    print "  time: ".tv_interval($start)." secs\n";$start = [gettimeofday()];

    #print "$_ => $hash->{$_}\n" foreach (sort {$a <=> $b} keys %$hash);
}
0 голосов
/ 30 октября 2011

Похоже, что единственная оптимизация, которую вы можете сделать, - это вычисление скаляра (@dataset) один раз вне цикла:

my $data_set_size = scalar(@dataset);

и внутри цикла:

my $i = floor($start_index + $index + ($data_set_size * $_));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...