Difference between revisions of "Tutorial - Parallel Types"

From Mesham
Jump to navigationJump to search
Line 1: Line 1:
 +
<metadesc>Tutorial describing the use of types for more advanced parallelism in Mesham</metadesc>
 +
'''Tutorial number six''' - [[Tutorial_-_Shared Memory|prev]] :: [[Tutorial_-_Arrays|next]]
 +
 
== Introduction ==
 
== Introduction ==
  

Revision as of 18:27, 19 January 2013

Tutorial number six - prev :: next

Introduction

Up until this point we have been dealing with the default shared memory model of communication. Whilst this is a simple, safe and consistent model it can have a performance penalty associated with it. In this tutorial we shall look at overriding the default communication, via types, to a more message passing style.

A channel

#include <io>
#include <string>

function void main() {
   var a:Int::channel[1,2];
   var b:Int::allocated[single[on[2]]];
   proc 1 {
       a:=23;	
   };	
   proc 2 {
      b:=a;
      print(itostring(b)+"\n");
   };
};

In this example we are using variable a as a channel, between processes 1 and 2. At line 8, process 1 writes the value 23 into this channel and at line 11, process 2 reads that value out of the channel. Note that channels are unidirectional (i.e. process 2 could not write to process 1 in this example.)

Pipes

#include <io>
#include <string>

function void main() {
   var a:Int:: pipe[1,2];
   var b:Int;
   var p;
   par p from 0 to 2 {
      var i;
      for i from 0 to 9 {
         var master:=1;
         var slave:=2;
         if (i%2!=0) {
            master:=2;
            slave:=1;
         };
         if (p==master) a:=i;
         if (p==slave) {
            b:=a;
            print(itostring(p)+": "+itostring(b)+"\n");
         };
      };
   };

};

This code demonstrates using the pipe type for bidirectional point to point communication. If you change the pipe to a channel then you will see that instead, only process 1 may send and only 2 may receive.

Extra parallel control

By default the channel type is a blocking call, we have a number of fine grained types which you can use to modify this behaviour.

#include <io>
#include <string>

function void main() {
   var a:Int::channel[0,1]::nonblocking[];
   var b:Int;
   proc 0 {
      a:=23;
      sync a;	
   };
   proc 1 {
      b:=a;
      sync a;
      print(itostring(b)+"\n");
   };
};

In this code we are using the nonblocking type to override the default blocking behaviour of a channel. The type is connected to the sync keyword such that it will wait at that point for outstanding communication to complete. Try experimenting with the code to understand the differences these types make.

Collective communication

Mesham has a number of collective communication types, here we are just going to consider the reduce and broadcast here.

A broadcast

The broadcast type allows us to explicitly specify that a communication is to involve all processes (in current parallel scope.)

#include <io>
#include <string>

function void main() {
   var a:Int;	
   a::broadcast[2]:=23;
   print(itostring(a)+"\n");
};

In this example we are declaring a to be a normal Int variable, then on line 6 we are coercing the broadcast type with the existing type chain of a just for that assignment and telling the type that process 2 is the root process. The root process is the one that drives the broadcast itself, i.e. here process 2 is sending the value 23 to all other processes. Then on line 7 we are just using a as a normal program variable to display its value. This use of types is actually quite a powerful one; we can append extra types for a specific expression and then after that expression has completed the behaviour is back to what it was before.

A reduction

Another very common parallel operation is to combine values from a number of processes and, applying some operation, reduce this to a resulting value.

#include <io>
#include <string>

function void main() {	
   var p;
   par p from 0 to 19 {
      var a:Int;
      a::reduce[0,"sum"]:=p;
      if (p==0) print(itostring(a)+"\n");
   };
};

This code will combine all of the values of each process's p onto process 0 and sum them all up. Multiple operations are supported and are listed in the reduce type documentation