0

ハッシュのハッシュを共有する 1 つの方法は、次のようにすべてのレベルのハッシュを宣言することです。

my %hash : shared;
$hash{test} = &share({});

しかし、第 1 レベルのキーの量を予測できない場合や、多すぎてすべてを宣言できない場合はどうでしょう。

以下のコードのように:

#!/usr/bin/perl -w
use strict;
use threads;
use threads::shared;

my %counts :shared;
my $infile = $ARGV[0];
open my $inf, "$infile";

while(my $inline = <$inf>){
    chomp($inline);
    my @entry = split(/\t/,$inline);
    my $t = threads->create('WORK',@entry)->join;
}

foreach my $i(sort {$a cmp $b} keys %counts){
    foreach my $j(sort {$a cmp $b} keys %{$counts{$i}}){
        print "$i\t$j\t$counts{$i}{$j}\n";
    }
}

sub WORK{
    my @work = @_;
    $counts{$work[0]}{$work[1]}++;
}

そしてテストセット:

apple   pie
banana  icecream
orange  juice
mango   juice
mango   pie
mango   pie
......

スクリプトは、「SOME 行の共有スカラーの値が無効です」という警告によって停止します。%counts と %{$counts{KEY1}} の両方を共有する方法はありますか? テスト セットの列 1 で観察する果物の数と種類がわからない場合、出力は次のようになります。

apple    pie      1
banana   icecream 1
mango    juice    1
mango    pie      2
orange   juice    1
4

1 に答える 1

1

スクリプトでは、自動生存に依存しています。ハッシュと配列は、一度参照されると、すぐに存在します。これは通常は機能します。あなたがそうするときはそうではありませんuse threads(自動活性化されたデータ構造はデフォルトでは共有されません)。必要に応じて、自分でサブハッシュを作成するだけです。これはあなたのWORKサブになります

sub WORK{
  unless (exists $counts{$_[0]}) {
    my %anon :shared;
    $counts{$_[0]} = \%anon;
  }
  $counts{$_[0]}{$_[1]}++;
}

また

sub WORK { ($counts{$_[0]} //= do{my %a :shared; \%a})->{$_[1]}++ }

または類似。@_また、配列のかなり役に立たないコピーを削除しました。

あなたの例はスレッド化さえ必要としないことに注意してください。あなたがするので

my $t = threads->create('WORK',@entry)->join;

これはほぼ正確に同等です

my $t = WORK(@entry);

また、スレッドオブジェクトではなくjoin、スレッドの戻り値(この場合、最後のステートメントの値であるため、増分前のカウント)を返します。

于 2012-10-11T21:46:05.677 に答える