The followiing code uses threads to calculate the max value in a subarry, and then calculates the max value out of the max values the threads returned. I have a bug that the main thread doesn't wait for the threads to finish when collecting the results.
Thread class:
public class MaxTask extends Thread {
private int[] arr;
private int max;
private int first, last;
public MaxTask(int[] arr, int first, int last) {
this.arr = arr;
this.first = first;
this.last = last;
}
public int getMax() {
return max;
}
public void run() {
max = arr[first];
for (int i = first + 1; i <= last; i++) {
if (arr[i] > max) max = arr[i];
}
}
}
Main:
public class MainMax {
public static void main(String[] args) throws Exception {
int size = 100;
int workers = 10;
int[] arr = new int[size];
int max = 0;
for (int i = 0; i < size; i++) {
arr[i] = (int)(Math.random() * 100);
if (max < arr[i]) max = arr[i];
}
System.out.println("max=" + max);
int gsize = (arr.length - 1) / workers;
MaxTask[] tasks = new MaxTask[workers];
int first = 0;
int last;
for (int i = 0; i < workers; i++) {
last = first + gsize;
tasks[i] = new MaxTask(arr, first, last);
tasks[i].start();
first = last + 1;
}
int maxmax = tasks[0].getMax();
int temp;
for (int i = 1; i < workers; i++) {
temp = tasks[i].getMax();
if (temp > maxmax) maxmax = temp;
}
System.out.println("maxmax=" + maxmax);
}
}
I am trying to solve the problem using synchronized. I managed to get it working when using synchronized on both run and getMax. But I really don't understand why this solves the problem.
First, you must understand that the main class is also running on a thread. That thread is seperate from the threads you created for the function and is thus running in parallel to them. By that logic, int maxmax = tasks[0].getMax(); is running asynchronously and possibly before the loop is finished.
One possible solution would be to lock that part of the code and force the execution to wait before executing that line. Only release the lock after everyone in the loop is done. Synchronizing access to the run method only defeats the purpose of running multiple threads since you're forcing the whole thing to be sequential.
It is also not recommended to create a thread for every single element, since there's a tradeoff between number of threads and how much you're speeding up execution.
Related
I am writing code to let 4 threads build a histogram.
I have an array in main:
int N = 10000;
Random r = new Random();
int[] a = new int[N];
for (int i = 0; i < a.length; i++)
{
a[i] = Math.abs(r.nextInt() % 100);
}
So basically what I want to do is cycle through this array and count how many times each number appears.
So I have written my thread class, and I used AtomicInteger which I thought would help solve the problem of multiple threads trying to access the same index simultaneously.
import java.util.concurrent.atomic.AtomicInteger;
public class UseThread implements Runnable
{
private static int[] array;
private static AtomicInteger[] count;
private static boolean[] check;
public UseThread(int[] array, AtomicInteger[] count)
{
this.array = array;
this.count = count;
this.check = new boolean[array.length];
}
public void run()
{
for (int i = 0; i < array.length; i++)
{
if (!getIndex(this.check[i]))
{
this.check[i] = true;
int number = array[i];
count[number].incrementAndGet();
}
}
}
public synchronized static boolean getIndex(boolean check2)
{
return check2;
}
However, this hasn't quite fixed my problem. Some of the threads are accessing the array at the same time, making the count array, hold a larger value than the length of the array array.
I think the problem is in the boolean array of checking. I have a feeling that multiple threads access the same boolean array index at the same time.
I figure it is probably a simple fix, but I am just not seeing it.
Any suggestions??
I have tried the AtomicBoolean array, but it has not helped. Below is the same class but with the AtomicBoolean array implemented.
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class Assign7Q3 implements Runnable
{
private static int[] array;
private static AtomicInteger[] count;
private static AtomicBoolean[] check;
public Assign7Q3(int[] array, AtomicInteger[] count)
{
this.array = array;
this.count = count;
this.check = new AtomicBoolean[array.length];
for(int i = 0; i < check.length; i ++)
check[i] = new AtomicBoolean(false);
}
public void run()
{
for (int i = 0; i < array.length; i++)
{
//System.out.println(this.check[i].get());
if (!getIndex(this.check[i]))
{
this.check[i].set(true);
int number = array[i];
count[number].incrementAndGet();
}
}
}
public synchronized static boolean getIndex(AtomicBoolean check2)
{
return check2.get();
}
You need to use compareAndSet for your if statement to be mutally exclusive:
if (this.check[i].compareAndSet(false, true))
{
int number = array[i];
count[number].incrementAndGet();
}
This both checks and sets the value atomically.
Without compareAndSet, there is a possibility that two threads can check the value and enter the if block at the same time before one has a chance to call set(true).
I've been writing the following code for my OS course and I got some weird results. The code creates x threads and runs them concurrently in order to multiply two squared matrices. Every thread will multiply Number_of_rows/Number_of_threads rows of the input matrices.
When running it on a 1024X1024 matrices, with 1...8 threads, I get that the fastest multiplication happens when using only one thread. I would expect that a MacBook pro with i5 processor (2-cores) will utilize the two cores and that will yield faster results when using two threads.
Running time goes from about ~9.2 seconds using one thread, ~9.6 seconds to 27 seconds using 8.
Any idea why this is happening?
BTW, A few things about the code:
a. Assume that both matrices have identical dimensions and are square.
b. Assume that number of threads <= number of rows/columns.
public class MatrixMultThread implements Runnable {
final static int MATRIX_SIZE = 1024;
final static int MAX_THREADS = MATRIX_SIZE;
private float[][] a;
private float[][] b;
private float[][] res;
private int startIndex;
private int endIndex;
public MatrixMultThread(float[][] a, float[][]b, float[][] res, int startIndex, int endIndex) {
this.a = a;
this.b = b;
this.res = res;
this.startIndex = startIndex;
this.endIndex = endIndex;
}
public void run() {
float value = 0;
for (int k = startIndex; k < endIndex; k++) {
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length; j++) {
value += a[k][j]*b[j][i];
}
res[k][i] = value;
value = 0;
}
}
}
public static float[][] mult(float[][] a, float[][] b, int threadCount){
// Get number of rows per each thread.
int rowsPerThread = (int) Math.ceil(MATRIX_SIZE / threadCount);
float[][] res = new float[MATRIX_SIZE][MATRIX_SIZE];
// Create thread array
Thread[] threadsArray = new Thread[threadCount];
int rowCounter = 0;
for (int i = 0; i < threadCount; i++) {
threadsArray[i] = new Thread(new MatrixMultThread(a,b,res,rowCounter, Math.max(rowCounter + rowsPerThread, MATRIX_SIZE)));
threadsArray[i].start();
rowCounter += rowsPerThread;
}
// Wait for all threads to end before finishing execution.
for (int i = 0; i < threadCount; i++) {
try {
threadsArray[i].join();
} catch (InterruptedException e) {
System.out.println("join failed");
}
}
return res;
}
public static void main(String args[]) {
// Create matrices and random generator
Random randomGenerator = new Random();
float[][] a = new float[MATRIX_SIZE][MATRIX_SIZE];
float[][] b = new float[MATRIX_SIZE][MATRIX_SIZE];
// Initialize two matrices with initial values from 1 to 10.
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length; j++) {
a[i][j] = randomGenerator.nextFloat() * randomGenerator.nextInt(100);
b[i][j] = randomGenerator.nextFloat() * randomGenerator.nextInt(100);
}
}
long startTime;
for (int i = 1; i <= 8; i++) {
startTime = System.currentTimeMillis();
mult(a,b,i);
System.out.println("Total running time is: " + (System.currentTimeMillis() - startTime) + " ms");
}
}
}
Firstly a bit of logging helps. I did logging for this and found out a bug in your logic.
Here is the log
Starting execution for thread count: 1
Start index: 0
End index: 1024
Starting execution: MatrixMultiplier: 0
Ending executionMatrixMultiplier: 0
Total running time is: 6593 ms
Starting execution for thread count: 2
Start index: 0
End index: 1024 <------ This is the problem area
Start index: 512
End index: 1024
Starting execution: MatrixMultiplier: 1
Starting execution: MatrixMultiplier: 0
Your first thread in all iterations is performing whole multiplication everytime. That's why you are not seeing results. Figure out the bug.
Trying to get a multi-threaded matrix multiplication to work in Java. It is given a (m x n) matrix, a (n x k) matrix and 't' threads to perform the operation on.
My program works when the matrices are square and t == n. When running with t < n, the other threads do not pick up the additional operations, and it returns a partially completed matrix. When the matrices are not square, the additional threads return array out of bounds errors and do not run. I would really appreciate any advice. Here are the relevant code snippets
Beginning threads. multipliers is an array of MatrixMultiplier, a class defined later.
Multiply multiply = new Multiply(cols_mat, rows_mat2);
for (int i = 0; i < threads; i++) {
multipliers[i] = new MatrixMultiplier(multiply);
}
for (int i = 0; i < threads; i++) {
my_threads[i] = new Thread(multipliers[i]);
}
for (int i = 0; i < threads; i++) {
my_threads[i].start();
}
for (int i = 0; i < threads; i++) {
my_threads[i].join();
}
Multiply class which defines the matrix multiplication
class Multiply extends MatrixMultiplication {
private int i;
private int j;
private int chance;
public Multiply(int i, int j) {
this.i = i;
this.j = j;
chance = 0;
}
public synchronized void multiplyMatrix() {
int sum = 0;
int a = 0;
for (a = 0; a < i; a++) {
sum = 0;
for (int b = 0; b < j; b++) {
sum = sum + mat[chance][b] * mat2[b][a];
}
result[chance][a] = sum;
}
if (chance >= i)
return;
chance++;
}
}
And the matrix multiplier
class MatrixMultiplier implements Runnable {
private final Multiply mul;
public MatrixMultiplier(Multiply mul) {
this.mul = mul;
}
#Override
public void run() {
mul.multiplyMatrix();
}
}
Where I personally think the issue lies is with if (chance >= i) return; but I have not found a way to incorporate a thread's column responsibilities with the program still working. Again, any advice pointing me in the right direction would be greatly appreciated.
There are several issues with your code.
The t threads assume that only t multiplications are required to produce your result matrix. This is not to be the case when m != k or t != m or t != k. The threads are worker threads that will only process your requests. I would consider making each MatrixMultiplier have access to the mxn, nxk, mxk matrices and a rolcolumn entries container.
class MatricMultiplier {
private double a[][], b[][], results[][];
private Queue<..> entries;
....
}
The run method will then use the entries container to calculate the sum for a given <row,column> entry of the resulting mxk matrix. The run method could become:
run() {
for (Entry entry = entries.poll(); entry != null; entry = entries.poll()) {
int row = entry.row;
int col = entry.col;
double sum = 0.0;
for (int i = 0; i < a[row].length; i++) {
sum += a[row][i] * b[i][col];
}
results[row][col] = sum;
}
}
There are three things to note here that is different than what you have.
you are not using a synchronization block
each entry is calculating the answer for a unique row/column of the result matrix
the Multiple class is not required any longer
You can then create t threads that process each entry in the entries container and will exit when the entries container is empty.
Note that the entries container should be one of the concurrent Queue containers available in the java.util.concurrent package.
The remaining task is how to create the rowcolumn entries container. Here is some code that you could use:
Queue<..> entries = new Concurrent...<..>();
int rowSize = a.length;
int colSize = b[0].length;
for (int row = 0; row < rowSize; row++) {
for (int col = 0; col < colSize; col++) {
entries.add(new RowColumnEntry(row, col));
}
}
Noting that the a and b are the m×n and n×k matrices.
Hope this helps.
I would like to simulate a situation which is mentioned in books about concurrency - that without a proper synchronization one thread can see a stale value of a variable that has been already modified by a different thread. This could happen because for example a CPU cache.
To do this I have written the following program. The idea is that there are 4 threads that initialize a different part of a shared array. The 5th thread (main, parent thread) waits until all 4 previous threads are done, iterates over the shared array and adds its values (always 1 or if I'm lucky null, which would mean a stale value)
package p1;
class ArrFill implements Runnable {
int l, r;
Integer[] arr;
ArrFill(int l, int r, Integer[] arr) {
this.l = l;
this.r = r;
this.arr = arr;
}
#Override
public void run() {
for(int i = l; i < r; i++)
arr[i] = new Integer(1);
}
}
public class Main {
final static int MAX = 10000000;
final static int tnum = 4;
public static void main(String[] args) throws InterruptedException {
int cores = Runtime.getRuntime().availableProcessors();
System.out.println(cores);
Integer[] arr = new Integer[MAX];
Thread[] t = new Thread[tnum];
if(MAX % tnum != 0)
throw new IllegalStateException();
int step = MAX / tnum;
int l = 0, r = 0;
for(int i = 0; i < tnum; i++) {
l = r;
r += step;
t[i] = new Thread(new ArrFill(l, r, arr));
t[i].start();
}
for(int i = 0; i < tnum; i++)
t[i].join();
int res = 0;
for(int i = 0; i < MAX; i++)
if(arr[i] != null)
res += arr[i];
System.out.println(res == MAX);
}
}
I have run this program many times although I never seen a stale value (null). I have 2 cores. Do you have any idea how this program could be improved to actually present the cached value phenomena? Or maybe you have a completly different approach?
Thanks!
I want to make a simple math operations on a vector(array) using two cores of my CPU. The program doesn't work correctly. Please explain me how to solve my problem.
public class MyRunnable implements Runnable {
private int startIndex;
private int endIndex;
private float[] tab;
public MyRunnable(int startIndex, int endIndex, float[] tab)
{
this.startIndex = startIndex;
this.endIndex = endIndex;
this.tab = tab;
}
#Override
public void run()
{
System.out.println(Thread.currentThread());
for(int i = startIndex; i < endIndex; i++)
{
tab[i] = i * 2;
}
System.out.println("Finished");
}
}
public class Test {
public static void main(String[] args) {
int size = 10;
int n_threads = 2;
float tab[] = new float[size];
for(int i = 0; i < size; i++)
{
tab[i] = i;
}
System.out.println(Thread.currentThread());
for(int i = 0; i < size; i++)
{
System.out.println(tab[i]);
}
Runnable r1 = new MyRunnable(0, size / n_threads, tab );
Runnable r2 = new MyRunnable(size / n_threads, size, tab );
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
for(int i = 0; i < size; i++)
{
System.out.println(tab[i]);
}
}
It seems like you don't wait for the threads to finish. Use the join method and add
t1.join();
t2.join();
just before the output loop.
As pointed out by others, you are not waiting for your threads to finish execution. You should follow the advice of #Howard and #JK and that will fix your basic issue. If you decide to do more with threads and parallel processing though I would highly advice looking into the java.util.concurrent packages - they have many useful classes that will make your life much easier.
I took the liberty of recoding your example using Callable and ExecutorService. Please see the sample code below:
public static void main(String[] args) {
int size = 10;
int n_threads = 2;
float tab[] = new float[size];
for (int i = 0; i < size; i++) {
tab[i] = i;
}
System.out.println(Thread.currentThread());
for (int i = 0; i < size; i++) {
System.out.println(tab[i]);
}
// Determine batch size, based off of number of available
// threads.
int batchSize = (int) Math.ceil((double) size / n_threads);
System.out.println("Size: " + size + " Num threads: " + n_threads
+ " Batch Size: " + batchSize);
// Create list of tasks to run
List<Callable<Object>> tasks = new ArrayList<Callable<Object>>(
n_threads);
for (int i = 0; i < n_threads; i++) {
tasks.add(Executors.callable(new MyRunnable(i * batchSize,
((i + 1) * batchSize) - 1, tab)));
}
// Create an executor service to handle processing tasks
ExecutorService execService = Executors.newFixedThreadPool(n_threads);
try {
execService.invokeAll(tasks);
} catch (InterruptedException ie) {
ie.printStackTrace();
} finally {
execService.shutdown();
}
for (int i = 0; i < size; i++) {
System.out.println(tab[i]);
}
}
And made one slight change in your MyRunnable class, which was skipping processing on the last index:
#Override
public void run() {
System.out.println(Thread.currentThread());
for (int i = startIndex; i <= endIndex; i++) {
tab[i] = i * 2;
}
System.out.println("Finished");
}
Works great, you can test for yourself. Theres many more classes in java.util.concurrent that can do similar functionality, feel free to explore.
Good luck!
You can wait for the threads to finish execution by inserting calls to Thread.join():
t1.join();
t2.join();
after your x.start() function call to pause until the threads have completed. Otherwise you cannnot know if they are finished executing or not.
You should also consider synchronizing your tab[] accesses within the separate threads with a mutex/semaphore or similar mechanism, and not necessarily perform calculations directly on the passed in array reference, since this can limit the amount of concurrency (if present).