It takes m iterations to transform the array according to the rule: a[i]=(a[i-1] a[i 1])/2 Also, according to the assignment, I must use Thread and Phaser. Using of Thread and Phaser is mandatory, and there is no way I can refuse to use them.
For transforming I use this code:
package lab3;
import java.util.concurrent.Phaser;
public class Program {
public static void main(String[] args)
{
int n = 100;
int m = 100;
int [] arr;
arr = new int [n];
int [] arr2;
arr2 = new int [n];
for (int i = 0; i<n; i )
{
int r = (int)(Math.random()*50);
arr [i] = r;
arr2 [i] = r;
System.out.print(arr[i] " ");
}
int [] arr3 = arr2.clone();
System.out.println(" ");
for (int p = 0; p<m; p )
for (int i = 1; i<n-1; i )
{
arr [i] = (arr [i-1] arr [i 1])/2;
}
for (int i = 0; i<n; i )
{
System.out.print(arr[i] " ");
}
System.out.println();
Sum.arr = arr2;
Sum.m=m;
Phaser p = new Phaser();
for (int i = 1; i<n-1; i )
{
var x = new Sum (p, i);
x.start();
}
for (int i = 0; i<n; i )
{
System.out.print(Sum.arr[i] " ");
}
System.out.println();
for (int i = 0; i<n; i )
{
if (arr[i]!=Sum.arr[i])
System.out.println("Error! Value is incorrect at position: " i ". Original val is: " arr[i] " Thead val is: " Sum.arr[i] " Before transform is: " arr3[i]);
}
}
}
class Sum extends Thread
{
static int [] arr;
static int m;
Phaser ph;
int i;
public Sum(Phaser p, int i)
{
this.ph = p;
this.i = i;
}
public static synchronized void trans (int i)
{
arr [i]= (arr [i-1] arr [i 1])/2;
}
@Override
public void run ()
{
ph.register();
for (int j = 0; j<m; j )
{
trans(i);
ph.arriveAndAwaitAdvance();
}
ph.arriveAndDeregister();
}
}
However, the results of serial and parallel algorithms are not the same. Please tell me what am I doing wrong?
CodePudding user response:
I can see 2 problems:
- you don't wait for the
Sum
threads to finish before checking the results:Phaser p = new Phaser(); for (int i = 1; i<n-1; i ) { var x = new Sum (p, i); x.start(); } // YOU SHOULD WAIT HERE UNTIL ALL THE STARTED Sum THREADS ARE FINISHED for (int i = 0; i<n; i ) { System.out.print(Sum.arr[i] " "); } System.out.println();
- in
Sum
threads you don't wait forarr[i-1]
andarr[i 1]
to get computed before computingarr[i]
.
Don't forget thatSum.run()
are executed in parallel (because they are executed in different threads), and when some thread computesa[i]
, then there are no guarantees that the other threads have just computed the right iterations ofa[i-1]
anda[i 1]
.
CodePudding user response:
It seems like the question has transformed into:
how can I synchronize Sum.run()? how can I run it serially?
The answer is that you should probably use Phaser for synchronization because:
according to the assignment, I must use Thread and Phaser
You can learn how Phaser works here:
If the above resources aren't clear to you, then I can recommend Java Concurrency in Practice - this book explains concurrency in Java in great details and is ideal for novices in the topic.
Also I would recommend you to check one more time if you understood your assignment correctly.
Because right now (the way you explained it) your assignment looks weird:
- one one hand the algorithm you described cannot be split into parallel subtasks: in order to compute
a[i 1]
we needa[i]
from the same iteration. - on the other hand you should use threads, whose sole purpose is to perform work in parallel
To use threads with an algorithm that can only work sequentially is weird because this way you get only negatives: the program becomes more complicated and its performance decreases.