1 Attachment(s)
Many thread benchmark help
I'm building a simple benchmark program that proves the primality the largest 64-bit unsigned prime number. So far, I can set up the threads and they all run correctly, but in an effort to increase the efficiency in which the threads are executed, I want to start all the threads at once. I don't know how to do this, or if it is even possible. Currently I have it loop through an array list of the threads starting each one individually. The number of threads created is your free memory divided by five megabytes (5 * Math.pow(2,10)). Also, am I waiting for termination the right way?
Execution class:
Code java:
package benchmark;
import java.util.ArrayList;
import javax.swing.JOptionPane;
public class Run {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
long lim = (long)4294967296.0;//upper limit of loop
JOptionPane.showMessageDialog(null, "Welcome to the 64-bit prime benchmark. It measures how efficiently your machine can run through the algorithm.");
long threads = (Runtime.getRuntime().freeMemory())/(5 * (long)(Math.pow(2, 10)));//calculates the number of threads to use.
JOptionPane.showMessageDialog(null, "It will run using " + threads + " threads.\n\nPress OK to build the threads.");
ArrayList<Thread> th = new ArrayList<Thread>();//arraylist of threads
long inc = lim/threads, s = 2;
for(long i = 0; i < threads; i++)
{
th.add(new Algorithm(s,inc+s));//creates each thread and adds it to the array list
}
JOptionPane.showMessageDialog(null, "Threads built. \n\nPress OK to run benchmark.");
long start = System.currentTimeMillis();//times the amount of time it takes
for(int i = 0; i < threads; i++)
{
th.get(i).start();//starts each thread
}
while(th.get(th.size()-1).isAlive())
{}//waits for the last thread in the list to terminate
long end = System.currentTimeMillis();//end of the timer
//prints some stats
JOptionPane.showMessageDialog(null,"Statistics:\n" +
"Time: " + (end - start) + " ms.\n" +
"Total iterations: " + lim/2 + "\n" +
"Iterations per second: " + ((lim/2)/(end-start))*1000+"\n" +
"Number of threads: "+ th.size());
System.exit(1);
}
}
Algorithm():
Code java:
package benchmark;
import org.jscience.mathematics.number.LargeInteger;
public class Algorithm extends Thread{
/**
* @param args
*/
private LargeInteger val = LargeInteger.valueOf("18446744073709551557");//number being factored
private long start, end, increment = 2;//runtime variables that specify where to start, stop, and the increment for each number
/**
* @param start - value to start at
* @param end - value to end at
*/
public Algorithm(long start, long end)
{
this.start =start;
this.end = end;
}
public synchronized void run()
{
//System.out.println("Thread: " + threadNum + " starting. Thread ID: " + getId());
LargeInteger lim = LargeInteger.valueOf(end);//LargeInteger containing the end value
for(LargeInteger i = LargeInteger.valueOf(start); lim.isGreaterThan(i); i.plus(increment))//loop for primality check
{
if(val.mod(i).equals(0))//checks for accuracy of the thread
{
throw new RuntimeException("Inaccurate Process.");//throughs an exception if an error is made showing the value not prime.
}
}
}
}
I will attach the JScience library that I use here.
Re: Many thread benchmark help
Quote:
Originally Posted by
aesguitar
...but in an effort to increase the efficiency in which the threads are executed, I want to start all the threads at once. ...
Why do you think that this will increase efficiency?
Why do you feel that you're not starting them as close together in time as is possible?
Re: Many thread benchmark help
Quote:
Originally Posted by
curmudgeon
Why do you think that this will increase efficiency?
Why do you feel that you're not starting them as close together in time as is possible?
The thing is, I don't know. I was simply wondering if there was maybe an easier or faster way to do it, I don't have anything to compare it to as I'm not very good with multi-threading yet. Also, is the way I'm checking for full termination the right way to do it? Is there a better way perhaps?
Re: Many thread benchmark help
How many different processors does the computer you are executing the program on have?
Having one thread per processor will allow the threads to execute in parallel. Otherwise there is a chance that extra threads will lengthen the time taken to run the program due to OS overhead swapping between threads.
Re: Many thread benchmark help
How you're starting threads is just fine.
I don't think you're waiting for threads to end correctly. For one, the last thread started isn't guaranteed to be the last one to finish execution. Secondly, you're consuming a lot of resources in your main thread waiting for the other threads to finish. This will drastically reduce your performance.
A better way to wait for the thread to end is to use the join method. This consumes very little resources, and is guaranteed to wait for all threads to finish under normal circumstances.
Code java:
for(Thread t: th)
{
t.join();
}
Also, I noticed you're starting a rather large number of threads. More threads != better performance. Usually the ideal number of threads is around the number of physical cores your CPU has. There are ways to schedule tasks with a small number of worker threads to get better throughput and less memory. Do a search for Java thread pools.
Re: Many thread benchmark help
I have a dual core i5 @ 2.4 GHz with hyperthreading giving 4 logical cores. I have it creating threads based on the amount of free RAM. When it runs, it uses 800,000 MB and around 90% of my processor. Should I only have like 1 or 2 threads per physical processor?
Re: Many thread benchmark help
Quote:
The number of threads created is your free memory divided by five megabytes (5 * Math.pow(2,10))
Think about this statement for a moment. A thread is run on a processor...each thread must 'coordinate' access to a processor to be able to run the code it contains. Imagine for the sake of argument you have 8 processors and a good amount of free memory - this means you could quite possibly be launching thousands of threads - each competing for your sole 8 processors. And remember, there is also the thread which spawns them - in the example above the main thread - which is also competing for its own processor time. In other words, spawning so many threads actually decreases performance. If you wish to push your computer, create a reasonable number of threads based upon the number of processors, not the amount of free memory - and don't forget the threads your program inherently owns but you don't directly create (for instance, the main thread)
Re: Many thread benchmark help
Did I do this correctly?
Code java:
for(Thread t: th)
{
t.start();
}
for(Thread t : th)
{
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I am also starting threads based on the number of processors now.
Code java:
long threads = (Runtime.getRuntime().availableProcessors()*4);
Re: Many thread benchmark help
Yes, that looks much better.
1 Attachment(s)
Re: Many thread benchmark help
Thank you all. It runs beautifully... I think...
Final code:
Code java:
package benchmark;
import java.util.ArrayList;
import javax.swing.JOptionPane;
public class Run {
public static long score(long time, long ipers, long threads)
{
return (ipers/time)*threads;
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
long lim = (long)4294967295.0;//upper limit of loop
JOptionPane.showMessageDialog(null, "Welcome to the 64-bit prime benchmark. It measures how efficiently your machine can run through the algorithm.");
long threads = Runtime.getRuntime().availableProcessors()*2;//calculates the number of threads to use.
JOptionPane.showMessageDialog(null, "It will run using " + threads + " threads.\n\nPress OK to build the threads.");
long tStart = System.currentTimeMillis();
ArrayList<Thread> th = new ArrayList<Thread>();//arraylist of threads
long inc = lim/threads, s = 2;
for(long i = 0; i < threads; i++)
{
th.add(new Algorithm(s,inc+s));//creates each thread and adds it to the array list
}
long tEnd = System.currentTimeMillis();
JOptionPane.showMessageDialog(null, "Threads built.\nTime: " + (tEnd-tStart) + " ms\n\nPress OK to run benchmark.");
long start = System.currentTimeMillis();//times the amount of time it takes
for(Thread t: th)
{
t.start();
}
for(Thread t : th)
{
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
long end = System.currentTimeMillis();//end of the timer
JOptionPane.showMessageDialog(null,"Statistics:\n" +
"Time: " + (double)(end - start)/1000.0 + " ms.\n" +
"Total iterations: " + lim/2 + "\n" +
"Iterations per second: " + ((lim/2)/(end-start))*1000+"\n" +
"Number of threads: "+ th.size() +"\n" +
"Score (higher=better): " + score(end-start,((lim/2)/(end-start))*1000, threads));//prints some stats
System.out.println("Statistics:\n" +
"Time: " + (double)(end - start)/1000.0 + " ms.\n" +
"Total iterations: " + lim/2 + "\n" +
"Iterations per second: " + ((lim/2)/(end-start))*1000+"\n" +
"Number of threads: "+ th.size() +"\n" +
"Score (higher=better): " + score(end-start,((lim/2)/(end-start))*1000, threads));
System.exit(1);
}
}
Algorithm:
Code java:
package benchmark;
import org.jscience.mathematics.number.LargeInteger;
public class Algorithm extends Thread{
/**
* @param args
*/
private LargeInteger val = LargeInteger.valueOf("18446744073709551557");//number being factored
private long start, end, increment = 2;//runtime variables that specify where to start, stop, and the increment for each number
/**
* @param start - value to start at
* @param end - value to end at
*/
public Algorithm(long start, long end)
{
this.start =start;
this.end = end;
}
public void run()
{
//System.out.println("Thread: " + threadNum + " starting. Thread ID: " + getId());
LargeInteger lim = LargeInteger.valueOf(end);//LargeInteger containing the end value
for(LargeInteger i = LargeInteger.valueOf(start); lim.isGreaterThan(i); i = i.plus(increment))//loop for primality check
{
if(val.mod(i).equals(0))//checks for accuracy of the thread
{
throw new RuntimeException("Inaccurate Process.");//throughs an exception if an error is made showing the value not prime.
}
}
}
}
The LargeInteger class was posted earlier in the thread.
Zip file containing the compiled program: