http://www.perlmonks.org?node_id=445880

I was looking at the latest parrot and saw in the examples, a mandelbrot generator, with the equivalent c source code. So I modified them slightly, and ran them thru 1000 generations. Parrot is fast, but it took 5 times the cpu, and roughly 3 times as long on my machine(Duron 800). It would be interesting to compare it to equivalent perl5 code, and if anyone can convert it, please post it. I'm almost there, but the C for statements are a little complicated for me to convert. :-)

Anyways, here is the code for you to try. I slightly modified the original code, to add timer variables.

################################################# # mandel.pasm ...run with "parrot mandel.pasm" time N10 set I0, 0 loop: set S1, " .:,;!/>)|&IH%*#" set I2, 30 YREDO: # C = y*0.1 - 1.5 set N8, I2 set N9, 0.1 mul N7, N8, N9 set N8, 1.5 sub N7, N7, N8 set I1, 0 XREDO: # c = x*0.04 - 2 set N8, I1 set N9, 0.04 mul N6, N8, N9 set N8, 2.0 sub N6, N6, N8 set N3, 0 set N4, 0 set N1, N6 set N2, N7 set I3, 0 KREDO: # t = z*z - Z*Z + r mul N8, N3, N3 mul N9, N4, N4 sub N5, N8, N9 add N5, N5, N1 # Z = 2*z*Z + i add N4, N4, N4 mul N4, N4, N3 add N4, N4, N2 # z = t set N3, N5 # if (z*z + Z*Z > 10) break; mul N8, N3, N3 mul N9, N4, N4 add N8, N8, N9 gt N8, 10.0, PRINT inc I3 lt I3, 112, KREDO PRINT: mod I4, I3, 16 substr S2, S1, I4, 1 print S2 inc I1 lt I1, 75, XREDO print "\n" dec I2 gt I2, 0, YREDO inc I0 lt I0, 1000, loop print I0 print " count in " time N11 sub N11,N10 print N11 print " seconds\n" END: end ############################################

And the c source

/* mandel.c ... compile with gcc -o mandel mandel.c */ #include <stdio.h> #include <time.h> int main() { int x, y, k, counter; char *b = " .:,;!/>)|&IH%*#"; float r, i, z, Z, t, c, C; time_t begin, end; counter = 0; begin = time (NULL); while(counter < 1000){ for (y=30; puts(""), C = y*0.1 - 1.5, y--;) { for (x=0; c = x*0.04 - 2, z=0, Z=0, x++ < 75;) { for (r=c, i=C, k=0; t = z*z - Z*Z + r, Z = 2*z*Z + i, z=t, k<112 +; k++) if (z*z + Z*Z > 10) break; printf ("%c", b[k%16]); } } counter++; } end = time (NULL); printf ("%d count in %ld secs \n", counter, end - begin); }

I'm not really a human, but I play one on earth. flash japh

Replies are listed 'Best First'.
Re: Parrot vs. C cagematch (Just for fun)
by tilly (Archbishop) on Apr 07, 2005 at 21:57 UTC
    Here is the C translated into Perl in a straightforward way:
    use strict; my ($x, $y, $k, $counter); my @b = split //, " .:,;!/>)|&IH%*#"; my ($r, $i, $z, $Z, $t, $c, $C); my ($begin, $end); my $counter = 0; $begin = time; while($counter < 1000){ for ($y=30; print("\n"), $C = $y*0.1 - 1.5, $y--;) { for ($x=0; $c = $x*0.04 - 2, $z=0, $Z=0, $x++ < 75;) { for ($r=$c, $i=$C, $k=0; $t = $z*$z - $Z*$Z + $r, $Z = 2*$z*$Z + + $i, $z=$t , $k<112; $k++) { last if ($z*$z + $Z*$Z > 10); } printf ($b[$k%16]); } } $counter++; } $end = time; printf ("%d count in %ld secs \n", $counter, $end - $begin);
    Note that this is going to be much slower than both Parrot and C. Without knowing much about Parrot, I'd be surprised if Perl 6 actually gets compiled to Parrot that is as efficient as the handrolled code above.
      Note that this is going to be much slower than both Parrot and C. .. I'd be surprised if Perl 6 actually gets compiled to Parrot that is as efficient as the handrolled code above.

      Yes, on my machine, the perl5 version used double the parrot cpu, and near 75% longer. Maybe Perl6 will do a bit better. It does look like Inline::Parrot could replace Inline::C in some circumstances. Parrot looks easy enough to understand.


      I'm not really a human, but I play one on earth. flash japh

        Actually, there is a Perl6/Pugs version of mandel here. And Autrijus actually used this as his basis for the early Pugs->Parrot compiler. You can read more about it here.

        -stvn
Re: Parrot vs. C cagematch (Just for fun)
by chromatic (Archbishop) on Apr 08, 2005 at 00:43 UTC

    How did you compile Parrot and the C program? By default, Parrot builds without optimizations, and I believe the JIT is off by default too. Both of those will improve its performance.

Re: Parrot vs. C cagematch (Just for fun)
by Joost (Canon) on Apr 07, 2005 at 21:53 UTC
    #!/usr/local/bin/perl -w use strict; my ($x, $y, $k, $counter); my @b = split //, " .:,;!/>)|&IH%*#"; my ($r, $i, $z, $Z, $t, $c, $C); my ($begin, $end); $counter = 0; $begin = time; while ($counter < 1000) { for ($y = 30 ; $C = $y * 0.1 - 1.5, $y--;) { print "\n"; for ($x = 0 ; $c = $x * 0.04 - 2, $z = 0, $Z = 0, $x++ < 75 ;) + { for ( $r = $c, $i = $C, $k = 0 ; $t = $z * $z - $Z * $Z + $r, $Z = 2 * $z * $Z + $i +, $z = $t, $k < 112 ; $k++ ) { last if ($z * $z + $Z * $Z > 10); } print $b[ $k % 16 ]; } } $counter++; } $end = time; printf("%d count in %ld secs \n", $counter, $end - $begin);
    updated: misplaced the counter++ statement.
Re: Parrot vs. C cagematch (Just for fun)
by gellyfish (Monsignor) on Apr 08, 2005 at 14:49 UTC

    This isn't actually equivalent but this is the mandelbrot generator I include as an example in Linux::Svgalib:

    #!/usr/bin/perl -w use strict; use Linux::Svgalib; use vars qw($P @Q $col $row @colours ); my ( $max_iterations, $max_size ) = (512,4); my $screen = Linux::Svgalib->new(); $screen->init(); $screen->setmode(8); my ($XMax,$XMin,$YMax,$YMin) = (1.2,-2.0,1.2,-1.2); my $maxcol = $screen->getxdim(); my $maxrow = $screen->getydim(); my $max_colours = $screen->getcolors(); my $deltaP = ($XMax - $XMin) / $maxcol; my $deltaQ = ($YMax - $YMin) / $maxrow; $Q[0] = $YMax; $screen->clear(); for( 1 .. $maxrow ) { $Q[$_] = $Q[$_ -1] - $deltaQ; } $P = $XMin; for $col ( 0 .. $maxcol -1 ) { for $row ( 0 .. $maxrow - 1) { my ($X,$Y,$XSquare,$YSquare) = (0,0,0,0); my $colour = 1; while (( $colour < $max_iterations ) && (($XSquare + $YSquare ) < $max_size )) { $XSquare = $X * $X; $YSquare = $Y * $Y; $Y *= $X; $Y += $Y + $Q[$row]; $X = $XSquare - $YSquare + $P; $colour++; } $screen->setcolor($colour % $max_colours); $screen->drawpixel($col,$row); } $P += $deltaP; } $screen->getch(); $screen->setmode(TEXT);
    This is quite fast, especially when the exact same algorithm in C used to take nearly a day to render on an Amiga 500

    /J\

Re: Parrot vs. C cagematch (Just for fun)
by tall_man (Parson) on Apr 08, 2005 at 14:17 UTC
    Perl isn't great at this sort of number-crunching application, but you can use C extension modules like PDL to improve performance. There is an example of a fast PDL Mandelbrot here.
Re: Parrot vs. C cagematch (Just for fun)
by spurperl (Priest) on Apr 10, 2005 at 07:40 UTC
    Personally I find it a little sad that Parrot is so much slower than C.

    Thinking on a conceptual level, Parrot shouldn't be much more difficult to translate to machine language efficiently than C, hence I expect it to be at least comparable.

    Granted, C compilers lived through 30 years of optimizations and there probably isn't such a thing in existence for Parrot, yet.

      spurperl,
      I freely admit it has been more than half a year since I followed Parrot development. I can tell you that there is a constant struggle being waged between finishing specs, getting it to work, and speeding it up. More often then not, the optimizations take a back seat. I would like to think the finished product with optimizations and JIT are more closely comparable to C.

      Cheers - L~R