Я тестирую параллелизм в Java, моя цель - определить, действительно ли полезно иметь несколько потоков, однако я получаю результаты, которые не суммируются. Я пытаюсь оптимизировать функцию факториала, для этого конкретного теста я использую 1e9! и я хочу результат по модулю 1e9 + 7, чтобы он не переполнялся. Во-первых, я разделил число на основе number_of_threads и назначил каждому потоку их работу соответственно. Затем я делаю это нормально и сравниваю полученное время. Кажется, что когда number_of_threads = 4, я получаю лучшие результаты, чем версия без потоков, что имеет смысл, так как мой процессор имеет 4 ядра. Как и ожидалось, любое количество потоков больше 4 имеет более медленное время по сравнению с только 4. Однако при выполнении этого с менее чем 4 потоками результаты становятся слишком большими, например, с 1 потоком, я ожидаю, что он будет длиться так же, как и при выполнении. это без нити + накладные расходы. Без потока я получаю 6,2 секунды и 19,3 с 1 потоком, что является слишком большой разницей для того, чтобы это было просто издержками.
Чтобы проверить почему, я поставил некоторый счетчик на метод run, и кажется, чтоиногда выполнение только 1 цикла for внутри него занимает больше миллисекунды, и не должно, так как это всего лишь две операции плюс таймер.
public class Calc implements Runnable{
long min, max, mod, res;
Res r;
public Calc(long min, long max, long mod, Res r) {
this.min = min;
this.max = max;
this.mod = mod;
res = 1;
this.r = r;
}
public void run() {
for(long i = min; i <= max; i++) {
res *= i;
res %= mod;
}
r.addup(res);
}
}
public class Res{
long result;
long mod;
public Res(long mod) {
result = 1;
this.mod = mod;
}
public synchronized void addup(long add) {
result *= add;
result %= mod;
}
public long getResult() {
return result;
}
}
public class Main{
public static void main(String args[]) {
long startTime = System.nanoTime();
final long factorial = 1000000000L;
final long modulo = 1000000007L;
Res res = new Res(modulo);
int number_of_threads = 1;
Thread[] c = new Thread[number_of_threads];
long min = 1, max = factorial/(long)number_of_threads;
long cant = max;
for(int i = 0; i < number_of_threads; i++) {
if((long)i < (factorial % number_of_threads))max++;
c[i] = new Thread(new Calc(min, max, modulo, res));
c[i].start();
min = max +1;
max += cant;
}
for(int i = 0; i < number_of_threads; i++) {
try {
c[i].join();
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(res.getResult());
long endTime = System.nanoTime();
long totalTime = endTime - startTime;
System.out.println((double)totalTime/1000000000L);
}
}
Когда number_of_threads = 1, я получаю 19,3 секунды. Когда number_of_threads = 2, я получаю 10,1 секунды. Когда number_of_threads = 3, я получаю 7,1 секунды. Когда number_of_threads = 4, я получаю 5,4 секунды. И когда я делаю это без потоков, я получаю 6,2 секунды (я вычисляю время на этом с помощью того же метода)
Не должно быть такой большой разницы между только 1 потоком и без потоков, а для 2 и 3темы должны быть быстрее, чем нет темы. Почему это так и есть ли способ это исправить? Спасибо.
Редактировать: Добавление без версии потока
public class Main{
public static void main(String args[]) {
long startTime = System.nanoTime();
final long factorial = 1000000000L;
final long modulo = 1000000007L;
long res = 1;
for(long i = 1; i <= factorial; i++) {
res *= i;
res %= modulo;
}
System.out.println(res);
long endTime = System.nanoTime();
long totalTime = endTime - startTime;
System.out.println((double)totalTime/1000000000L);
}
}