Java Yavaş mı? : Java’nın Performansı Üzerine – III

Bir önceki yazıdan devam edelim ve şimdi de Monte Carlo simulasyonu ile PI’ye yakınsamayı ele alalım.

Önce MonteCarloPI.cpp

/* 
 * File:   MonteCarloPI1.cpp
 * Author: akin
 * 
 * Created on October 7, 2015, 12:39 AM
 */

#include <iostream>
#include <stdlib.h>
#include <ctime>

namespace MonteCarloPI1 {
    
    using namespace std;

    int n;

    int main() {
        cout.precision(10);

        int dotsInCircle = 0;
        cout << "Number of points: " << endl;
        cin >> n;

        clock_t start = clock();

        for (int i = 0; i < n; i++) {
            double x = static_cast<double> (rand()) / static_cast<double> (RAND_MAX);
            double y = static_cast<double> (rand()) / static_cast<double> (RAND_MAX);

            double distance = x * x + y * y;
            if (distance <= 1.0)
                dotsInCircle++;
        }

        clock_t end = clock();
        int time = (int) (1000 * (end - start) / CLOCKS_PER_SEC);

        double myPi = (double) 4 * dotsInCircle / n;

        cout << "My PI is: " << myPi << endl;
        cout << "Time is: " << time << " ms." << endl;

        return 0;
    }
}

ve şimdi de MonteCarloPI.java

package org.javaturk.performance.algorithm.pi;

import java.util.Scanner;

import org.apache.commons.math.random.BitsStreamGenerator;
import org.apache.commons.math.random.MersenneTwister;

/**
 * Monte Carlo simulation to get closer to PI. It uses MersenneTwister to
 * produce random numbers. The implementation of this algorithm comes with
 * Apache's commons Math library.
 * 
 * @author akin
 *
 */
public class MonteCarloPI {
	private static long n;
	private static BitsStreamGenerator randomData = new MersenneTwister();

	public static void main(String[] args) {
		System.out.println("*** MonteCarloPI2 ***");
		System.out.print("Number of points: ");
		Scanner in = new Scanner(System.in);
		n = in.nextLong();
		calculatePI();
	}

	public static void calculatePI() {
		int dotsInCircle = 0;
		double start = System.currentTimeMillis();
		for (int i = 0; i < n; i++) {
			double x = randomData.nextDouble();
			double y = randomData.nextDouble();
			double distance = x * x + y * y;
			if (distance <= 1)
				dotsInCircle++;
		}
		double finish = System.currentTimeMillis();
		double seconds = (finish-start);
		double myPI = (double) 4*dotsInCircle/n;
		System.out.println("My PI is: " + myPI + " and Java's PI is: " + Math.PI);
		System.out.println("Time is: " + seconds);
	}
}

 

Monte Carlo simulasyonu ile PI’ye yakınsamak görüldüğü gibi çok daha basit ama çok güzel bir algoritmadır. Random veri oluşturmak dışında son derece basit bir for bloğu içinde bir if cümleciğinden oluşuyor. Random veri için Java’da Apache Commons Math’de bulunan MersenneTwister gerçekleştirmesini kullandım. Buna karşın C++’daki random veri üretimi ise standart kütüphanedeki gerçekleştirmeyi kullandım. Bu farklılığın performansa etkisinin ne kadar olacağını pek kestiremiyorum şu anda, daha fazla araştırmak gerekli.

Bu programın MacBook Pro’mdaki ölçümleri ise şöyle:

Program 10^6 10^7 10^8 10^9 2*10^9
MonteCarloPI.java 38 296 1,637 24,329 50,486
MonteCarloPI.cpp 21 214 2,404 33,898 81,899

 

Bu ölçümlerin de bir önceki SieveOfAtkin‘deki ölçümleri destekliyor olduğu açıktır.

Bu ölçümlerde bir şey dikkatinizi çekiyor mu? Girdi sayısı artarken performans ölçümlerinin Java lehine değişiyor olması bir tesadüf müdür acaba?

 

Toplam görüntülenme sayısı: 635