Я хотел изучить параллельное программирование для ускорения алгоритмов и выбрать Java.
Я написал две функции для суммирования long
целые числа в массиве - один простой итерационный массив, второй - разделение массива на части и суммирование частей в отдельных потоках.Многопользовательские потоки Java дают очень малый коэффициент усиления
Ожидалось, что логика будет примерно вдвое выше, используя два потока. Тем не менее, у меня есть только 24% скорости. Более того, используя больше потоков, я не получаю улучшения (возможно, менее 1%) по двум потокам. Я знаю, что должно быть создание потоков/присоединение накладных расходов, но я думаю, что это не должно быть так много.
Не могли бы вы объяснить, что мне не хватает или где ошибка в коде? Вот код:
import java.util.concurrent.ThreadLocalRandom;
public class ParallelTest {
public static long sum1 (long[] num, int a, int b) {
long r = 0;
while (a < b) {
r += num[a];
++a;
}
return r;
}
public static class SumThread extends Thread {
private long num[];
private long r;
private int a, b;
public SumThread (long[] num, int a, int b) {
super();
this.num = num;
this.a = a;
this.b = b;
}
@Override
public void run() {
r = ParallelTest.sum1(num, a, b);
}
public long getSum() {
return r;
}
}
public static long sum2 (long[] num, int a, int b, int threadCnt) throws InterruptedException {
SumThread[] th = new SumThread[threadCnt];
int i = 0, c = (b - a + threadCnt - 1)/threadCnt;
for (;;) {
int a2 = a + c;
if (a2 > b) {
a2 = b;
}
th[i] = new SumThread(num, a, a2);
th[i].start();
if (a2 == b) {
break;
}
a = a2;
++i;
}
for (i = 0; i < threadCnt; ++i) {
th[i].join();
}
long r = 0;
for (i = 0; i < threadCnt; ++i) {
r += th[i].getSum();
}
return r;
}
public static void main(String[] args) throws InterruptedException {
final int N = 230000000;
long[] num = new long[N];
for (int i = 0; i < N; ++i) {
num[i] = ThreadLocalRandom.current().nextLong(1, 9999);
}
// System.out.println(Runtime.getRuntime().availableProcessors());
long timestamp = System.nanoTime();
System.out.println(sum1(num, 0, num.length));
System.out.println(System.nanoTime() - timestamp);
for (int n = 2; n <= 4; ++n) {
timestamp = System.nanoTime();
System.out.println(sum2(num, 0, num.length, n));
System.out.println(System.nanoTime() - timestamp);
}
}
}
EDIT: Я есть i7 процессор с 4 ядрами (8 потоков). выхода задается кодом:
1149914787860
175689196
1149914787860
149224086
1149914787860
147709988
1149914787860
138243999
Это означает, что если бы у меня было больше задач с интенсивным процессором в цикле, тогда у меня будет лучшее усиление производительности с большим количеством потоков? – Somnium
@Somnium - правильный. – rcgldr