in reply to Re^4: Refactoring: Better Variable Names For Better Understanding? [SOLVED]
in thread Refactoring: Better Variable Names For Better Understanding? [SOLVED]
Update: Finalized code, small changes.
Update: Added MCE + Inline::C example.
Solutions allowing one to run with or without threads for comparing against the shootout demonstration. The fastest time posted at the Computer Language Benchmarks site is 19.77 seconds. Perl + MCE + Inline::C runs 10 times faster.
Testing was done on a Core i7 (Haswell 4 Cores with HT at 2.6 GHz / 1600 MHz memory).
$ time perl mandelbrot1.pl 16000 > m1.pbm real 8m38.383s ( Perl code by Mykola Zubach, threads only ) $ time perl mandelbrot2.pl 16000 > m2.pbm real 3m52.245s ( MCE supporting threads and processes ) $ time perl mandelbrot3.pl 16000 > m3.pbm real 1.974s ( MCE + Inline::C, mind boggling )
# http://benchmarksgame.alioth.debian.org/u64q/performance.php?test=ma +ndelbrot # based on Perl code contributed by Mykola Zubach # parallelization via MCE by Mario Roy use strict; use warnings; use MCE::Flow; use constant MAXITER => 50; use constant LIMIT => 4.0; use constant XMIN => -1.5; use constant YMIN => -1.0; use constant WHITE => "\000"; use constant BLACK => "\001"; my ( $w, $h, $m, $invN ); sub draw_line { my ( $mce, $y, $chunk_id ) = @_; my ( $Cr, $Zr, $Zi, $Tr, $Ti ); my $Ci = $y * $invN + YMIN; my $line; LOOP: for my $x (0 .. $w - 1) { $Cr = $x * $invN + XMIN; $Zr = $Zi = $Tr = $Ti = 0.0; 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 LOOP; } } $line .= BLACK; } MCE->gather( $chunk_id, pack('B*', $line) ); } ## MAIN() $w = $h = shift || 200; $m = int( $h / 2 ); $invN = 2 / $w; # Compute upper-half only, gather lines my %picture = mce_flow_s { chunk_size => 1 }, \&draw_line, 0, $m; # Output PBM image header # Output upper half # Remove first and last lines # Output bottom half in reverse binmode STDOUT; print "P4\n$w $h\n"; print @picture{ sort { $a <=> $b } keys %picture }; delete @picture{ 1, $m + 1 }; print @picture{ sort { $b <=> $a } keys %picture };
Below, code using MCE + Inline::C for extra performance.
# http://benchmarksgame.alioth.debian.org/u64q/performance.php?test=ma +ndelbrot # based on Perl code contributed by Mykola Zubach # parallelization via MCE + Inline::C by Mario Roy use strict; use warnings; use MCE::Flow; use Inline 'C' => Config => CCFLAGSEX => '-O2'; use Inline 'C' => <<'END_C'; #define MAXITER 50 #define LIMIT 4.0 #define XMIN -1.5 #define YMIN -1.0 #define WHITE "\000" #define BLACK "\001" int width; double invN; void c_init( int _width, double _invN ) { width = _width; invN = _invN; } SV* c_draw_line( int y ) { SV *line = newSVpvn( "", 0 ); double Ci, Cr, Zr, Zi, Tr, Ti; int x, j; Ci = (double) y * invN + YMIN; x = -1; LOOP: do { if ( ++x >= width ) break; Cr = (double) x * invN + XMIN; Zr = Zi = Tr = Ti = 0.0; for (j = 1; j <= MAXITER; j++) { Zi = Zi * 2.0 * Zr + Ci; Zr = Tr - Ti + Cr; Ti = Zi * Zi; Tr = Zr * Zr; if (Tr + Ti > LIMIT) { sv_catpvn( line, WHITE, 1 ); goto LOOP; } } sv_catpvn( line, BLACK, 1 ); } while ( 1 ); return sv_2mortal( line ); } END_C my ( $w, $h, $m, $invN ); sub draw_line { my ( $mce, $y, $chunk_id ) = @_; my $line = c_draw_line( $y ); MCE->gather( $chunk_id, pack('B*', $line) ); } ## MAIN() $w = $h = shift || 200; $m = int( $h / 2 ); $invN = 2 / $w; # Init C c_init( $w, $invN ); # Compute upper-half only, gather lines my %picture = mce_flow_s { chunk_size => 1 }, \&draw_line, 0, $m; # Output PBM image header # Output upper half # Remove first and last lines # Output bottom half in reverse binmode STDOUT; print "P4\n$w $h\n"; print @picture{ sort { $a <=> $b } keys %picture }; delete @picture{ 1, $m + 1 }; print @picture{ sort { $b <=> $a } keys %picture };
|
---|