The following demonstrations show-case the use of MCE for the spectral-norm benchmark on the web. Both run on Perl compiled without threads support. The MCE::Hobo example largely resembles the threads version by Mykola Zubach.
MCE::Map
# perl spectral-norm.pl 5500
# output: 1.274224153
# The Computer Language Benchmarks Game
# http://benchmarksgame.alioth.debian.org/
#
# Contributed by Andrew Rodland
# modified by R. Jelinek
# multicore by Mykola Zubach
# MCE::Map version by Mario Roy
use strict;
use MCE::Map;
my $n = shift || 500;
my $cpus = 4; ## MCE::Util->get_ncpu() || 4;
MCE::Map->init(
max_workers => $cpus,
chunk_size => int(($n - 1) / $cpus) + 1,
);
my @v = multiplyAtAv(
multiplyAtAv( multiplyAtAv((1) x $n) )
);
my @u = multiplyAtAv(@v);
my ($i, $vBv, $vv) = (0);
for my $v (@v) {
$vBv += $u[$i++] * $v, $vv += $v ** 2;
}
printf "%0.9f\n", sqrt($vBv / $vv);
MCE::Map->finish();
sub multiplyAtAv {
return multiplyAtv(multiplyAv(@_));
}
sub eval_A {
use integer;
my $div = (($_[0] + $_[1]) * ($_[0] + $_[1] + 1) >> 1) + $_[0] + 1
+;
no integer;
1 / $div;
}
sub multiplyAv {
my @data = @_;
return mce_map_s {
my ($i, $sum) = ($_);
$sum += eval_A($i, $_) * $data[$_] for (0 .. $#data);
$sum;
} 0, $#data;
}
sub multiplyAtv {
my @data = @_;
return mce_map_s {
my ($i, $sum) = ($_);
$sum += eval_A($_, $i) * $data[$_] for (0 .. $#data);
$sum;
} 0, $#data;
}
MCE::Hobo
# perl spectral-norm.pl 5500
# output: 1.274224153
# The Computer Language Benchmarks Game
# http://benchmarksgame.alioth.debian.org/
#
# Contributed by Andrew Rodland
# modified by R. Jelinek
# multicore by Mykola Zubach
# MCE::Hobo version by Mario Roy
use strict;
use MCE::Hobo;
my $cpus = 4; ## MCE::Util->get_ncpu() || 4;
my $n = shift || 500;
my @v = multiplyAtAv(
multiplyAtAv( multiplyAtAv((1) x $n) )
);
my @u = multiplyAtAv(@v);
my ($i, $vBv, $vv) = (0);
for my $v (@v) {
$vBv += $u[$i++] * $v, $vv += $v ** 2;
}
printf "%0.9f\n", sqrt($vBv / $vv);
sub multiplyAtAv {
return multiplyAtv(multiplyAv(@_));
}
sub eval_A {
use integer;
my $div = (($_[0] + $_[1]) * ($_[0] + $_[1] + 1) >> 1) + $_[0] + 1
+;
no integer;
1 / $div;
}
sub multiplyAv {
my($begin, $end, @procs);
my $chunk = int($#_ / $cpus) + 1;
for($begin = 0; $begin < $#_; $begin = $end + 1) {
$end = $begin + $chunk;
$end = $#_ if $end > $#_;
push @procs, MCE::Hobo->create( sub {
my $begin = shift;
my $end = shift;
return map {
my ($i, $sum) = ($_);
$sum += eval_A($i, $_) * $_[$_] for (0 .. $#_);
$sum;
} ($begin .. $end);
}, $begin, $end, @_);
}
return map $_->join, @procs;
}
sub multiplyAtv {
my($begin, $end, @procs);
my $chunk = int($#_ / $cpus) + 1;
for($begin = 0; $begin < $#_; $begin = $end + 1) {
$end = $begin + $chunk;
$end = $#_ if $end > $#_;
push @procs, MCE::Hobo->create( sub {
my $begin = shift;
my $end = shift;
return map {
my ($i, $sum) = ($_);
$sum += eval_A($_, $i) * $_[$_] for (0 .. $#_);
$sum;
} ($begin .. $end);
}, $begin, $end, @_);
}
return map $_->join, @procs;
}
Regards, Mario.