Update: See this post for a faster version. A MCE + Inline::C demonstration is also included.
Parallelism is possible with just one line of code for the next demonstration. As in the previous examples, am using the sequence generator with chunk_size set to 1. Thus, $_ is the next sequence number when specifying chunk_size => 1.
mce_flow_s sub { draw_line($_) }, 0, $h - 1;
Folks will be pleased to know that this will work for non-threads in the upcoming MCE 1.7 release with MCE::Shared. One simply replaces ( use threads; use threads::shared ) with ( use MCE::Shared ) and ( my @picture : shared; ) with ( my @picture : Shared; ). That's all.
The code outputs the image in pbm format.
# synopsis: perl mandelbrot.pl 1024 > image.pbm
#
# https://github.com/nbraud/benchmarksgame/blob/master/bench/
# mandelbrot/mandelbrot.perl
#
# The Computer Language Benchmarks Game
# http://benchmarksgame.alioth.debian.org/
#
# contributed by Mykola Zubach
# shorten by Mario Roy from using MCE
use strict;
use threads;
use threads::shared;
use MCE::Flow chunk_size => 1, max_workers => 'auto';
use constant MAXITER => 50;
use constant LIMIT => 4.0;
use constant XMIN => -1.5;
use constant YMIN => -1;
use constant WHITE => "\0";
use constant BLACK => "\001";
my ($w, $h, $invN);
my @picture : shared;
sub draw_line($) {
my $y = shift;
my $line;
my $Ci = $y * $invN + YMIN;
X:
for my $x (0 .. $w - 1) {
my ($Zr, $Zi, $Tr, $Ti);
my $Cr = $x * $invN + XMIN;
for (1 .. MAXITER) {
$Zi = $Zi * 2 * $Zr + $Ci;
$Zr = $Tr - $Ti + $Cr;
$Ti = $Zi * $Zi;
$Tr = $Zr * $Zr;
if ($Tr + $Ti > LIMIT) {
$line .= WHITE;
next X;
}
}
$line .= BLACK;
}
$picture[$y] = pack 'B*', $line;
}
## MAIN()
$w = $h = shift || 200;
$invN = 2 / $w;
mce_flow_s sub { draw_line($_) }, 0, $h - 1;
binmode STDOUT;
print "P4\n$w $h\n"; # PBM image header
print @picture;
|