Parallel extension language Linda
hp-linda : A free High Performance implementation of the parallel extension
language Linda for Amoeba. (Linda ia a registered trademark of Scientific Computing Associates) |
#include "linda.h" errstat linda_init(char
*pname); int Linda_worker_id; LINDA_MASTER(master func); errstat out( char *tuple_mask,
... ); errstat linda_init_ts(); errstat out_ts( char *tsname, char *tuple_mask, ... ); errstat in_ts( char *tsname, char *tuple_mask, ... ); errstat rd_ts( char *tsname, char *tuple_mask, ... ); |
Linda
is a parallel coordination language developed largely by the Linda Group |
- 2 - The Linda model is a parallel programming model
which uses a so called global |
Tuples |
('myarraydata',intarr,100,200) are represented by a list of argument fields of various types, for example |
strings, integers, integer arrays, floats and so on.
Tuples are managed by the Tuple server,
a seperate process.
They consist of only six functions, those being:
outproduces a tuple inpconsumes a
tuple if available evalexecutes a
function in a subprocess |
OUT operation * Generates a data (passive) tuple * Each field is evaluated and put into the tuple space * Control is then returned to the invoking program * Example: dim1=100 out('array data',dim1,dim2) |
IN operation |
- 3 - |
* Uses
a template (or anti tuple) to retrieve a tuple from the tuple
space. * Once retrieved, it is taken out of the tuple
space and no longer available * If no matching tuple is found, process will block * Provides for synchronization between processes. * Example: in("arraydata",?dim1,?dim2); in("arraydata",100,?dim2); The (integer) variables contain the values dim1=100 and dim2=200. RD operation * Uses a template to copy data without removing it
from the tuple space. * Once read it is still available for others. * If no matching tuple is found, process will block. * Example: rd("arraydata",?dim1,?dim2); rd("arraydata",?dim1,200); The (integer) variables contain the values dim1=100 and dim2=200. |
In order for a template to match a tuple:
* Have to have the same number of fields * Actuals must have the same type, length and
values as those in |
- 4 - * Formals in the template must match type and
length of corresponding * Example: The tuple matches with the templates (anti tuples): ("string",100,?int array(100)) but not with ("string",111,?int array(100)) |
In hp-linda, there are
some restrictions to the generic Linda modell.
First, no eval operation exists. This
operation was replaced by the linda_spawn
function.
All linda operations are performed with a single Tuple
Space server linda[U].
But several different tuple spaces can exist in parallel, each with its own
tuple
space server. Each tuple space has a uniq name from which the server port
is
derivate.
Hp-linda is a pure library
implementation. Therefore, an additional tuple mask
string is needed for each tuple operation to determine the
type of a tuple
argument. It's always the first argument of a linda operation. More details
in the
Programming Interface.
Only the blocking operations are implemented. Because the
hp-linda interface
can be used concurrently by many threads (up to TS_MAX_THREADS ) in one program, there is no
need for the non blocking counterparts and polling abuse is
avoided.
In an IN operation, all aggregates (arrays) are treated always as formals!
HP-Linda supports operations in different tuple spaces
within the same program
(distributed tuple space).
- 5 -
There are two possible cases to perform linda's master/worker modell: 1. All sub parts are splitted in different programs and started by hand: - One
Master program 2. The
Master and Worker functions are glued in one program, and only 1. Simple Linda Master/Worker modell Before the Linda interface can be used, the user
must choose a unique tuple linda -n "mylinda" To prepare the client interface, both in the worker
and the master program, you errstat where pname is
the above chosen tuple space name. From this name string, a 2. All in One Linda Master/Worker modell Only one program must be compiled and started. The
master and worker int This function needs the argc
and argv arguments from the program |
- 6 -
1. Scan the command line arguments.
2. Decide if it was called by the master or worker.
Master:
3. Call linda_scan_pooldir() to get a list of
available hosts used for worker
spawning and for the linda tuple
space server. If no one is specified, use
the users default run server
(DEFAULT_POOLDIR).
4. Call linda_init() to perform initial client setup.
5. Call linda_checkpoint_init() to initialize the process checkpointing.
6. Start linda
tuple space server either on user specified host or a host
selected from the host pool list
(with linda_find_next_host()). Except
in
the case the command line
argument "-s -" exists: no server will be
started.
7. Call the master function specified with LINDA_MASTER().
Worker:
3. Do initial linda client setup, call linda_init().
4. Call the
desired worker function, specified by LINDA_FUNC()
and the
command line
arguments
-f
<function name>
-w <worker
id>
The behaviour of linda_main is mainly controlled by the arguments given to the
program command line. Those are:
- 7 -
The master function to be called must be declared with LINDA_MASTER(<Master function name>); before the linda_main() call appears! |
LINDA_FUNC(<Worker function name>);
A typical linda program prototype:
int
main(int argc,char
**argv)
{ |
||||
LINDA_FUNC(myworker); |
||||
} void |
mymaster(int argc,char **argv)
{ |
||||
... |
||||
} |
myworker()
{
} |
.... |
The master function gets the pointer argument array argv of all user arguments, given after the
option "--" and argc reflects the number
of user arguments.
- 8 -
Somewhere in the master control function, the worker programs can be started
with |
|||
errstat |
Linda_spawn starts a new process, and
the worker function funcname will be |
int Linda_worker_num; The worker can retrieve his identity number from the global variable int Linda_my_id; The first worker get the id number 0. The master
program get the ownership of |
errstat
out(tuple_mask,...) |
errstat
in(tuple_mask,...)
char
*tuple_mask
errstat
rd(tuple_mask,...)
char
*tuple_mask
The IN/RD tuple space operations are performed in blocking
mode. If no
matching tuple is available, the operation blocks untill a matching tuple
arrives, or an interrupt (User interrupt) occured.
- 9 -
Additionally to the single tuple space model, it's possible
to use several different |
errstat |
errstat errstat Tsname is the user chosen name for the specific tuple space. |
For the multi tuple space there are different initialization functions:
All initiation is done by the the function
int
linda_main_ts(argc,argv)
int argc; |
In the main() function of the program, the user must specify all tuple space names with
LINDA_TS("tsname");
The One-in-all program must be started without the "-n
<tsname>" option, of
course! Linda_main_ts() is responsible
to start all specified linda tuple space
servers, except in the case the program was started with the "-s -"
option.
- 10 -
And the simple init routine for the multi space needs no argument:
errstat |
typedef char |
Linda_char; |
The tuple mask argument is needed because the types of the following arguments can't be determined on runtime.
The tuple mask can contain the following identifiers:
1. Scalar actuals (data arguments in an Out or In/Rd operation)
- 11 -
2. Aggregate (array) actuals (data arguments only in Out operation)
The array pointer argument must follow an integer value/variable with the size in type units, not in bytes!
3. Scalar formals (question fields)
All formals arguments must be pointers of course.
4. Aggregate formals (arrays)
- 12 -
The
array pointer argument is followed by an integer with the size in
type units. ("%s %d %d *F:d","mystring",n,m,myarr,mysize) Some constants: TS_MAX_DIM : maximal argument number (20) |
Because the linda parser can only determine the tuple
argument type from the |
Parallel calculation of the PI constant with random numbers.
1. Simple Linda Master/Worker modell The master program master_pi /* |
- 13 -
*
Calculate the Constant PI with random numbers and the
distributed
* Linda
parallel interface: |
* (x,y) values.
* We generate with a (high
quality) radom generators
positive values
* in the range 0 .. 1 for each
x- and y-coordinate and count
* the numbers of generated
random pairs with "allcalc":
* |
(pos_x,pos_y) |
|||
* |
allcalc++ |
* We got a 2-dim vector with the length sqrt(rad):
*
*
rad=pos_x^2+pos_y^2
*
* Now we construct a circle of
unit radius in the x-y-plane.
* All points with rad<=1.0
are located within this circle.
We
* count
these points with pi_hit. |
* random
point hits in the cirle area is 1/4. #include "linda.h" int |
Linda_int loopcount; double pi_calc; int maxclients; |
int |
i; |
- 14 - |
char *linda; if(argc!=4) |
} |
exit(1); |
linda=argv[1]; |
} |
exit(1); |
/*
maximal (x,y) point calculation of all workers */ loopcount=100000; printf("master_pi: maxcounts=%d
maxclients=%d\n", /* init the linda client interface */ /* put the worker ids in the tuple space */ /* put the maxcount/loopcount values in the tuple space |
||
*/ |
||
out("%s %d","maxcount",maxcount); /* put an initial allcalc and pi_hit variable in the |
tuple space */
out("%s %d","allcalc",allcalc); /* wait untill all workers finished */ |
- 15 -
}; |
printf("master_pi: worker %d finished\n",myid); |
/* collect the results */
in("%s
?%d","allcalc",&allcalc); /*
and collcect our remains */ pi_calc=(pi_hit*1.0)/(allcalc*1.0)*4.0; printf("master_pi: Result: allcalc=%d pi_hit=%d |
allcalc,pi_hit,pi_calc); |
|||
} |
Must be be started by hand (N times): ax -m <host> worker_pi #include "linda.h" /* we use an own random generator version */ extern Linda_double rand_val01(); |
seed); |
extern Linda_int rand_rand(); |
void hit(); int |
char *linda;
Linda_int randinit;
- 16 -
if(argc!=2) /* init linda client interface */ /* init random generator */ /* call the real worker */ return 0; |
||
} void |
||
int mypass=0; Linda_double pos_x,pos_y,rad; /* get the maxcount and the loopcount values
from /* get my id number */ printf("worker_pi(%d): maxcount=%d
loopcount=%d\n", while(allcalc < maxcount) |
} |
- 17 - for(i=0;i<loopcount;i++) in("%s ?%d","allcalc",&allcalc); printf("worker_pi(%d): Pass=%d\n",myid,mypass); |
/* okay, we're finished; add our indoor count to the
* global
variable pi_hit printf("worker_pi(%d): finished. indoor
hits=%d\n", in("%s ?%d","pi_hit",&pi_hit); /* tell the master we're finished */ |
|||
}; |
pi_all -n
"mypilinda" -N 4 -v \ #include "linda.h" int |
main(argc,argv) LINDA_FUNC(worker); |
- 18 - |
LINDA_MASTER(master); linda_main(argc,argv); |
|||
} void |
master(argc,argv) |
Linda_int
loopcount; int i; if(argc!=1) |
Linda_my_name,Linda_my_name);
} |
return; |
/*
maximal (x,y) point calculation of all workers */ loopcount=maxcount/100; printf("master_pi: maxcounts=%d
maxclients=%d\n", /* start the workers */ /* put the maxcount/loopcount values in the tuple space |
||
*/ |
||
out("%s
%d","maxcount",maxcount); |
- 19 -
/* put an inital allcalc and pi_hit variable in
* the
tuple space
*/
allcalc=0;
pi_hit=0;
out("%s %d","allcalc",allcalc);
out("%s %d","pi_hit",pi_hit);
/* wait
untill all workers finished */
printf("master_pi: waiting for
worker...\n");
for(finished=0;finished<Linda_worker_num;finished++)
{ |
|||
in("%s
?%d","finished",&myid); |
|||
}; |
/* collect
the results */ /*
and collcect our remains */ if(allcalc!=0) printf("master_pi: Result: allcalc=%d pi_hit=%d |
allcalc,pi_hit,pi_calc);
return;
} /* we use our own random generator version */ extern Linda_double rand_val01(); |
seed); |
extern Linda_int rand_rand(); Linda_int maxcount; void hit(); void |
{ |
- 20 - |
||||||
char |
*linda; |
printf("worker %d started...\n",Linda_worker_id); /* init random generator */ /* call the real worker */ return; |
||
} void |
||
int mypass=0; Linda_double pos_x,pos_y,rad; /* get the maxcount and the loopcount values
from myid=Linda_worker_id; printf("worker_pi(%d): maxcount=%d
loopcount=%d\n", while(allcalc < maxcount) |
} |
- 21 - |
} |
/*
get the allcalc variable value and add in("%s
?%d","allcalc",&allcalc); printf("worker_pi(%d): Pass=%d\n",myid,mypass); |
/* okay, we're finished; add our indoor count to the
* global
variable pi_hit printf("worker_pi(%d): finished. indoor
hits=%d\n", in("%s
?%d","pi_hit",&pi_hit); /* tell the master we're finished */ return; |
|||
}; |
#include "linda.h" #define PICALC "picalc" |
"picalc" |
||
#define RESULT "result" int LINDA_TS(PICALC); |
"result" |
- 22 -
LINDA_TS(RESULT); linda_main_ts(argc,argv); |
|||
} void |
master(argc,argv) |
Linda_int
loopcount; int i; if(argc!=1) |
Linda_my_name,Linda_my_name);
} |
return; |
/*
maximal (x,y) point calculation of all workers */ loopcount=maxcount/100; printf("master_pi: maxcounts=%d
maxclients=%d\n", /* start the workers */ /* put the maxcount/loopcount values in the tuple space |
||
*/ |
||
out_ts(PICALC,"%s
%d","maxcount",maxcount); /* put an inital allcalc and pi_hit variable in the |
tuple space */
allcalc=0;
pi_hit=0;
- 23 -
out_ts(RESULT,"%s
%d","allcalc",allcalc);
out_ts(RESULT,"%s %d","pi_hit",pi_hit);
/* wait
untill all workers finished */
printf("master_pi: waiting for
worker...\n");
for(finished=0;finished<Linda_worker_num;finished++)
{ |
|||
in_ts(RESULT,"%s
?%d","finished",&myid); |
|||
}; |
/* collect
the results */ /*
and collcect our remains */ if(allcalc!=0) printf("master_pi: Result: allcalc=%d pi_hit=%d |
allcalc,pi_hit,pi_calc);
return;
} /* we use an own random generator version */ extern Linda_double rand_val01(); |
seed); |
extern Linda_int rand_rand(); Linda_int maxcount; void hit(); void |
char |
*linda; |
printf("worker %d started...\n",Linda_worker_id);
/* init
random generator */
- 24 - randinit=-rand_rand()/1000; /* call the real worker */ return; |
||
} void |
||
int mypass=0; Linda_double pos_x,pos_y,rad; /* get the maxcount and the loopcount values
from myid=Linda_worker_id; printf("worker_pi(%d): maxcount=%d
loopcount=%d\n", while(allcalc < maxcount) in_ts(RESULT,"%s
?%d","allcalc",&allcalc); |
- 25 -
} |
printf("worker_pi(%d): Pass=%d\n",myid,mypass); |
/* okay, we're finished; add our indoor count to the
* global
variable pi_hit printf("worker_pi(%d): finished. indoor
hits=%d\n", in_ts(RESULT,"%s
?%d","pi_hit",&pi_hit); /* tell the master we're finished */ return; |
||||
}; |
1. "p4-Linda: A Portable Implementation of Linda", R.M. Butler et al. 2. "Design and Implementation of a Tuple-Space
Server for Java CSC 9020", 3. "Glenda Installation and Use", B.R. Seyfarth et al. 3. "Linda Tutorial", SCA (www.sca.com) |
linda[U] , linda_cap[U]
- 26 - Tuple space server |
Linda
- high performance Linda tuple space server for Amoeba's HP- |
linda -n <tuple space name> [-v]
The
tuple space server linda is the
central point of the design of the Fundamentals The tuple space server service incoming tuple
operation requests. The |
each dimension:
All tuples of the same dimension, that means argument number, belong to
the
same subspace N. The tuple server manage all subspaces with a |
- 27 -
All tuple from
a subspace are further divided in signature domains, that
means all tuples with the same
type signature, for example
[string,int,int,intp] are merged
in the same signature domain:
All
subdomains of one specific dimension (argumnet number) are put Searching To find a matching tuple (for example an IN
operation with a template To speed up this search, a byte checksum for each
scalar tuple argument To avoid specification limitations in the tuple
server, no hash search was Client-Server Communication The server port will be created from a user choosen
tuple space name. |
- 28 - avoid server abuse, the private field od the server
and public capability |
-n "tsname" To
make client and server communication to be possible, the tuple -v |
Special administartion is not needed. Usually, the linda
server will be lindacap -n "mytuplespace" -c "tscap" |
linda -n "mytuplespace"
linda[L] , lindacap[U]