I'm trying to implement a median filter for a 1D array filled with floating point numbers using the fork join framework. I've managed to do it sequentially and my parallel version is outputting values it's just that each time its ran it outputs different values, for instance when printing out the first element of the filtered array I will get -0.178966 and after running it again I'll get -0.168073, and so on and so forth. I think this could be a race condition of some sort or perhaps I'm overlooking something or doing something wrong in my main class. Either way, I hope that one of you can maybe help me, I'm new to parallel programming and don't fully understand it yet, so please bear with me. Thank you. (ignore commented out code in main class)
My main class and some other relevant code:
static final ForkJoinPool fjPool = new ForkJoinPool();
static void F(int fs,double[] nums, double[] ans)
{
fjPool.invoke(new TFilter(fs,nums,0,nums.length,ans));
}
public static void main(String[] args)
{
//note program requires user to enter file name, ask for filter size, and
//write to file with name being asked by program.
//Scanner scn = new Scanner(System.in);
// System.out.println("Enter name of file to be read from:");
//String rfn = scn.nextLine();
//System.out.println("Enter name of file to write to:");
//String wfn = scn.nextLine();
//System.out.println("Enter median filter size: ( must be odd and in range [3,21] )");
//int fs = Integer.parseInt(scn.nextLine());
double[] ss = read("sampleinputfile.txt"); //read fills array with input values
double[] a = new double[ss.length];
F(3,ss,a);
System.out.println(a[0]);
}
My parallel class:
import java.util.*;
import java.util.concurrent.RecursiveAction;
public class TFilter extends RecursiveAction
{
int lo;
int hi;
int fSize;
double [] arr;
double [] ans;
static final int SEQUENTIAL_CUTOFF = 500;
TFilter(int fs, double[] ar, int l, int h, double[] an)
{
this.fSize = fs;
this.arr = ar;
this.lo = l;
this.hi = h;
this.ans = an;
}
public double median(double[] a)
{
Arrays.sort(a);
double m;
if (a.length % 2 == 0)
{
m = ( a[a.length/2] + a[a.length/2 - 1])/2;
}
else
{
m = a[a.length/2];
}
return m;
}
public void MF()
{
double[] Arr = new double[hi-lo];
int cnt = 0;
for (int i = lo; i < hi; i++)
{
Arr[cnt] = arr[i];
cnt++;
}
int m = (Arr.length-fSize)+1;
List<Double> med = new ArrayList<>();
double[] win = new double[fSize];
for (int i = 0; i < m; i++)
{
int c = i;
for (int j = 0; j < fSize; j++)
{
win[j] = Arr[c];
c++;
}
med.add(median(win));
}
int x = (Arr.length-m)/2;
for (int i = 0; i < x; i++) //first boundry points
{
ans[i] = Arr[i];
}
int c = 0;
for (int i = x; i < Arr.length-x; i++)
{
ans[i] = med.get(c);
c++;
}
for (int i = Arr.length-x; i < Arr.length; i++) //last boundry points
{
ans[i] = Arr[i];
}
}
@Override
protected void compute()
{
if((hi-lo) < SEQUENTIAL_CUTOFF)
{
MF();
}
else
{
TFilter left = new TFilter(fSize,arr,lo,(hi+lo)/2,ans);
TFilter right = new TFilter(fSize,arr,(hi+lo)/2,hi,ans);
left.fork();
right.compute();
left.join();
}
}
}