Difference between revisions of "Mandelbrot"

From Mesham
Jump to navigationJump to search
m (14 revisions imported)
 
(7 intermediate revisions by the same user not shown)
Line 1: Line 1:
 +
<metadesc>Mesham is a type oriented programming language allowing the writing of high performance parallel codes which are efficient yet simple to write and maintain</metadesc>
 
== Overview ==
 
== Overview ==
  
Line 19: Line 20:
 
== Source Code ==
 
== Source Code ==
  
  var pnum:=4; // number of processes to run this on
+
#include <io>
  var hxres:=1000;
+
#include <string>
  var hyres:=1000;
+
 +
typevar pixel::=record["r",Int,"g",Int,"b",Int];
 +
 +
  var pnum:=16; // number of processes to run this on
 +
  var hxres:=512;
 +
  var hyres:=512;
 
  var magnify:=1;
 
  var magnify:=1;
 
  var itermax:=1000;
 
  var itermax:=1000;
var pixel:record["r",Int,"g",Int,"b",Int];
 
var mydata:array[pixel,hxres,hyres] :: allocated[row[] :: horizontal[pnum] :: single[evendist[]]];
 
var s:array[pixel,hxres,hyres] :: allocated[single[on[0]]];
 
 
   
 
   
  var p;
+
  function Int iteratePixel(var hy:Float, var hx:Float) {
par p from 0 to pnum - 1
+
    var cx:Double;
{
+
    cx:=((((hx / hxres) - 0.5) / magnify) * 3) - 0.7;
  var hy;
+
    var cy:Double;
  for hy from (mydata#p).low to (mydata#p).high
+
    cy:=(((hy / hyres) - 0.5) / magnify) * 3;
  {
+
    var x:Double;
    var hx;
+
    var y:Double;
    for hx from 1 to hxres
+
    var iteration;
    {
+
    for iteration from 1 to itermax {
      var cx:=((((hx % hxres) - 0.5) % magnify) * 3) - 0.7;
+
       var xx:=((x * x) - (y * y)) + cx;
      var cy:=((((hy + (mydata#p).start) % hyres) - 0.5) % magnify) * 3;
+
      y:= ((2 * x) * y) + cy;
      var x:Double;
+
      x:=xx;
      x:=0;
+
      if (((x * x) + (y * y)) > 100) {
      var y:Double;
+
          return iteration;
      y:=0;
 
      var iteration;
 
      var ts:=0;
 
      for iteration from 1 to itermax
 
       {
 
        var xx:=((x * x) - (y * y)) + cx;
 
        y:= ((2 * x) * y) + cy;
 
        x:=xx;
 
        if (((x * x) + (y * y)) > 100)
 
        {
 
          ts:=iteration;
 
          iteration:=999999;
 
        };
 
 
       };
 
       };
       var red:=0;
+
    };
       var green:=0;
+
    return -1;
       var blue:=0;
+
};
      if (iteration > 999998)
+
       {
+
function void main() {
        blue:=(ts * 10) + 100;
+
    var mydata:array[pixel,hxres,hyres] :: allocated[single[on[0]]];
        red:=(ts * 3) + 50;
+
    var p;
        green:=(ts * 3)+ 50;
+
    par p from 0 to pnum - 1 {
        if (ts > 25)
+
       var tempd:array[record["r",Int,"g",Int,"b",Int], hyres];
        {
+
       var myStart:=p * (hyres / pnum);
          blue:=0;
+
       var hy:Int;
          red:=(ts * 10);
+
      for hy from myStart to (myStart +  (hyres / pnum)) - 1 {
          green:=(ts * 5);
+
          var hx;
        };
+
          for hx from 0 to hxres - 1 {
        if (blue > 255) blue:=255;
+
            var iteration := iteratePixel(hy, hx);
        if (red > 255) red:=255;
+
            tempd[hx]:=determinePixelColour(iteration);
        if (green > 255) green:=255;
+
          };
      };
+
          mydata[hy]:=tempd;
       (((mydata#p)#hy)#hx).r:=red;
+
          sync mydata;
       (((mydata#p)#hy)#hx).g:=green;
+
        };
       (((mydata#p)#hy)#hx).b:=blue;
+
    };
    };
+
    proc 0 {
  };
+
      createImageFile("picture.ppm", mydata);
 +
    };
 +
};
 +
 +
function pixel determinePixelColour(var iteration:Int) {
 +
    var singlePixel:pixel;
 +
    if (iteration > -1) {
 +
       singlePixel.b:=(iteration * 10) + 100;  
 +
      singlePixel.r:=(iteration * 3) + 50;
 +
      singlePixel.g:=(iteration * 3)+ 50;
 +
      if (iteration > 25) {
 +
          singlePixel.b:=0;
 +
          singlePixel.r:=(iteration * 10);
 +
          singlePixel.g:=(iteration * 5);
 +
        };
 +
        if (singlePixel.b > 255) singlePixel.b:=255;
 +
        if (singlePixel.r > 255) singlePixel.r:=255;
 +
        if (singlePixel.g > 255) singlePixel.g:=255;
 +
    } else {
 +
       singlePixel.r:=0;
 +
       singlePixel.g:=0;
 +
       singlePixel.b:=0;
 +
    };
 +
    return singlePixel;
 
  };
 
  };
  s:=mydata;
+
   
  proc 0
+
  function void createImageFile(var name:String, var mydata:array[pixel,hxres,hyres]) {
{
+
    var file:=open(name,"w");
  var fname:="picture.ppm";
+
    writestring(file,"P6\n# CREATOR: LOGS Program\n");
  var fil:=openfile[fname,"w"]; // open file
+
    writestring(file,itostring(hyres));
  // generate picture file header
+
    writestring(file," ");
  writetofile[fil,"P6\\n# CREATOR: LOGS Program\\n"];
+
    writestring(file,itostring(hxres));
  writetofile[fil,1000];
+
    writestring(file,"\n255\n");
  writetofile[fil," "];
+
    // now write data into the file
  writetofile[fil,1000];
+
    var j;
  writetofile[fil,"\\n255\\n"];
+
    for j from 0 to hyres - 1 {
  // now write data into the file
+
      var i;
  var j;
+
      for i from 0 to hxres - 1 {
  for j from 0 to hyres - 1
+
          writebinary(file,mydata[j][i].r);
  {
+
          writebinary(file,mydata[j][i].g);
    var i;
+
          writebinary(file,mydata[j][i].b);
    for i from 0 to hxres - 1
+
        };
    {
+
    };
      var f:=((s#j)#i).r;
+
    close(file);
      writechartofile[fil,f];
 
      f:=((s#j)#i).g;
 
      writechartofile[fil,f];
 
      f:=((s#j)#i).b;
 
      writechartofile[fil,f];
 
    };
 
  };
 
  closefile[fil];
 
 
  };
 
  };
 +
 +
''This code is compatible with Mesham version 1.0 and later''
  
 
== Notes ==
 
== Notes ==
Line 117: Line 124:
 
== Download ==
 
== Download ==
  
You can download the Mandelbrot example [http://www.mesham.com/downloads/mandle.mesh here]
+
You can download the Mandelbrot example [http://www.mesham.com/downloads/mandle.mesh here] or a legacy Mesham 0.5 version [http://www.mesham.com/downloads/mandle-0.5.mesh here]
 +
 
 +
[[Category:Example Codes]]

Latest revision as of 15:44, 15 April 2019

Overview

Mandelbrot in Mesham

The mandlebrot example will compute the Mandlebrot set over any number of processes. This is a set of points in the complex plane, the boundary of which forms a fractal. The mathematics, which are quite simple, behind the Mandlebrot computation really do not matter for our purposes. The important issue is that firstly the calculation is embrasingly parallel (i.e. simple and natural to parallelise) and secondly will produce an image which the user can identify with.

The algorithm itself is actually quite simple, with a relatively large proportion of it dealing with specific colourisation of the resulting fractal. The example on this page is purposly basic so that the potential programmer can understand it.


Performance

Mandelbrot Performance Evaluation, Mesham against C-MPI

The Mandelbrot example was evaluated against one written in C-MPI on a super computing cluster. Below is the graph detailing the performance of such codes, due to the close performance of the codes when run on an initial number of processors was the same and as such not shown. Due to the embarrassingly parallel nature of this problem the advantages of using Mesham in terms of performance do not start to stand out until a large number of processors is reached.


Source Code

#include <io>
#include <string>

typevar pixel::=record["r",Int,"g",Int,"b",Int];

var pnum:=16; // number of processes to run this on
var hxres:=512;
var hyres:=512;
var magnify:=1;
var itermax:=1000;

function Int iteratePixel(var hy:Float, var hx:Float) {
   var cx:Double;
   cx:=((((hx / hxres) - 0.5) / magnify) * 3) - 0.7;
   var cy:Double;
   cy:=(((hy / hyres) - 0.5) / magnify) * 3;
   var x:Double;
   var y:Double;
   var iteration;
   for iteration from 1 to itermax {
      var xx:=((x * x) - (y * y)) + cx;
      y:= ((2 * x) * y) + cy;
      x:=xx;
      if (((x * x) + (y * y)) > 100) {
         return iteration;
      };
   };
   return -1;
};

function void main() {
   var mydata:array[pixel,hxres,hyres] :: allocated[single[on[0]]];
   var p;
   par p from 0 to pnum - 1 {
      var tempd:array[record["r",Int,"g",Int,"b",Int], hyres];
      var myStart:=p * (hyres / pnum);
      var hy:Int;
      for hy from myStart to (myStart +  (hyres / pnum)) - 1 {
         var hx;
         for hx from 0 to hxres - 1 {
            var iteration := iteratePixel(hy, hx);
            tempd[hx]:=determinePixelColour(iteration);
         };
         mydata[hy]:=tempd;
         sync mydata;
       };
   };
   proc 0 {
      createImageFile("picture.ppm", mydata);
   };
};

function pixel determinePixelColour(var iteration:Int) {
   var singlePixel:pixel;
   if (iteration > -1) {
      singlePixel.b:=(iteration * 10) + 100; 
      singlePixel.r:=(iteration * 3) + 50;
      singlePixel.g:=(iteration * 3)+ 50;
      if (iteration > 25) {
         singlePixel.b:=0;
         singlePixel.r:=(iteration * 10);
         singlePixel.g:=(iteration * 5);
       };
       if (singlePixel.b > 255) singlePixel.b:=255;
       if (singlePixel.r > 255) singlePixel.r:=255;
       if (singlePixel.g > 255) singlePixel.g:=255;
   } else {
      singlePixel.r:=0;
      singlePixel.g:=0;
      singlePixel.b:=0;
   };
   return singlePixel;
};

function void createImageFile(var name:String, var mydata:array[pixel,hxres,hyres]) {
   var file:=open(name,"w");
   writestring(file,"P6\n# CREATOR: LOGS Program\n");
   writestring(file,itostring(hyres));
   writestring(file," ");
   writestring(file,itostring(hxres));
   writestring(file,"\n255\n");
   // now write data into the file
   var j;
   for j from 0 to hyres - 1 {
      var i;
      for i from 0 to hxres - 1 {
         writebinary(file,mydata[j][i].r);
         writebinary(file,mydata[j][i].g);
         writebinary(file,mydata[j][i].b);
       };
   };
   close(file);
};

This code is compatible with Mesham version 1.0 and later

Notes

To change the number of processes, edit pnum. In order to change the size of the image edit hxres and hyres. The mandlebrot set will calculate up until itermax for each point, by increasing this value you will get a crisper image (but it will take much more time!) Lastly, the variable magnify will specify the magnification of the image - the value of 1 will generate the whole image and by increasing this image the computation is directed into working on a specific area in more detail.

Note: This example will produce an image in the Portable PixMap format (PPM), viewers of these on Unix based systems are easy to come by (i.e. eye of gnome) but on Windows are slightly more difficult. Windows users might want to rewrite some of the last bit on process 0 so that a BitMaP is created.

Download

You can download the Mandelbrot example here or a legacy Mesham 0.5 version here