multithreading with ability to suspend/continue calculations - java

I am writing Java program which allows me to get the geometric center of random-generated 2-dimensional points. I want the calculations to be done by custom number of threads. I want to suspend/continue calculations at any time. Unfortunately, my code doesn't work, It seems like run() is never executed. Here is what I got:
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
System.out.println("running... " + Thread.currentThread().getName());
PointInterface p = pg.getPoint(); // getting random point(x,y)
pointCount++;
int[] pos = p.getPositions(); // getting (x,y)
System.out.println(pos[0] + ", " + pos[1] + " k");
sumxy[0] += pos[0];
sumxy[1] += pos[1];
geometricCenter[0] = (double) sumxy[0] / pointCount;
geometricCenter[1] = (double) sumxy[1] / pointCount;
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("exception caught in run()");
return;
}
}
}
Setting number of threads:
public void setNumberOfThreads(int threads) {
threadsList.clear();
for (int i = 0; i < threads; i++) {
threadsList.add(new Thread());
}
}
Starting the calculations:
public void start() {
try {
for (Thread t : threadsList) {
t.start();
}
} catch (Exception e) {
System.out.println("start() exception caught");
}
}
Suspending calculations:
public void suspendCalculations() {
try {
Thread.sleep(1200);
} catch (InterruptedException e) {
System.out.println("SuspendCalculations() exception caught");
}
}
Resuming calculations:
I don't exactly know what I'm supposed to do here. Should I create new set of Threads like that?
public void continueCalculations() {
int x = threadsList.size();
threadsList.clear();
for (int i = 0; i < x; i++) {
threadsList.add(new Thread());
threadsList.get(i).start();
}
}
How I run my program:
public static void main(String[] args) {
ParallelCalculations pc = new ParallelCalculations(); // My main class object where run() and all the methods above are declared
PointGenerator g = new PointGenerator(); // class that allows me to generate points
PointInterface a = g.getPoint(); // getting random point
pc.setNumberOfThreads(3);
pc.setPointGenerator(g);
pc.start();
pc.suspendCalculations();
System.out.println(pc.getGeometricCenter()[0] + ", " + pc.getGeometricCenter()[1]);
pc.continueCalculations();
pc.suspendCalculations();
System.out.println(pc.getGeometricCenter()[0] + ", " + pc.getGeometricCenter()[1]);
}
If needed:
Point:
class Point {
public static final int MAX_POSITION = 16;
private int[] positions = new int[2];
Point(int _x, int _y) {
this.positions[0] = _x;
this.positions[1] = _y;
}
public int[] getPositions() {
return positions;
}
}
Point Generator:
class PointGenerator {
private int x = (int) (Math.random() * (Point.MAX_POSITION + 1));
private int y = (int) (Math.random() * (Point.MAX_POSITION + 1));
public PointInterface getPoint() { // Can be called by many Threads at the same time.
return new Point(x, y);
}
}

Your run() should be executed and should do it's thing.
Though there is a far bigger cause for random behaviour in this code: All the threads write to sumxy, geometricCenter and pointCount at he same time without any syncronisation-locks, causing more or less random behaviour. You at least need to implement some kind of synchronisation to prevent simultanious writes.
Maybe start here (Java synchonized tutorial by Oracle) if you have no clue.
But simply adding synchronisation to everything will probably just make it slower than a single thread, you will need some kind of buffer for each thread to work independently and than collect the results when they are suspended.
And now general problems:
A) Your suspendCalculations() doesn't do anything (for 1200ms to be percise). To break the calcualtion you would need to interrupt all the worker-threads since they terminate upon interruption. Call threadsList.get(i).Interrupt() to do so.
B) If you want to to be able to change the number of threads while suspended, this is a way to go. If this is not necessarry, it would be more efficient to create a constant
public static final Object LOCK = new Object();
make all the threads LOCK.wait() on that object, so resuming them is just a call to LOCK.notifyAll().
C) Instead of using your own implementaion of Point you can use java.awt.Point.
D) Returning the coordinates of a point simply in an array is really bad for readability of your code, java.awt.Point has getX() and getY() functions.

Related

Control amount of threads reading a file in java (only using synchronized, wait, notify and sleep)

In the problem I am trying to solve, each thread has to read the whole file, (maybe each thread will deliver its content to another task or any other purpose). After reading it, the thread should sleep a bit then try to read the file again, and only a given number(n) of threads should read the file. My attempt to solve this dealing with controling the amount of threads working is in the code below :
import java.util.*;
class Reader implements Runnable{
Thread t;
Controler c;
public Reader(Controler c){
t = new Thread(this);
this.c = c;
t.start();
}
public void run(){
Random ran = new Random();
int napTime;
while(true){
try{
w.intentarLeerArchivo(t);
//Specification says that each reader
//should wait a bit before trying to
//read the file again
napTime = ran.nextInt(1000);
t.sleep(napTime);
}catch(InterruptedException e){
System.out.println("InterruptedException");
}
}
}
}
class Controler{
Random ran;
LinkedList <Reader> readers;
int n;
int count;
public Controler(int n){
readers = new LinkedList <Reader>();
this.n = n;
count = 0;
ran = new Random();
}
public synchronized void getPermission(){
try{
while(count >= n){
wait();
}
notify();
}catch(InterruptedException e){
System.out.println("InterruptedException");
}
}
public synchronized void increaseCount(){
count++;
}
public synchronized void decreaseCount(){
count--;
System.out.println("There are " + count + " threads reading");
}
public void intentarLeerArchivo(Thread t){
int readTime = 1000;
try{
getPermission();
System.out.println("Thread " + t.getId() +" empezó a leer");
increaseCount();
t.sleep(readTime);
System.out.println("Thread " + t.getId() +" is reading");
System.out.println("Thread " + t.getId() + " finished reading");
decreaseCount();
} catch(InterruptedException e){
System.out.println("InterruptedException");
}
}
}
class Initializer{
int numReaders;
int maxReaders;
public Initializer(int numReaders, int maxReaders){
this.numReaders = numReaders;
this.maxReaders = maxReaders;
}
public void init(){
Controler c = new Controler(maxReaders);
for(int i = 0; i < numReaders; i++){
new Reader(c);
}
}
}
public class FileShare{
public static void main(String [] args){
Initializer c = new Initializer(100, 50);
c.init();
}
}
There are a few lines I wrote in order to debug. They print the state of each thread and the number of threads that are reading whenever one of them ends reading. But when I run the program, it turns out that suddenly there are more Threads reading the file than the ones there were supposed to be doing so. I guess it has something to do with my synchronization manipulation. What am I doing wrong?
When a thread is in the
while(...){wait()}
section of your implementation, it wait until someone notify it to go on. Right now, when you finish waiting, you notify right away.
Think about it, if once I get in I notify someone to come, he will not wait until I'm done before coming in. You want to use notify when you leave the file.

Java [threads] - summarizing table with multiple threads doesn't seem to work

I am learning java, and trying to summarize elements in table with multiple threads, but I am always getting wrong result.
I tried 4 different methods of threads synchronization and all of them failed. Everything is explained in the comments.
My result (bad):
Without threads: 4949937, 15ms
With threads: 4944805, 78ms
Maybe am I executing the System.out.println on summarizeT() too early? I mean before all the threads finish work. With .join() the summarizeT() method works good but. Is the .join() blocking the "main" thread until all other threads are finished?
Main class:
public class Main
{
static int size = 100000; //size of tab
static int length = 100; //each thread gets 100 elements of tab, thread 1 calculates sum from 0 to 99, thread 2 from 100 to 199 etc.
static int[] tab = new int[size];
static Random generator = new Random();
static void initialize()
{
for (int i = 0; i < size; i++)
tab[i] = generator.nextInt(100);
}
static int summarize() //summarize with only one thread
{
int sum = 0;
for (int i = 0; i < size; i++)
sum += tab[i];
return sum;
}
static int summarizeT() //summarize with more threads (size / length)
{
int threadsCounter = size/length;
int start = 0; //pointer to table from where each thread should start counting
int[] sum = new int[1]; //I am sharing the sum value between threads with table, not sure if it is best method to pass the value between them
sum[0] = 0;
Thread[] threads = new Thread[threadsCounter]; //nedeed for .join() test
for (int i = 0; i < threadsCounter; i++)
{
threads[i] = new Thread(new MyThread(tab, start, sum));
threads[i].start();
start += length; //moving the start pointer, next thread should start counting from next 100 indexes
}
/*for (int i = 0; i < threadsCounter; i++) // adding .join() solves the problem, but is it a good solution?
{
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}*/
return sum[0];
}
public static void main(String[] args)
{
initialize();
long start = Calendar.getInstance().getTimeInMillis();
System.out.println("Without threads: " + summarize() + ", " + (Calendar.getInstance().getTimeInMillis() - start) + "ms");
start = Calendar.getInstance().getTimeInMillis();
System.out.println("With threads: " + summarizeT() + ", " + (Calendar.getInstance().getTimeInMillis() - start) + "ms"); //giving wrong answer
}
}
MyThread class:
import java.util.concurrent.Semaphore;
public class MyThread extends Thread
{
int[] tab;
int[] sum;
int start;
MyThread(int tab[], int start, int sum[]) //in args: main table, starting index, value that is being shared between threads
{
this.tab = tab;
this.start = start;
this.sum = sum;
}
#Override
public void run()
{
int end = start + Main.length; //place where thread should stop counting
int temp = 0; //nedeed to sumarize the "subtable"
while (start < end)
{
temp += tab[start];
start++;
}
// Method 1
Semaphore semaphore = new Semaphore(1);
try {
semaphore.acquire();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try
{
sum[0] += temp;
} catch (Exception e) {
} finally {
semaphore.release();
}
// Method 2
/*Object lock = new Object();
synchronized(lock)
{
sum[0] += temp;
}*/
// Method 3
/*synchronized(this)
{
sum[0] += temp;
}*/
// Method 4
//summarize(temp);
// Method 5 - no threads synchronization, works only when .join() is used, the same as other methods
//sum[0] += temp;
}
private synchronized void summarize(int value)
{
sum[0] += value;
}
}
Isn't the problem here that you create a lock object , or semaphore object, in each thread, rather than having one object that all threads synchronise on?
Each Thread creates is own Semaphore object ( for example ) so no other thread will ever contend with it. You need to create an object that ALL threads have access to and synchronise on that. You might consider synchronising on the array that you are writing the results in to itself.
There are some problems with your solution.
You should use AtomicInteger to hold results. that way you don't need to synchronize sum update.
BTW the way you synchronize is invalid. For semaphores to work you need to share same instance between all threads. And your try/catch/finally blocks are invalid. You should do acquire() and sum update in one try block, and release() in it's finally. That way you did it. It is possible that you'll do sum update even though acquire() failed.
Also you return from summarizeT() without waiting for threads to finish. You have to implement thread.join() logic or some other way to wait.

Java Threading- Am I writing thread-safe code?

I'm currently trying to get into parallel processing, so to do this, I'm writing a program that processes an image, giving information about its color values overall- I am doing some tests on this one class with a randomly generated array of integers, and 4 threads are running to process every 4th pixel, from their respective starting places. I was just wondering if this read is thread-safe? Can multiple threads read the same data structure if that's what I want?
import java.awt.image.BufferedImage;
import java.lang.Thread;
public class ImageProcessor extends Thread {
public static void main(String[] args) {
int[] z = new int[10000000];
for (int i = 0; i < 10000000; i++) {
double a = (Math.random()*1000000);
z[i] = (int) a;
}
ImageProcessor ip = new ImageProcessor();
ip.imgRGBPercent(z);
}
public ImageProcessor() {
}
public void process(int[] x, int startPoint) {
(new Thread(new ReadThread(x, startPoint))).start();
}
public int[] imgRGBPercent(int[] x) {
ReadThread first = new ReadThread(x, 0);
ReadThread second = new ReadThread(x, 1);
ReadThread third = new ReadThread(x, 2);
ReadThread fourth = new ReadThread(x, 3);
Thread a = (new Thread(first));
Thread b = (new Thread(second));
Thread c = (new Thread(third));
Thread d = (new Thread(fourth));
long timeMetric = System.currentTimeMillis();
a.start();
b.start();
c.start();
d.start();
try {
a.join();
}
catch (Exception e) {
}
try {
b.join();
}
catch (Exception e) {
}
try {
c.join();
}
catch (Exception e) {
}
try {
d.join();
}
catch (Exception e) {
}
int redTotal, blueTotal, greenTotal;
redTotal = first.getRGBTotals()[0] + second.getRGBTotals()[0] + third.getRGBTotals()[0] + fourth.getRGBTotals()[0];
blueTotal = first.getRGBTotals()[1] + second.getRGBTotals()[1] + third.getRGBTotals()[1] + fourth.getRGBTotals()[1];
greenTotal = first.getRGBTotals()[2] + second.getRGBTotals()[2] + third.getRGBTotals()[2] + fourth.getRGBTotals()[2];
System.out.println(greenTotal);
System.out.println(System.currentTimeMillis() - timeMetric);
timeMetric = System.currentTimeMillis();
ColorValue cv1 = new ColorValue();
int sum = 0;
int sum1 = 0;
int sum2 = 0;
for (int i = 0; i < x.length; i++) {
sum += cv1.getGreen(x[i]);
sum1 += cv1.getRed(x[i]);
sum2 += cv1.getBlue(x[i]);
}
System.out.println(sum);
System.out.println(System.currentTimeMillis() - timeMetric);
int[] out = new int[3];
return out;
}
private class ReadThread implements Runnable {
private int[] colorArr;
private int startPoint, redTotal, blueTotal, greenTotal;
private ColorValue cv;
public ReadThread(int[] x, int startPoint) {
colorArr = x;
this.startPoint = startPoint;
cv = new ColorValue();
}
#Override
public void run() {
//System.out.println("hit");
for (int i = startPoint; i < colorArr.length; i+=4 ) {
redTotal += ColorValue.getRed(colorArr[i]);
blueTotal += ColorValue.getBlue(colorArr[i]);
greenTotal += ColorValue.getGreen(colorArr[i]);
}
}
public int[] getRGBTotals() {
int[] out = new int[3];
out[0] = redTotal;
out[1] = blueTotal;
out[2] = greenTotal;
return out;
}
}
}
Yes. As long as the data structure is not modified while it's being read, you're safe. Every write done before starting a thread will be visible by the started thread.
This logic would concern me a little:
for (int i = startPoint; i < colorArr.length; i+=4 ) {
redTotal += ColorValue.getRed(colorArr[i]);
blueTotal += ColorValue.getBlue(colorArr[i]);
greenTotal += ColorValue.getGreen(colorArr[i]);
}
colorArr is a reference to an array; the reference was passed to the Runnable during the constructor, but the array itself was created outside.
In the complete program you posted, I don't think it's a problem, since this array isn't modified anywhere in your program after the point where you start the threads. But in a larger, "real-world" case, you have to be aware that you're reading colorArr[i] three times and the value may not be the same each time, if there are other threads that could make changes to colorArr. That's one of the things you have to watch out for when writing concurrent code. This would be a little better:
for (int i = startPoint; i < colorArr.length; i+=4 ) {
int color = colorArr[i];
redTotal += ColorValue.getRed(color);
blueTotal += ColorValue.getBlue(color);
greenTotal += ColorValue.getGreen(color);
}
But depending on what your needs are, you may need to take extra steps to make sure no part of the program can modify colorArr at any point while the entire loop is running. Then you need to start looking into lock objects and synchronized, and you'd want to seriously consider setting up a separate class for the colorArr, with methods for modifying and reading the array that are either synchronized methods or contain logic to ensure that things are synchronized properly--by putting the array in its own class, the needed synchronization logic could be encapsulated in that class, so clients of the class wouldn't have to worry about it. That's the kind of thing you need to think about when you start using concurrency.
Yes, multiple threads can read the same objects and are fine so long as other threads aren't modifying them at the same time. Depending on what you're doing the Fork-Join framework may be useful, it manages a lot of the threading details for you, so would be worth investigating.

Java Multithreading : How to make a thread wait ?

I want to make a plane (Thread) fly from one airfield to another. When a plane is starting the airfield is blocked for 5 sec. (if another plane wants to land or take off - must wait). If a plane reach its destination it lands (if airfield is not blocked by another plane) and then takes a random airfield and fly there and so on....
I have questions in comments - how to make a thread wait ? And what else is wrong with my code ?
Here is my class Samolot aka Plane:
public class Samolot extends Thread{
int id;
double paliwo;
Lotnisko source; //Lotnisko aka airfield
Lotnisko dest;
double xPosition;
double yPosition;
double xTarget;
double yTarget;
public Samolot(Lotnisko source, Lotnisko dest) {
this.source = source;
this.dest = dest;
paliwo = 100;
}
public void run(){
while(true){
tryStart();
}
}
public void tryStart(){
if(source.pas == true){ // if true the airfield is not blocked and we can go
source.timer(); // its a method in class Lotnisko, makes pas = false for 8sec
lecimy(source, dest);
}
else if(source.pas == false){
// how to make a thread wait ?
}
}
public void tryLadowanie(){
if(dest.pas == true){
dest.timer();
source = dest;
dest = Rand(source);
tryStart();
}
else if(dest.pas == false){
//how to make a thread wait ?
}
}
public void lecimy(Lotnisko source, Lotnisko dest){
xPosition = source.coords.getX();
yPosition = source.coords.getY();
xTarget = dest.coords.getX();
yTarget = dest.coords.getY();
while( (xPosition != xTarget) && (yPosition != yTarget) ){
update();
try{
sleep(100);// ok
}
catch (InterruptedException e) {
System.out.println("Error");
}
}
tryLadowanie();
}
public void update() {
paliwo -= 0.05;
double dx = xTarget - xPosition;
double dy = yTarget - yPosition;
double length = sqrt(dx*dx+dy*dy);
dx /= length;
dy /= length;
if (Math.abs(dest.coords.getX() - source.coords.getX()) < 1)
dx = 0;
if (Math.abs(dest.coords.getY() - source.coords.getY()) < 1)
dy = 0;
xPosition += dx;
yPosition += dy;
}
public Point getPositions() {
Point curPos = new Point((int)xPosition, (int)yPosition);
return curPos;
}
OK, so your plane is a thread and your airfields are the shared resource. So to make your plane (thread) wait, you'll need to synchronized on the shared resource (airfield). You'll probably do something like this.
For take off,
public void tryStart() {
synchronized(source) { // try to obtain source lock
try {
Thread.sleep(5000); // lock it for 5 seconds.
}
catch(Exception ignore) {
// You'll need to decide what to do if something interrupts the thread while it's "sleeping" (ie. locked) on the source airfield. Normally, this should not happen.
}
}
// After 5 seconds, releases lock on airfield "source" and Plane starts flying
}
For landing,
public void tryLadowanie() {
synchronized(dest) { // try to obtain dest lock
// successfully obtained lock.
// perform your landing
}
// plane landed and releases "dest" resource for other planes (ie. threads)
}
For a more complete picture of plane flying.
public void run(){
while(true){
tryStart(); // take off from source
lecimy(); // fly the plane. Method will only return when plane reaches destination.
tryLadowanie(); // land the plane
source = dest;
dest = Rand(source); // returns a new destination but can't be the same as source
}
}
public void tryStart(){
synchronized(source) {
try {
Thread.sleep(5000);
}
catch(Exception ignore) { }
}
}
public void tryLadowanie(){
synchronized(dest) {
// land the plane
}
}
Not a complete answer but wait method is used to wait the thread and notify is used to wake up the thread that is in wait.
Check this for more info on wait and notify method:
http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait()
http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#notify()
Use general java object exp.
Object lock=new Object();
To wait :
Synchronized(lock)
{
lock.wait();
}
To release or free the lock from another thread
On same lock object
Synchronized(lock)
{
lock.notify();
}

How to remove manually created pauses in Main-thread?

Problem description:
We have a given matrix randomly filled with digits and have to create separate threads for each row of the matrix that count how many times the digits encounter in that row.
Without these sleeps in the main thread, it's not working correctly..
Here's my solution.
Also it's following here:
public class TestingMatrixThreads {
public static void main(String[] arr) throws InterruptedException {
int[][] a = new int[67][6];
// class.Count works with class.Matrix, that's why I've made it this way
Matrix m = new Matrix(a);
m.start();
Thread.sleep(1000); // Here comes the BIG question -> how to avoid these
// manually created pauses
Count c;
Thread t;
// Creating new threads for each row of the matrix
for (int i = 0; i < Matrix.matr.length; i++) {
c = new Count(i);
t = new Thread(c);
t.start();
}
//Again - the same question
System.out.println("Main - Sleep!");
Thread.sleep(50);
System.out.println("\t\t\t\t\tMain - Alive!");
int sum = 0;
for (int i = 0; i < Count.encounters.length; i++) {
System.out.println(i + "->" + Count.encounters[i]);
sum += Count.encounters[i];
}
System.out.println("Total numbers of digits: " + sum);
}
}
class Count implements Runnable {
int row;
public static int[] encounters = new int[10]; // here I store the number of each digit's(array's index) encounters
public Count(int row) {
this.row = row;
}
public synchronized static void increment(int number) {
encounters[number]++;
}
#Override
public void run() {
System.out.println(Thread.currentThread().getName() + ", searching in row " + row + " STARTED");
for (int col = 0; col < Matrix.matr[0].length; col++) {
increment(Matrix.matr[row][col]);
}
try {
Thread.sleep(1); // If it's missing threads are starting and stopping consequently
} catch (InterruptedException e) {
}
System.out.println(Thread.currentThread().getName() + " stopped!");
}
}
class Matrix extends Thread {
static int[][] matr;
public Matrix(int[][] matr) {
Matrix.matr = matr;
}
#Override
public void run() {
//print();
fill();
System.out.println("matrix filled");
print();
}
public static void fill() {
for (int i = 0; i < matr.length; i++) {
for (int j = 0; j < matr[0].length; j++) {
matr[i][j] = (int) (Math.random() * 10);
}
}
}
public static void print() {
for (int i = 0; i < matr.length; i++) {
for (int j = 0; j < matr[0].length; j++) {
System.out.print(matr[i][j] + " ");
}
System.out.println();
}
}
}
P.S. I'm sorry if this question is too stupid for you to answer, but I'm a newbie in Java programming, as well as it's my very first post in stackoverflow, so please excuse me for the bad formatting, too :)
Thank you in advance!
Change the Thread.sleep by m.join()
Doing this will make the main thread wait for the other to complete its work and then it will continu its execution.
Cheers
To answer your main question:
Thread.join();
For example:
public static void main(String[] args) throws Exception {
final Thread t = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("Do stuff");
}
});
t.start();
t.join();
}
The start call, as you know, kicks off the other Thread and runs the Runnable. The join call then waits for that started thread to finish.
A more advanced way to deal with multiple threads is with an ExecutorService. This detaches the threads themselves from the tasks they do. You can have a pool of n threads and m > n tasks.
Example:
public static void main(String[] args) throws Exception {
final class PrintMe implements Callable<Void> {
final String toPrint;
public PrintMe(final String toPrint) {
this.toPrint = toPrint;
}
#Override
public Void call() throws Exception {
System.out.println(toPrint);
return null;
}
}
final List<Callable<Void>> callables = new LinkedList<>();
for (int i = 0; i < 10; ++i) {
callables.add(new PrintMe("I am " + i));
}
final ExecutorService es = Executors.newFixedThreadPool(4);
es.invokeAll(callables);
es.shutdown();
es.awaitTermination(1, TimeUnit.DAYS);
}
Here we have 4 threads and 10 tasks.
If you go down this route you probably need to look into the Future API to so that you can check whether the tasks completed successfully. You can also return a value from the task; in your case a Callable<Integer> would seem to be appropriate so that you can return the result of your calculation from the call method and gather up the results from the Future.
As other Answers have stated, you can do this simply using join; e.g.
Matrix m = new Matrix(a);
m.start();
m.join();
However, I just want to note that if you do that, you are not going to get any parallelism from the Matrix thread. You would be better of doing this:
Matrix m = new Matrix(a);
m.run();
i.e. executing the run() method on the main thread. You might get some parallelism by passing m to each "counter" thread, and having them all join the Matrix thread ... but I doubt that it will be worthwhile.
Frankly, I'd be surprised if you get a worthwhile speedup for any of the multi-threading you are trying here:
If the matrix is small, the overheads of creating the threads will dominate.
If the matrix is large, you are liable to run into memory contention issues.
The initialization phase takes O(N^2) computations compared with the parallelized 2nd phase that has N threads doing O(N) computations. Even if you can get a decent speedup in the 2nd phase, the 1st phase is likely to dominate.

Categories