Несмотря на «разогрев» с помощью повторений и добавленную к алгоритму сложность, parallelSetAll()
выглядит здесь медленнее. Я на самом деле не пытаюсь микро-бенчмарк здесь, просто грубо чувствую, что происходит.Попытка сопоставить Java 8 parallelSetAll() vs setAll()
import java.util.*;
import java.time.*;
public class SlowParallelSetAll {
static final int SIZE = 20_000_000;
static long timeIt(Runnable test) {
Instant start = Instant.now();
test.run();
long millis = Duration.between(start, Instant.now()).toMillis();
System.out.println(millis);
return millis;
}
public static void main(String[] args) {
int reps = 10;
long[] la = new long[SIZE];
for(int i = 0; i < reps; i++)
timeIt(() -> Arrays.setAll(la, n -> n * n * 11 + n * 7));
System.out.println("###");
for(int i = 0; i < reps; i++)
timeIt(() -> Arrays.parallelSetAll(la, n -> n * n * 11 + n * 7));
}
}
/* Output:
38
37
35
34
35
34
35
34
34
35
###
52
42
43
44
46
46
44
44
43
43
*/
Алгоритм (лямбда-выражение) должен быть независимым, как она опирается только на значении индекса n
, и, следовательно, кажется, что он должен быть легко параллелизуемым.
Перемещение вызовов вокруг, чередуя оба подхода и т. Д., Дает разные результаты, но также кажется, что здесь есть что-то большее, чем просто микро-бенчмаркинг. Во-первых, я ожидал больших временных разниц между нормальной и параллельной версиями. Кроме того, кажется, что можно споткнуться о ситуациях, когда параллельная версия может показаться правильным выбором, но нормальная версия будет более подходящей. В основном я ищу некоторые сведения об этом --- в том числе есть ли простой способ показать, что то, что я вижу, является чисто феноменом микро-бенчмаркинга.
Для чего это стоит, здесь оно переписано для использования System.nanoTime()
и просто чередует тесты. Эти результаты кажутся разумными, хотя весь вопрос microbenchmarking обескураживает:
import java.util.*;
import java.time.*;
import java.util.concurrent.*;
public class SlowParallelSetAll {
static final int SIZE = 20_000_000;
static long timeIt(Runnable test) {
long start = System.nanoTime();
test.run();
long delta = System.nanoTime() - start;
long millis = TimeUnit.NANOSECONDS.toMillis(delta);
System.out.println(millis);
return millis;
}
public static void main(String[] args) {
int reps = 10;
long[] la = new long[SIZE];
for(int i = 0; i < reps; i++) {
timeIt(() -> Arrays.parallelSetAll(la, n -> n * n * 11 + n * 7));
timeIt(() -> Arrays.setAll(la, n -> n * n * 11 + n * 7));
}
}
}
/* Output:
41
74
41
73
41
67
40
67
40
67
41
67
41
67
40
67
40
67
40
67
*/
сколько медленнее? попробуйте изменить порядок вызовов и выполнить вызовы поочередно, а затем отменить этот порядок. Вы часто будете получать разные результаты. – JimmyJames
Какую систему вы выполняете? Например, если у вас есть только один процессор, вы бы ожидали, что параллельный алгоритм будет всегда медленнее, чем серийная версия, поскольку вы платите параллелизм накладные расходы без каких-либо преимуществ. – jacobm
Измерение времени с помощью Instant это, вероятно, не такая хорошая идея. Вы должны использовать нанотим. Или, что еще лучше, используйте надлежащий бенчмаркинг, например, jmh. – assylias