A parallel version of the mandel source using the GD module.
use strict;
use warnings;
use GD;
use MCE::Loop;
# based on original http://www.alfrog.com/mandel.html
# karlgoethebier: code refactor
# marioroy: parallelization
my $width = 1280;
my $height = 1024;
my $image = new GD::Image( $width, $height );
my @palette = $image->colorAllocate( 0, 0, 0 ); # black
my $iterations = 20;
for ( 1 .. $iterations ) {
my ( $r, $g, $b ) = map { int rand 255 } 1 .. 3;
push @palette, $image->colorAllocate( $r, $g, $b );
}
MCE::Loop::init {
use_threads => 0, # Windows default to threads, not thread safe
max_workers => 'auto', bounds_only => 1, gather => sub {
my ( $x, $y, $color );
while ( ($x, $y, $color) = splice(@_, 0, 3) ) {
$image->setPixel( $x, $y, $palette[ $color ] )
}
}
};
mce_loop_s {
my ( $mce, $chunk_ref, $chunk_id ) = @_;
my ( $re_c, $im_c, $re_z, $im_z, $color, $temp );
my ( @set_data );
for my $x ( $chunk_ref->[0] .. $chunk_ref->[1] ) {
for my $y ( 0 .. $height - 1 ) {
$re_c = ( $x - 3 * $width / 4 ) / ( $width / 3 );
$im_c = ( $y - $height / 2 ) / ( $width / 3 );
$re_z = $im_z = $color = 0;
while ( 1 ) {
$temp = $re_z;
$re_z = $re_z * $re_z - $im_z * $im_z + $re_c;
$im_z = 2 * $temp * $im_z + $im_c;
++$color;
last if $re_z * $re_z + $im_z * $im_z > 4;
if ( $color == $iterations ) {
$color = 0;
last;
}
}
push @set_data, $x, $y, $color;
}
}
MCE->gather( @set_data );
} 0, $width - 1;
MCE::Loop::finish;
open my $fh, '>mandelbrot.png' || exit 1;
binmode $fh;
print $fh $image->png;
close $fh;