SALSA provides a great support for parallel and distributed programming. Its support for code and data mobility and asynchronous message passing makes programming for distributed systems a natural task. Its coordination model provides an attractive feature for parallel programming where multiple CPUs need to coordinate and communicate between themselves in an efficient manner. SALSA depends on Java, hence it inherits Java’s powerful feature of portability across different platforms. All of this makes SALSA an attractive language for both distributed and parallel programming.
This application approximates the integral of a function over an interval [a, b] by using the trapezoidal approximation. The application solves this approximation through parallelism by dividing the approximation into several intervals. Different worker actors are started and migrated to different theaters. They all compute the integral approximation in parallel and send their results to bootstrapping actor. This latter collects the results from all the worker actors, adds them up, and displays the final result to the end user. The application consists of two behaviors: the Trap behavior, which implements the bootstrapping actor and the TrapWorker behavior, which implements the worker actors.
- Edit the theater config file. The default file is theatersFile.txt. Add host name with port number to that file.
- Start theaters at each host specifying in theatersFile.txt
- Execute demo.Trap:
java demo.Trap <iteration> <left point> <right point> <# of trapezoids> <# of actors> <nameserver> <theater file>
- Download Trap.salsa
- Download TrapWorker.salsa
- Download theatersFile.txt
module demo;
import java.io.*;
import java.util.*;
/* Trap.salsa -- Parallel Trapezoidal Rule
*
* Input: Optinal. a and b, the left and right endpoints of the integral. n the number of trapezoids.
* Output: Estimate of the integral from a to b of f(x)
* using the trapezoidal rule and n trapezoids.
*
* Algorithm:
* 1. Each actor calculates "its" interval of
* integration.
* 2. Each actor estimates the integral of f(x)
* over its interval using the trapezoidal rule.
* 3a. Each actor sends its results to the main actor.
* 3b. The main actor sums the calculations received from
* the individual actors and prints the result.
*
* Note: f(x) is hardwired.
*
*/
behavior Trap{
int noActors = 2; // The number of actors
double a = 0.0; // Left endpoint
double b = 1.0; // Right endpoint
int n = 1024; // Number of trapezoids
long initialTime; // Starting Time
String nameServer = "jupiter.wcl.cs.rpi.edu"; // Name Server
String theatersFile = "theatersFile.txt"; // File containing the theaters
void act(String args[]){
int argc = args.length;
if(argc>=1) a=Double.valueOf(args[0]).doubleValue();
if(argc>=2) b=Double.valueOf(args[1]).doubleValue();
if(argc>=3) n=Integer.parseInt(args[2]);
if(argc>=4) noActors=Integer.parseInt(args[3]);
if(argc>=5) nameServer=args[4];
if(argc>=6) theatersFile = args[5];
DistributeWork()@displayResults(token)@endTimer();
}
Double DistributeWork(){
Double h = new Double((b-a)/n); // Trapezoid base length
Integer local_n = new Integer((int) (n/noActors)); // Number of trapezoids for
Double local_a; // Left endpoint my process
Double local_b; // Right endpoint my process
//create actors and assign data
TrapWorker[] workers = new TrapWorker[noActors];
for (int i=0; i<noActors; i++){
workers[i] = new TrapWorker();
}
// read available theaters
Vector theaters = new Vector();
String theater;
try {
BufferedReader in = new BufferedReader(new FileReader(theatersFile));
while ((theater = in.readLine())!= null){
theaters.add(theater);
}
in.close();
} catch (IOException ioe){
standardOutput<-println("[error] Can't open the file "+theatersFile+" for reading.");
}
// migrate actors to theaters
for (int i=0; i<noActors; i++){
standardOutput<-println("Sending actor "+
"uan://"+nameServer+":3030/a"+i+" to "+
"rmsp://"+theaters.get(i%theaters.size())+"/a"+i);
workers[i] = new TrapWorker() at
(new UAN("uan://"+nameServer+":3030/a"+i),
new UAL("rmsp://"+theaters.get(i%theaters.size())+"/a"+i)
);
}
//start computation
standardOutput<-println(">>>>>>Starting the computation");
initialTime = System.currentTimeMillis();
join{
for (int i=0;i<noActors;i++){
/* Length of each actor's interval of
* integration = local_n*h. So my interval
* starts at: */
local_a = new Double(a + i*local_n.doubleValue()*h.doubleValue());
local_b = new Double(local_a.doubleValue() + local_n.doubleValue()*h.doubleValue());
workers[i]<-trap(local_a, local_b, local_n, h);
}
}@addUpIntegrals(token)@currentContinuation;
}
void endTimer(){
long finalTime = System.currentTimeMillis();
long runningTime = finalTime - initialTime;
standardOutput<-println("Running time for Trapezoidal" +
" approximation is "+runningTime+" ms.");
}
Double addUpIntegrals(Object[] results){
//rceives the integral calculated from each actor's work
double total = 0.0;
for (int i = 0; i<results.length; i++){
total += ((Double) results[i]).doubleValue();
}
return new Double(total);
}
void displayResults(Double result){
standardOutput<-println("With n = "+n+" trapezoids, our estimate of the integral on ("+a+","+b+") ="+
result.doubleValue()+ "with error "+ (result.doubleValue() - 1.0e0));
}
}
module demo;
import java.io.*;
/* TrapWorker.salsa --
* Worker for Parallel Trapezoidal Rule
*/
behavior TrapWorker{
Double trap(Double local_a ,Double local_b,Integer local_n ,Double h) {
//integral = (f(local_a) + f(local_b))/2.0;
token f_local_a = f(local_a);
token f_local_b = f(local_b);
token integral = startIntegral(f_local_a, f_local_b);
double x = local_a.doubleValue();
for (int i = 1; i <= local_n.intValue()-1; i++, x+=h.doubleValue()) {
//x = add(x,h);
token f_x = f(new Double(x));
integral = add(integral, f_x); //x = x + h; integral = integral + f(x);
}
multiply(integral, h)@currentContinuation;
}
Double f(Double d) {
double dv = d.doubleValue();
return new Double(5*dv*dv*dv*dv);
}
Double add(Double d, Double f){
double dv = d.doubleValue();
double fv = f.doubleValue();
return new Double(dv+fv);
}
Double multiply(Double d, Double f){
double dv = d.doubleValue();
double fv = f.doubleValue();
return new Double(dv*fv);
}
Double startIntegral(Double d, Double f){
return new Double((d.doubleValue()+f.doubleValue())/2.0);
}
}
return to the salsa home page