Perl根据计数将哈希分成相等的部分并发送以并行执行
Perl divide hash into equal parts based on count and send for Parallel execution
我有一个散列(%hash
),其中包含节点列表和需要为各个节点执行的命令。
在此之前,我有一个主机列表(@alive_hosts
),它应该在哪个主机上执行。
这是我的代码:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my @alive_hosts = qw/10.0.0.1 10.0.0.2/;
print Dumper(\@alive_hosts);
my %hash = (
'Node1' => 'cmd1 | cmd2 | cmd3',
'Node2' => 'cmd2 | cmd3',
'Node3' => 'cmd4 | cmd1',
'Node4' => 'cmd1',
'Node5' => 'cmd2',
'Node6' => 'cmd1 | cmd2',
'Node7' => 'cmd3 | cmd4',
);
print Dumper(\%hash);
my $num_buckets = scalar @alive_hosts;
print "num_buckets:$num_buckets\n";
my $no_of_nodes = scalar keys %hash;
my $per_bucket = int( $no_of_nodes / $num_buckets );
print "per_bucket:$per_bucket\n";
my $num_extras = $no_of_nodes % $num_buckets;
print "num_extras:$num_extras\n";
我想根据活动主机的数量来划分此哈希 (%hash
),哈希应该被划分。以便将其分发到每个主机。
在上面的例子中,
Host1(10.0.0.1
) 应包含:
'Node1' => 'cmd1 | cmd2 | cmd3',
'Node2' => 'cmd2 | cmd3',
'Node3' => 'cmd4 | cmd1',
'Node4' => 'cmd1'
Host2(10.0.0.2
) 应包含:
'Node5' => 'cmd2',
'Node6' => 'cmd1 | cmd2',
'Node7' => 'cmd3 | cmd4'
以上 2 个值可以保存在新哈希中,我需要从那里执行一个 shell 脚本,将以上值(即 Node 和 cmds)作为参数并行传递。要并行执行此操作,我正在考虑使用 Parallel::Loops
或 Parallel::ForkManager
。任何 idea/suggestions 将不胜感激。
您已经计算出每个新哈希中需要多少个节点。所以你可以从大哈希中得到一个键列表,并且每次循环时 slice()
那个数字。
像这样:
#!/usr/bin/perl
use strict;
use warnings;
use 5.20; # For the new hash slices
use feature 'say';
use Data::Dumper;
my @alive_hosts = qw/10.0.0.1 10.0.0.2/;
print Dumper(\@alive_hosts);
my %hash = (
'Node1' => 'cmd1 | cmd2 | cmd3',
'Node2' => 'cmd2 | cmd3',
'Node3' => 'cmd4 | cmd1',
'Node4' => 'cmd1',
'Node5' => 'cmd2',
'Node6' => 'cmd1 | cmd2',
'Node7' => 'cmd3 | cmd4',
);
print Dumper(\%hash);
my $no_of_nodes = scalar keys %hash;
my $num_buckets = scalar @alive_hosts;
my $per_bucket = int( $no_of_nodes / $num_buckets );
$per_bucket++ if $no_of_nodes % $num_buckets;
my @keys = keys %hash;
my %node_hash;
for (1 .. $num_buckets) {
my @newkeys = splice @keys, 0, $per_bucket;
$node_hash{$alive_hosts[$_ - 1]} = { %hash{@newkeys} }; # New hash slice syntax
}
say Dumper \%node_hash;
注意: 我使用新的(ish)(自 Perl 5.20 起)%hash{...}
哈希切片语法。如果您使用的是早期版本的 Perl,则需要调整该行。
看看您是否认为下一种方法可以接受
use strict;
use warnings;
use feature 'say';
use Data::Dumper;
my @alive_hosts = qw/10.0.0.1 10.0.0.2/;
print Dumper(\@alive_hosts);
my %hash = (
'Node1' => 'cmd1 | cmd2 | cmd3',
'Node2' => 'cmd2 | cmd3',
'Node3' => 'cmd4 | cmd1',
'Node4' => 'cmd1',
'Node5' => 'cmd2',
'Node6' => 'cmd1 | cmd2',
'Node7' => 'cmd3 | cmd4',
);
print Dumper(\%hash);
my %dispatch;
my @hosts;
while( my($node,$cmd) = each %hash ) {
@hosts = @alive_hosts unless @hosts;
my $host = shift @hosts;
$dispatch{$host}{$node} = $cmd;
}
say Dumper(\%dispatch);
输出
$VAR1 = [
'10.0.0.1',
'10.0.0.2'
];
$VAR1 = {
'Node1' => 'cmd1 | cmd2 | cmd3',
'Node4' => 'cmd1',
'Node6' => 'cmd1 | cmd2',
'Node5' => 'cmd2',
'Node3' => 'cmd4 | cmd1',
'Node7' => 'cmd3 | cmd4',
'Node2' => 'cmd2 | cmd3'
};
$VAR1 = {
'10.0.0.1' => {
'Node6' => 'cmd1 | cmd2',
'Node1' => 'cmd1 | cmd2 | cmd3',
'Node3' => 'cmd4 | cmd1',
'Node2' => 'cmd2 | cmd3'
},
'10.0.0.2' => {
'Node4' => 'cmd1',
'Node5' => 'cmd2',
'Node7' => 'cmd3 | cmd4'
}
};
我有一个散列(%hash
),其中包含节点列表和需要为各个节点执行的命令。
在此之前,我有一个主机列表(@alive_hosts
),它应该在哪个主机上执行。
这是我的代码:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my @alive_hosts = qw/10.0.0.1 10.0.0.2/;
print Dumper(\@alive_hosts);
my %hash = (
'Node1' => 'cmd1 | cmd2 | cmd3',
'Node2' => 'cmd2 | cmd3',
'Node3' => 'cmd4 | cmd1',
'Node4' => 'cmd1',
'Node5' => 'cmd2',
'Node6' => 'cmd1 | cmd2',
'Node7' => 'cmd3 | cmd4',
);
print Dumper(\%hash);
my $num_buckets = scalar @alive_hosts;
print "num_buckets:$num_buckets\n";
my $no_of_nodes = scalar keys %hash;
my $per_bucket = int( $no_of_nodes / $num_buckets );
print "per_bucket:$per_bucket\n";
my $num_extras = $no_of_nodes % $num_buckets;
print "num_extras:$num_extras\n";
我想根据活动主机的数量来划分此哈希 (%hash
),哈希应该被划分。以便将其分发到每个主机。
在上面的例子中,
Host1(10.0.0.1
) 应包含:
'Node1' => 'cmd1 | cmd2 | cmd3',
'Node2' => 'cmd2 | cmd3',
'Node3' => 'cmd4 | cmd1',
'Node4' => 'cmd1'
Host2(10.0.0.2
) 应包含:
'Node5' => 'cmd2',
'Node6' => 'cmd1 | cmd2',
'Node7' => 'cmd3 | cmd4'
以上 2 个值可以保存在新哈希中,我需要从那里执行一个 shell 脚本,将以上值(即 Node 和 cmds)作为参数并行传递。要并行执行此操作,我正在考虑使用 Parallel::Loops
或 Parallel::ForkManager
。任何 idea/suggestions 将不胜感激。
您已经计算出每个新哈希中需要多少个节点。所以你可以从大哈希中得到一个键列表,并且每次循环时 slice()
那个数字。
像这样:
#!/usr/bin/perl
use strict;
use warnings;
use 5.20; # For the new hash slices
use feature 'say';
use Data::Dumper;
my @alive_hosts = qw/10.0.0.1 10.0.0.2/;
print Dumper(\@alive_hosts);
my %hash = (
'Node1' => 'cmd1 | cmd2 | cmd3',
'Node2' => 'cmd2 | cmd3',
'Node3' => 'cmd4 | cmd1',
'Node4' => 'cmd1',
'Node5' => 'cmd2',
'Node6' => 'cmd1 | cmd2',
'Node7' => 'cmd3 | cmd4',
);
print Dumper(\%hash);
my $no_of_nodes = scalar keys %hash;
my $num_buckets = scalar @alive_hosts;
my $per_bucket = int( $no_of_nodes / $num_buckets );
$per_bucket++ if $no_of_nodes % $num_buckets;
my @keys = keys %hash;
my %node_hash;
for (1 .. $num_buckets) {
my @newkeys = splice @keys, 0, $per_bucket;
$node_hash{$alive_hosts[$_ - 1]} = { %hash{@newkeys} }; # New hash slice syntax
}
say Dumper \%node_hash;
注意: 我使用新的(ish)(自 Perl 5.20 起)%hash{...}
哈希切片语法。如果您使用的是早期版本的 Perl,则需要调整该行。
看看您是否认为下一种方法可以接受
use strict;
use warnings;
use feature 'say';
use Data::Dumper;
my @alive_hosts = qw/10.0.0.1 10.0.0.2/;
print Dumper(\@alive_hosts);
my %hash = (
'Node1' => 'cmd1 | cmd2 | cmd3',
'Node2' => 'cmd2 | cmd3',
'Node3' => 'cmd4 | cmd1',
'Node4' => 'cmd1',
'Node5' => 'cmd2',
'Node6' => 'cmd1 | cmd2',
'Node7' => 'cmd3 | cmd4',
);
print Dumper(\%hash);
my %dispatch;
my @hosts;
while( my($node,$cmd) = each %hash ) {
@hosts = @alive_hosts unless @hosts;
my $host = shift @hosts;
$dispatch{$host}{$node} = $cmd;
}
say Dumper(\%dispatch);
输出
$VAR1 = [
'10.0.0.1',
'10.0.0.2'
];
$VAR1 = {
'Node1' => 'cmd1 | cmd2 | cmd3',
'Node4' => 'cmd1',
'Node6' => 'cmd1 | cmd2',
'Node5' => 'cmd2',
'Node3' => 'cmd4 | cmd1',
'Node7' => 'cmd3 | cmd4',
'Node2' => 'cmd2 | cmd3'
};
$VAR1 = {
'10.0.0.1' => {
'Node6' => 'cmd1 | cmd2',
'Node1' => 'cmd1 | cmd2 | cmd3',
'Node3' => 'cmd4 | cmd1',
'Node2' => 'cmd2 | cmd3'
},
'10.0.0.2' => {
'Node4' => 'cmd1',
'Node5' => 'cmd2',
'Node7' => 'cmd3 | cmd4'
}
};