Customizing code
 
 
How to express custom parallel forms
Custom parallelism exploitation patterns can be expressed in Muskel by writing macro data flow graphs and embedding the graphs in a ParCompute object. ParCompute is a subclass of the Compute class. Besides the (unused, in this case) Object compute(Object) method, it provides a MdfGraph getMdfGraph() and the constructor requires and MdfGrpah as a parameter. Therefore, users willing to express their own parallelism exploitation patterns can prepare their own MDF graphs, embed it into a ParCompute object and use that object to implement the program to be submitted to the muskel Manager for the computation.
 
How to express MdfGraphs
MdfGraphs are graphs of connected Mdfi, that is Macro Data Flow Instructions. Mdfi can be built using the constructor of the class requiring the parameters:
 
  1. 1. Manager m: the manager used to run the program
  2. 2. int instrId: the instruction identifier
  3. 3. Compute opCode: the code to be computed by the instruction
  4. 4. int inCount: the number of input tokens
  5. 5. int outCount: the number of output tokens
  6. 6. Dest [] dests: the vector of Destination for the output tokens.
 
Each Dest is created passing to the constructor the position within the input tokens of the dest instruction, the id of the dest instruction and the id of the graph. Tokens directed to the output stream have a Mdfi.NoInstrId value in the destination instruction id field. While constructing graphs, the graph id values have to be set as Mdfi.NoGraphId. This will be changed with an actual id when the graph is instantiated upon arrival of a new input task on the program input stream.
 
Declaring the Managers
In case users want to declare their own macro data flow graphs, manager should be used to store the graphs and therefore declared before the actual program is built. The sequence used to declare the manager is therefore the following:
  1. 1.    declare the Manager using the costructor without arguments
           
    Manger mgr = new Manager();
  2. 2.    use the manager to store the graphs, as an example as in:
            
    manager.setProgram(pgm);
  3. 3.    provide InputManager and OutputManager
           
    manager.setInputManager(...); manager.setOutputManager(...);
  4. 4.    provide the manager the contract
            
    manager.setContract(new ParDegree(nw));
At this point you can run the program issuing a compute statement
        manager.compute();
 
Sample code building a MdfGraph
The following code shows how to build a simple two instructions graph:
 
Compute inc1 = new Inc();
Dest d = new Dest(0, 2 ,Mdfi.NoGraphId);
Dest[] dests = new Dest[1];
dests[0] = d;
Mdfi i1 = new Mdfi(manager,1,inc1,1,1,dests);
Compute sq1 = new Square();
Dest d1 = new Dest(0,Mdfi.NoInstrId, Mdfi.NoGraphId);
Dest[] dests1 = new Dest[1];
dests1[0] = d1;
Mdfi i2 = new Mdfi(manager,2,sq1,1,1,dests1);
MdfGraph graph = new MdfGraph();
graph.addInstruction(i1);
graph.addInstruction(i2);
ParCompute main = new ParCompute(graph);
 
Providing new skeletons
In case the user finds new MDF graphs useful to the implementation of a class of applications, he can provide some new Compute class implementing the new forms and use it freely in his muskel programs. The run time environment will deploy performance comparable to the performances achieved using standard muskel skeletons, provided the grain of the MDFi used in the program is not too fine.