簡體   English   中英

多線程增加了計算時間 - Java

[英]Multithread increases calculation time - Java

我被要求根據處理問題的線程數檢查計算時間 因此,我編寫了一個使用蒙特卡羅方法計算積分的程序。 我正在划分線程數的范圍。 在那之后我統計線程,計算它們的部分,最后總結部分結果以得到一般的。

問題是計算時間隨線程數而不是減少而增加 (i7處理器,Windows 7)

一些人正在研究它,我們不知道為什么會這樣。 我希望有人能給我一個建議。 我附上代碼:

import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentLinkedQueue;


public class Runner {

private static final int MAXT = 10; // maksymalna ilość wątków
static PrintWriter outM;
static PrintWriter outMTime;

public static void main(String[] args){

    double xp = 2;
    double xk = 3;




    filesOp();

    // Wypisywanie kolumn tabeli
    for(int threadNumber=1; threadNumber<=MAXT; threadNumber++){
            outM.print("\t"+ threadNumber);
            outMTime.print("\t"+ threadNumber);
        }

    double time1;
    double time2;

    //double startTime=System.currentTimeMillis(); // Przed wystartowaniem programu

    for(int n=10000; n<=10000000; n=n*10){

        System.out.println("Licze dla: " + n + " punktow.");


            outM.print("\n"+n);
            outMTime.print("\n"+n);


        for(int threadNumber=1; threadNumber<=MAXT; threadNumber++){

            outM.print("\t");
            outMTime.print("\t");

            time1=System.nanoTime();
                multiThread(xp, xk, n, threadNumber);
            time2=System.nanoTime();

            outMTime.print((time2-time1)/1000000);
            // czas pracy dla danej liczby wątków

        }

    }

    outM.close();
    outMTime.close();

}


public static void multiThread(double xp, double xk, int n, int threadNumber){
    // Funkcja licząca całkę wielowątkowo.
    // Całka do policzenia jest dzielona pomiędzy wątki

    ArrayList<Thread> threadList = new ArrayList<Thread>();
    ConcurrentLinkedQueue<Double> results = new ConcurrentLinkedQueue<Double>();

    for(int i=0; i<threadNumber; i++){ 

        MonteCarlo mc = new MonteCarlo( xp+(i*((xk-xp)/threadNumber)), xp+((i+1)*((xk-xp)/threadNumber)), (int)(n/threadNumber), results);


        Thread t = new Thread(mc);
        threadList.add(t);
        t.start();

    }

    //for(int j=0; j<threadNumber; j++){ // pętla czeka na zakończenie wątków
    for(Thread t : threadList){
        try {
            //while(t.isAlive()){}
            //threadList.get(j).join();
            t.join();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    double wynik = 0;
    //for(int k=0; k<results.size(); k++){
    for(double r: results){ 
        //wynik = wynik + results.remove();
        wynik= wynik + r;
    }


    outM.print(wynik);
}



public static void filesOp(){
    File fileTemp;

    fileTemp = new File("wyniki.txt");
    if (fileTemp.exists()) fileTemp.delete();


    fileTemp = new File("pomiary.txt");
    if (fileTemp.exists()) fileTemp.delete();


    try {

        outM = new PrintWriter(new FileWriter("wyniki.txt", true));
        outMTime = new PrintWriter(new FileWriter("pomiary.txt", true));    
    } catch (Exception e) {
        e.printStackTrace();
    }
}


}


public class MonteCarlo implements Runnable{

    double xp; 
    double xk; 
    long n;
    ConcurrentLinkedQueue<Double> results;

    MonteCarlo(double xp, double xk, long n, ConcurrentLinkedQueue<Double> results){
        this.xp=xp;
        this.xk=xk;
        this.n=n;
        this.results=results;
    }

    //funkcja dla ktorej obliczamy calke
    private static double func(double x) {
        return x*x+3;
    }


    private static double funcIn(double x, double y) {
        if (( y > 0) && (y <= func(x)))
            return 1;
        else if (( y > 0) && (y <= func(x)))
            return -1;
        return 0;
    }

    //random number from a to b
    private static double randomPoint(double a, double b) {
        return  a + Math.random() * (b-a);
    }  

    public void run(){      
        double yp, yk, calka;
        int pointsIn;


        yp = 0;
        yk = Math.ceil(Math.max(func(xp), func(xk)));

        pointsIn = 0;

        for (long i=0; i<n; i++) {
        pointsIn += funcIn(randomPoint(xp, xk), randomPoint(yp, yk));
        }

        calka = (pointsIn / (double)n) * ((xk-xp) * (yk-yp));       

        results.add(calka);

        }


}

結果的例子:

1 2 3 4 5 6 7 8 9 10

10000 6.185818 2.821405 3.721287 3.470309 4.068365 3.604195 4.323075 4.192455 6.159694 4.239105

100000 10.994522 15.874134 34.992323 40.851124 36.199631 49.54579 45.122417 61.427132 55.845435 60.7661

1000000 108.653008 274.443662 340.274574 407.054352 437.455361 469.853467 496.849012 584.519687 571.09329 594.152023

10000000 1066.059033 2877.947652 3600.551966 4175.707089 4488.434247 5081.572093 5501.217804 6374.335759 6128.274553 6339.043475

問題最有可能在於

private static double randomPoint(double a, double b) {
    return  a + Math.random() * (b-a);
}  

Math.random()在激烈爭用下表現不佳。 如果您使用的是Java 7或更高版本,請嘗試以下方法:

private static double randomPoint(double a, double b) {
    return ThreadLocalRandom.current().nextDouble(a, b);
}

經常使用靜態函數是多線程中的一個陷阱。 可以在這篇文章中找到更一般的答案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM