Вперед: Я экспериментирую с ExecutorService для запуска нескольких потоков, а время вычислений много хуже с несколькими потоками, чем с одним потоком, поэтому я пытаюсь выяснить где я ошибся. Если детали не важны, пропустите длинную часть ниже, чтобы перейти к коду.android executorservice multithreading performance monte carlo оценка
Долгое время: я устанавливаю метод monte carlo вычисления площади круга с радиусом 1 для приближения значения PI. Я смоделировал его как симуляцию бросания дротиков на круг со случайными координатами x и y. При большом количестве бросков площадь круга может быть аппроксимирована количеством дротиков.
Я создал класс DartTosser, реализующий runnable, чтобы подбрасывать приращение общего количества дротиков, которые нужно бросить. Я создал объект с полем экземпляра и синхронизированный метод для агрегирования ударов дротиков из нескольких DartTossers. Когда все дротики были брошены, pi оценивается и возвращается.
Количество потоков и количество оттисков считываются с пользовательского ввода. Затем нажмите кнопку вызывает следующий метод:
private double estimatePi(int numThreads, long numTosses, TossBin bin){
long tossIncrement = numTosses/numThreads;
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
for (int i = 0; i < numThreads; i++){
executor.submit(new DartTosser(i, tossIncrement, bin));
}
executor.shutdown();
System.out.println("All dart tossers have begun tossing darts.");
try {
executor.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("All darts have been tossed.");
return (4*bin.getTotalInCircle())/((double)numTosses);
}
Класс DartTosser вызывает следующий метод в методе Run(), а затем добавляет общее количество бросков, которые попали в круг на экземпляр объекта TossBin:
private long startTossing(){
for (int i = 0; i < localTosses; i++){
// get two random doubles between -1 and 1
x = generateRandomNumber();
y = generateRandomNumber();
distanceSquared = (x*x) + (y*y);
if (distanceSquared <= 1.0){
tossesInCircle++;
}
}
return tossesInCircle;
}
Просто для полноты картины, это то, что мой класс TossBin выглядит следующим образом:
public class TossBin {
private long totalTossesInCircle = 0;
public TossBin(){
}
public synchronized void addToTotalTosses(long n){
this.totalTossesInCircle += n;
}
public void resetTossValues(){
this.totalTossesInCircle = 0;
}
public long getTotalInCircle(){
return totalTossesInCircle;
}
}
приближение PI близко, так что я думаю, что мои фактические расчеты хороши. Запустив один поток, он обработает 1 миллион томов примерно за 1600 миллисекунд или около того. Запустив два потока, он обработает 1 миллион томов примерно за 5600 миллисекунд или около того. Чем больше потоков, тем более неэффективно. Я могу видеть на выходе системы, что потоки (как представляется, работают) одновременно, но моя распараллеливание, очевидно, всевозможно разворачивается.
Я запускаю это на галактике S3, а также эмулятор от затмения, и я вижу ту же общую тенденцию. Есть предположения?
И просто чтобы убедиться, что я в эфире все мои потенциально грязных постельного белья:
public class DartTosser implements Runnable {
private int id;
private long localTosses = 0;
private long tossesInCircle = 0;
double x, y, distanceSquared;
TossBin globalBin;
private double generateRandomNumber(){
return (Math.random()*2.0)-1.0;
}
public DartTosser(int id, long tosses, TossBin globalBin){
this.id = id;
this.localTosses = tosses;
this.globalBin = globalBin;
}
private long startTossing(){
for (int i = 0; i < localTosses; i++){
// get two random doubles between -1 and 1
x = generateRandomNumber();
y = generateRandomNumber();
distanceSquared = (x*x) + (y*y);
if (distanceSquared <= 1.0){
tossesInCircle++;
}
}
return tossesInCircle;
}
@Override
public void run() {
System.out.println("Dart tosser number " + Integer.toString(id) + "starting work.");
globalBin.addToTotalTosses(startTossing());
System.out.println("Dart tosser number " + Integer.toString(id) + "finished work.");
}
}
Просто чтобы убедиться, вы вызываете метод 'addToTotalTosses' только тогда, когда один поток выполняется со всеми его выводами, не так ли? – Aert
Да! Я должен продолжать печатать. – Deranger
И вы не делитесь своим случайным генератором между потоками? – Aert