Below, a version using shared variables ($r, $g, $b) provided by threads::shared. This completes in 9.730 seconds.
use strict;
use warnings;
use threads;
use threads::shared;
use MCE::Flow;
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
);
my $r = shared_clone [];
my $g = shared_clone [];
my $b = shared_clone [];
for my $i ( 0 .. $m - 1 ) {
$r->[$i] = shared_clone [];
$g->[$i] = shared_clone [];
$b->[$i] = shared_clone [];
}
#--------------------------------------------------------------------#
# 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 ) {
lock $r; # not necessary, but runs faster with locking
$r->[$i][$j] = 255;
$g->[$i][$j] = 255;
$b->[$i][$j] = 255;
}
else {
lock $r; # ditto
$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);
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",
$r->[$i][$j], $g->[$i][$j], $b->[$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.