How to parallelize Java/C# translation of COBOL programs: an example
SoftwareMining COBOL to java/C# translations are thread-safe and can be used in multi-threaded applications.
In this section we will review how to use the SoftwareMining API to launch several instances of a Batch program, and organise it break up the job in between them.
Launcing processes in multi-threaded mode
The API makes it very easy to start the application in multi-threaded mode.
For example, the standard way to launch a single intance of the translated program from command line would be:
>java SMLauncher com.packagename.ReportTotals
The following change launches three instances of the altered program (running in 3 threads) from the command-line:
Here the thread management will is managed by SoftwareMining framework.
Parallizing code: A Java Example
The following is a simple batch program which loops through a sub-total calculation process – where most of the time is spent.
Allocating multiple threads to parallelize the loop will result in significant performance enhancements.
On each iteration, the subtotal returned are added together into commData.total variable.
On completion of the iteration the "writeReport" method is invoked to write out the figure
into commData.total . Ie "writeReport" has a dependency on variable commData.total .
public class ReportTotals extends BaseService {
CommData commData = new CommData(this);
int start = 0;
int end = 10;
@Override
public void startUp () {
iterate();
writeReport();
}
public void iterate () {
for (int i = start; i < end; i++) {
commData.setCounter(i);
calculate();
}
}
public void calculate () {
// call a different program to calculate next sub-total ==================================
BaseService calculator = ServicesFactory.create("com.sm.parallel.SubTotalCalculator", this);
calculator.execute(commData);
// the above calculation has placed the result in : commData.getSubtotal()
// ======================================================================================== commData.setTotal( commData.getTotal() + commData.getSubtotal());
}
public void writeReport () {
// generate the report
System.out.println( " ============================================== ");
System.out.println( " total : " + commData.getTotal());
System.out.println( " ============================================== ");
super.goBack();
}
}
The following is the program adjusted to use 3 con-current threads to gain a 3x performance improvements.
Note the following:
A new method has been introduced for allocation of work into each instance (see allocateWorkToInstances)
The sum of all subtotals is now collected in the shared (static) variable totalForAllInstances , instead of the instance specific commData.total.
The system waits for all three instances to complete their iteration (using awaitBarrier() method) before invoking the "writeReport" method.
The "writeReport" method is now executed only on one (first) instance of the program as only one report is required. This instance copies the data from the variable shared by all instances (totalForAllInstances) to the current commData.total and then generate the simple report.
public class ReportTotals extends BaseService {
static Integer totalForAllInstances = 0; // Manually introduced
CommData commData = new CommData(this);
int start = 0;
int end = 10;
@Override
public void startUp () {
allocateWorkToInstances();// Manually introduced
iterate();
this.awaitBarrier(); // Wait for all instances to finish before writing the Report
writeReport();
}
// Manually introduced methodpublic void allocateWorkToInstances () {
// ========================================
// It is anticipated 3 instances will be launched. Split the work between each instance
switch (this.retrieveInstanceNumber() ) {
case 0:
start = 0; end = 3; break;
case 1:
start = 3; end = 7; break;
case 2:
start = 7; end = 10; break;
}
// ========================================
}
public void iterate () {
for (int i = start; i < end; i++) {
commData.setCounter(i);
calculate();
}
}
public void calculate () {
// call a different program to calculate next sub-total ==================================
BaseService calculator = ServicesFactory.create("com.sm.parallel.SubTotalCalculator", this);
calculator.execute(commData);
// the above calculation has placed the result in : commData.getSubtotal()
// ========================================================================================
// Manual adjustments: use the static "totalForAllInstances" variable
// commData.setTotal(commData.getTotal() + commData.getSubtotal());totalForAllInstances = totalForAllInstances + commData.getSubtotal();
}
public void writeReport () {
// Manual adjustment: produce a report ONLY for the first instance
if (this.isFirstInstance())
{
// Manual adjustment: copy information from the static "totalForAllInstances" variable, commData.setTotal( totalForAllInstances );
// generate the report
System.out.println( " ============================================== ");
System.out.println( " total : " + commData.getTotal());
System.out.println( " ============================================== ");
}
super.goBack();
}
}