Finally, a version using shared variables ($r, $g, $b) provided by MCE::Shared to be released with MCE 1.7 supporting processes and threads. This completes in 8.743 seconds.
The fast option to MCE::Shared applies to deep data structures and okay to enable for this demonstration from not having circular references. Deep data sharing is fully automatic. Thus, one is not having to run shared_clone as in the previous post.
use strict;
use warnings;
use MCE::Flow;
use MCE::Shared fast => 1;
my $r = mce_share [];
my $g = mce_share [];
my $b = mce_share [];
my ($m, $n, $count_max) = (500, 500, 2000);
my ($x_max, $x_min, $y_max, $y_min) = (
1.25, -2.25, 1.75, -1.75
);
#--------------------------------------------------------------------#
# Perl version of Mandelbrot_OpenMP by John Burkardt.
# http://people.sc.fsu.edu/~jburkardt/c_src/mandelbrot_openmp/
# mandelbrot_openmp.html
#
# Carry out the iteration for each pixel, determining count.
sub mandelbrot
{
my ($m1, $m2) = @_;
my ($x, $x1, $x2, $y, $y1, $y2);
my ($c, %count, $i, $j, $k);
for $i ( $m1 .. $m2 ) {
for $j ( 0 .. $n - 1 ) {
$x = ( ( $j - 1 ) * $x_max
+ ( $m - $j ) * $x_min )
/ ( $m - 1 );
$y = ( ( $i - 1 ) * $y_max
+ ( $n - $i ) * $y_min )
/ ( $n - 1 );
$count{$i}{$j} = 0;
$x1 = $x;
$y1 = $y;
for $k ( 1 .. $count_max ) {
$x2 = ( $x1 * $x1 ) - ( $y1 * $y1 ) + $x;
$y2 = 2 * $x1 * $y1 + $y;
if ( $x2 < -2.0 || 2.0 < $x2 || $y2 < -2.0 || 2.0 < $y2 )
{
$count{$i}{$j} = $k;
last;
}
$x1 = $x2;
$y1 = $y2;
}
if ( ( $count{$i}{$j} % 2 ) == 1 ) {
$r->[$i][$j] = 255;
$g->[$i][$j] = 255;
$b->[$i][$j] = 255;
}
else {
$c = int(
255.0 * sqrt(sqrt(sqrt($count{$i}{$j} / $count_max)))
);
$r->[$i][$j] = $g->[$i][$j] = 3 * $c / 5;
$b->[$i][$j] = $c;
}
}
}
return;
}
#--------------------------------------------------------------------#
# Return the smaller of two numbers.
sub min
{
$_[0] < $_[1] ? $_[0] : $_[1];
}
# Write image to an ASCII PPM file.
sub write_to_ppm
{
my ($ofile) = @_;
my ($FH, $i, $j, $jlo, $jhi);
my $re = $r->export; # work is completed, okay to export
my $ge = $g->export;
my $be = $b->export;
open $FH, '>', $ofile or die "cannot open file ($ofile): $!\n";
print $FH "P3\n";
print $FH "$n $m\n";
print $FH "255\n";
for ( $i = 0; $i < $m; $i++ ) {
for ( $jlo = 0; $jlo < $n; $jlo += 4 ) {
$jhi = min( $jlo + 4, $n );
for ( $j = $jlo; $j < $jhi; $j++ ) {
printf $FH " %d %d %d",
$re->[$i][$j], $ge->[$i][$j], $be->[$i][$j]
}
print $FH "\n";
}
}
close $FH;
}
#--------------------------------------------------------------------#
# The bounds_only option applies to sequence of numbers
# which means to compute the begin and end boundaries only,
# not the numbers in between. Thus, workers receive 2
# numbers in @{ $chunk_ref }.
# Same as mce_flow_s { mce options }, sub { ... }, 0, $m - 1;
MCE::Flow::run_seq( {
chunk_size => 5, max_workers => 'auto', bounds_only => 1
}, sub {
my ($mce, $chunk_ref, $chunk_id) = @_;
mandelbrot( @{ $chunk_ref} );
}, 0, $m - 1 );
# Write image to an ASCII PPM file.
write_to_ppm('mandelbrot.ppm');
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.