Quantcast

Maximum PC

It is currently Thu Jul 24, 2014 10:54 pm

All times are UTC - 8 hours




Post new topic Reply to topic  [ 15 posts ] 
Author Message
 Post subject: Java Multithreading
PostPosted: Mon Dec 01, 2008 6:23 pm 
Little Foot
Little Foot
User avatar

Joined: Mon Jul 28, 2008 1:39 pm
Posts: 123
I asked this on the java forums awhile ago and didn't get a clear answer...
I am working on a multithreaded Pi calculator application, and the question is, is it better to program the application to use the number of processor cores available (with Runtime.availableProcessors() ) or to hard-code the amount of threads I think I will need?

P.S.: The original thread on the Java forums:

http://forums.sun.com/thread.jspa?threadID=5347654&start=0&tstart=0


Top
  Profile  
 
 Post subject:
PostPosted: Tue Dec 02, 2008 4:37 am 
SON OF A GUN
SON OF A GUN
User avatar

Joined: Mon Nov 01, 2004 5:41 am
Posts: 11605
You have to be really careful with multi-threading stuff. I would only use what you need. For a calculator application I couldn't see needing more than two threads. One for the GUI and one for the calculation...


Top
  Profile  
 
 Post subject:
PostPosted: Tue Dec 02, 2008 7:06 am 
Little Foot
Little Foot
User avatar

Joined: Mon Jul 28, 2008 1:39 pm
Posts: 123
CrashTECH wrote:
You have to be really careful with multi-threading stuff. I would only use what you need. For a calculator application I couldn't see needing more than two threads. One for the GUI and one for the calculation...


You don't understand my implementation. The application's sole purpose is to calculate Pi (using Java's built-in BigDecimal class). Both threads would be constantly calculating. There is no GUI.


Top
  Profile  
 
 Post subject:
PostPosted: Tue Dec 02, 2008 7:36 am 
SON OF A GUN
SON OF A GUN
User avatar

Joined: Mon Nov 01, 2004 5:41 am
Posts: 11605
Well, that doesn't make sense. How are you planning on having two threads operate on the same value? That sounds very bad. You are going to have all kinds of locking issues and race conditions.

Is this for class?

If you just want an app to do it, download SuperPI.


Top
  Profile  
 
 Post subject: Re: Java Multithreading
PostPosted: Tue Dec 02, 2008 9:12 am 
Java Junkie
Java Junkie
User avatar

Joined: Mon Jun 14, 2004 10:23 am
Posts: 24222
Location: Granite Heaven
Quertior wrote:
I asked this on the java forums awhile ago and didn't get a clear answer...
I am working on a multithreaded Pi calculator application, and the question is, is it better to program the application to use the number of processor cores available (with Runtime.availableProcessors() ) or to hard-code the amount of threads I think I will need?

P.S.: The original thread on the Java forums:

http://forums.sun.com/thread.jspa?threadID=5347654&start=0&tstart=0


If you don't have a strong argument for hard-coding the number of threads, I don't see why you would do so.

This, of course, ignores the points that Crash made about the existence of race conditions ... how are you going to separate the work done by multiple processes.

Perhaps if you showed us the algorithm you're using, we would be better able to help.


Top
  Profile  
 
 Post subject:
PostPosted: Tue Dec 02, 2008 5:14 pm 
Little Foot
Little Foot
User avatar

Joined: Mon Jul 28, 2008 1:39 pm
Posts: 123
OK, here's the code I'm using... sorry, it's rather long:
Note that Apfloat and ApfloatMath are add-on classes that I downloaded from http://www.apfloat.org.

Code:
import org.apfloat.*;
import java.io.IOException;
import java.util.Scanner;
import java.io.File;
/**
*
* @author Jake Gunter
*/
public class PiChudnovskyMultithread {
   
    /**
     * the precision of the calculation; it is set later
     */
    static long precision = 1;
   
    /**
     * the scanner used throughout the program
     */
    Scanner in = new Scanner(System.in);
   
    /**
     * Pi, guaranteed correct (for testing purposes)
     */
    private String piCorrect;
   
    //simple constructor
    public PiChudnovskyMultithread() throws IOException {
        piCorrect = readPiFile();
    }
   
    public String readPiFile() throws IOException {
        Scanner fin = new Scanner(new File("pi.txt"));
        String piTmp = "";
        while(fin.hasNext())
            piTmp += fin.nextLine();
        return piTmp;
    }
    public void validatePi(Apfloat pi) {
        String piStr = pi.toString(true);
        int smallerLen = piStr.length() < piCorrect.length() ? piStr.length() : piCorrect.length();
        int digitsCorrect = 0;
        String userPiCorrect = "";
        boolean stillGoing = true;
        for(int i=0;i<smallerLen && stillGoing;i++) {
            char correct = piCorrect.charAt(i);
            char user = piStr.charAt(i);
            if (correct == user) {
                digitsCorrect++;
                userPiCorrect += user;
            }
            else stillGoing = false;
        }
        System.out.println(digitsCorrect-1 + " digits correct:");
        System.out.println(userPiCorrect);
    }
    public static Apfloat factorial(Apfloat num) {
        if (num.compareTo(new Apfloat(0)) == 0) return Apfloat.ONE;
        Apfloat factorialized = num;
        for(Apfloat i=num;i.compareTo(new Apfloat(0))>0;i=i.subtract(new Apfloat(1))) {
            Apfloat x = i.compareTo(new Apfloat(1)) == 0 ? new Apfloat(0) : new Apfloat(1);
            factorialized = factorialized.multiply(i.subtract(x));
        }
        return factorialized;
    }
    public static Apfloat inverse(Apfloat num) {
        return new Apfloat(1).divide(num);
    }
    public static Apfloat negpow(Apfloat a, Apfloat b) {
        if(b.mod(new Apfloat(2)).intValue() == 0) {
            return ApfloatMath.pow(a.negate(),b);
        }
        else return ApfloatMath.pow(a.negate(), b).negate();
    }
   
    /**
     * This method handles the thread scheduling and the final summation of                                                            pi. */
    public void calculatePi() throws InterruptedException, IOException {
        int numProcs = Runtime.getRuntime().availableProcessors();
        chudThread[] calculators = new chudThread[numProcs];
        long start = 0;
        System.out.print("How many iterations? ");
        int procMult = Integer.parseInt(in.nextLine()) / numProcs;
        while (procMult <= 0) {
            System.out.println("That's not a valid number of iterations!");
            System.out.print("How many iterations? ");
            procMult = (in.nextInt()) / numProcs;
        }
        precision = procMult * numProcs * 14 + 1 + (procMult * numProcs)/10;
        System.out.println(precision);
        for(int i=0;i<numProcs;i++) {
            calculators[i] = new chudThread(start, start+=procMult);
        }
        System.out.println("Calculating...");
        long startTime = System.currentTimeMillis();
        for(int i=0;i<numProcs;i++) {
            calculators[i].start();
        }
        for(int i=0;i<numProcs;i++) {
            calculators[i].join();
        }
        Apfloat pi = new Apfloat(0,precision);
        for (int i=0;i<numProcs;i++) {
            pi = pi.add(calculators[i].piPart);
        }
        pi = pi.multiply(new Apfloat(12,precision));
        pi = inverse(pi);
        new PiChudnovskyMultithread().validatePi(pi);
        long endTime = System.currentTimeMillis();
        System.out.println("Calculation took " + ((double)(endTime - startTime) / 1000) + " seconds.");
    }
   
    /**
     * This subclass is the thread that calculates a partial sum of pi from a
     * specified start iteration to a specified end iteration. The calculation
     * loop algorithm is based on the Chudnovsky brothers' formula for pi.
     */
    static class chudThread extends Thread {
        /**
         * This thread's partial sum
         */
        private Apfloat piPart = new Apfloat(0,precision);
        /**
         * the start iteration (inclusive)
         */
        private long start;
        /**
         * the end iteration (exclusive)
         */
        private long end;
        /**
         * The constructor.
         *
         * @param startI the starting iteration
         * @param endI the ending iteration
         */
        public chudThread(long startI, long endI) {
            start = startI;
            end = endI;
        }
        /**
         * This method sums pi from the start iteration to the end iteration.
         * It stores the result in the field <code>piPart</code>.
         */
        @Override
        public void run() {
            Apfloat x = new Apfloat(0,precision);
            Apfloat y = new Apfloat(0,precision);
            Apfloat a = new Apfloat(0,precision);
            Apfloat b = new Apfloat(0,precision);
            Apfloat c = new Apfloat(0,precision);
            Apfloat bn1 = new Apfloat(-1,precision);
            Apfloat b6 = new Apfloat(6,precision);
            Apfloat b13591409 = new Apfloat(13591409,precision);
            Apfloat b545140134 = new Apfloat(545140134,precision);
            Apfloat b3 = new Apfloat(3,precision);
            for(Apfloat i=new Apfloat(start,precision);i.compareTo(new Apfloat(end,precision))<0;i=i.add(new Apfloat(1))) {
                 a = negpow(bn1,i);
                 b = factorial((b6.multiply(i)));
                 c = b13591409.add(b545140134.multiply(i));
                 x = a.multiply(b.multiply(c));
                 a = factorial(b3.multiply(i));
                 b = ApfloatMath.pow(factorial(i),3);
                 c = new Apfloat(3.0/2.0,precision).add(new Apfloat(3,precision).multiply(i));
                 y = a.multiply(b).multiply(ApfloatMath.pow(new Apfloat(640320,precision),c));
                 piPart = piPart.add(x.divide(y));
            }
        }
    }
    public static void main(String[] args) throws InterruptedException, IOException {
        new PiChudnovskyMultithread().calculatePi();
    }
}

This code uses the Chudnovsky brothers' infinite series to calculate Pi. And I am doing this just for fun, it's not a school assignment. No seriously! :)

And as regards using two threads to operate on the same value, say that the user on a dual-core proc machine wants to do 20 iterations. The first core would calculate from iteration 0-10, the second from 10-20. I have tested this and it works, the question is whether or not it is faster to hard-code the number of threads or use the number of processors.


Top
  Profile  
 
 Post subject:
PostPosted: Tue Dec 02, 2008 6:59 pm 
SON OF A GUN
SON OF A GUN
User avatar

Joined: Mon Nov 01, 2004 5:41 am
Posts: 11605
I think I see what you are saying then... IF you have a dual core, or quad core, you could in theory break up the series into 2 or 4 pieces and then calculate each portion of the segment and then add them together again?

So each thread would be responsible for x values of the series?


Top
  Profile  
 
 Post subject:
PostPosted: Tue Dec 02, 2008 7:59 pm 
Little Foot
Little Foot
User avatar

Joined: Mon Jul 28, 2008 1:39 pm
Posts: 123
Yup, you got it. The iterations are divided equally among all the available cores.


Top
  Profile  
 
 Post subject:
PostPosted: Tue Dec 02, 2008 8:13 pm 
SON OF A GUN
SON OF A GUN
User avatar

Joined: Mon Nov 01, 2004 5:41 am
Posts: 11605
I would probably do it problematically then based on the number of available CPUs.

Try it and see what happens. I have a Quad core cpu I would be willing to try it out on.


Top
  Profile  
 
 Post subject:
PostPosted: Tue Dec 02, 2008 9:37 pm 
Little Foot
Little Foot
User avatar

Joined: Mon Jul 28, 2008 1:39 pm
Posts: 123
That would be great! I've been testing it using 100 iterations entered at the prompt. I have access myself to single core and dual core systems, which get a time of 52.766 seconds on my dual core, and 65.266 seconds on the single core. Note that in order to run it, you need the file pi.txt in the same directory as the program. That file is here.


Top
  Profile  
 
 Post subject:
PostPosted: Wed Dec 03, 2008 5:21 am 
SON OF A GUN
SON OF A GUN
User avatar

Joined: Mon Nov 01, 2004 5:41 am
Posts: 11605
Can you compile it or something? I don't have anything here to do that @ work.


Top
  Profile  
 
 Post subject:
PostPosted: Wed Dec 03, 2008 5:29 am 
SON OF A GUN
SON OF A GUN
User avatar

Joined: Mon Nov 01, 2004 5:41 am
Posts: 11605
I would be curious how your app compares to Super PI.

100 iterations gives you how many digits?

I told Super PI to get 1 Million digits and it claims it was 19 iterations (not sure what method it uses). I came back with ~ 22 seconds. (My work machine is a Core 2 Duo E6550 and I have 3.25 GB of ram)

SuperPI does not appear to be threaded at all. I at most see 50% cpu utilization. The second core never gets over 30 or 40% on a spike.


Top
  Profile  
 
 Post subject:
PostPosted: Wed Dec 03, 2008 7:10 am 
Little Foot
Little Foot
User avatar

Joined: Mon Jul 28, 2008 1:39 pm
Posts: 123
Yeah, superPi is written using an extremely efficient method called binary splitting, which I haven't implemented yet, but I would like to in the future. I'll compile it... here's the link:

http://wjqyxq.blu.livefilestore.com/y1pHeyKWFNMy7HNUSGTH-r-cVqNKdIjKomi0z-uRg7ajbY66OGptPHxHhPdPqHKSLtxuLkn1KqVHareUb4hodJyYA/piCalc.zip?download

It's a zip file with everything you need to run it. Open the .bat file to run the calculator, and enter 100 at the prompt. Thanks again!


Top
  Profile  
 
 Post subject:
PostPosted: Wed Dec 03, 2008 8:40 am 
SON OF A GUN
SON OF A GUN
User avatar

Joined: Mon Nov 01, 2004 5:41 am
Posts: 11605
Code:
Exception in thread "main" java.lang.UnsupportedClassVersionError: PiChudnovskyM
ultithread (Unsupported major.minor version 49.0)
        at java.lang.ClassLoader.defineClass0(Native Method)
        at java.lang.ClassLoader.defineClass(Unknown Source)
        at java.security.SecureClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.access$100(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClassInternal(Unknown Source)
Press any key to continue . . .


Top
  Profile  
 
 Post subject:
PostPosted: Wed Dec 03, 2008 4:24 pm 
Little Foot
Little Foot
User avatar

Joined: Mon Jul 28, 2008 1:39 pm
Posts: 123
OHH SHIT... totally forgot that you need the special Apfloat classes to run it...
http://www.apfloat.org/apfloat_java


Top
  Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC - 8 hours


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group