Сообщение Re: Покажите, пожалуйста, профит от функционального программ от 04.08.2024 10:48
Изменено 04.08.2024 11:07 vsb
Re: Покажите, пожалуйста, профит от функционального программ
package test;
import static java.lang.Math.min;
import static java.lang.System.currentTimeMillis;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.DoubleSupplier;
import java.util.stream.IntStream;
public class Test {
public static void main(String[] args) {
run("Monte Carlo imperative", Test::monteCarloImperative, 5);
run("Monte Carlo functional single-threaded", () -> monteCarloFunctional(false), 10);
run("Monte Carlo functional multi-threaded", () -> monteCarloFunctional(true), 10);
}
static void run(String name, DoubleSupplier supplier, int count) {
long bestTimeMillis = Long.MAX_VALUE;
for (int counter = 0; counter < count; counter++) {
long startTimeMillis = currentTimeMillis();
supplier.getAsDouble();
long endTimeMillis = currentTimeMillis();
bestTimeMillis = min(bestTimeMillis, endTimeMillis - startTimeMillis);
}
System.out.printf("%s: best time %d ms%n", name, bestTimeMillis);
}
static final int ITERATIONS = 1_000_000_000;
static double monteCarloImperative() {
int hits = 0;
var random = ThreadLocalRandom.current();
for (int iteration = 0; iteration < ITERATIONS; iteration++) {
double x = random.nextDouble();
double y = random.nextDouble();
if (x * x + y * y <= 1) {
hits++;
}
}
return (double) hits / ITERATIONS * 4;
}
static double monteCarloFunctional(boolean parallel) {
record Point(double x, double y) {
}
IntStream stream;
if (parallel) {
stream = IntStream.range(0, ITERATIONS).parallel();
} else {
stream = IntStream.range(0, ITERATIONS);
}
long hits = stream
.mapToObj(iteration -> {
var random = ThreadLocalRandom.current();
return new Point(random.nextDouble(), random.nextDouble());
})
.filter(point -> point.x() * point.x() + point.y() * point.y() <= 1)
.count();
return (double) hits / ITERATIONS * 4;
}
}
Monte Carlo imperative: best time 3187 ms
Monte Carlo functional single-threaded: best time 7776 ms
Monte Carlo functional multi-threaded: best time 1097 ms
Функциональный стиль проигрывает примерно в 2.5 раза по скорости для однопоточного кода и выигрывает в 3 раза при использовании многопоточности.
Re: Покажите, пожалуйста, профит от функционального программ
package test;
import static java.lang.Math.PI;
import static java.lang.Math.abs;
import static java.lang.Math.min;
import static java.lang.System.currentTimeMillis;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.DoubleSupplier;
import java.util.stream.IntStream;
public class Test {
public static void main(String[] args) {
run("Monte Carlo imperative", Test::monteCarloImperative, 10);
run("Monte Carlo functional single-threaded", () -> monteCarloFunctional(false), 10);
run("Monte Carlo functional multi-threaded", () -> monteCarloFunctional(true), 10);
}
static void run(String name, DoubleSupplier supplier, int count) {
long bestTimeMillis = Long.MAX_VALUE;
for (int counter = 0; counter < count; counter++) {
long startTimeMillis = currentTimeMillis();
supplier.getAsDouble();
long endTimeMillis = currentTimeMillis();
bestTimeMillis = min(bestTimeMillis, endTimeMillis - startTimeMillis);
}
System.out.printf("%s: best time %d ms%n", name, bestTimeMillis);
}
static final int ITERATIONS = 1_000_000_000;
static double monteCarloImperative() {
int hits = 0;
var random = ThreadLocalRandom.current();
for (int iteration = 0; iteration < ITERATIONS; iteration++) {
double x = random.nextDouble();
double y = random.nextDouble();
if (x * x + y * y <= 1) {
hits++;
}
}
return (double) hits / ITERATIONS * 4;
}
static double monteCarloFunctional(boolean parallel) {
IntStream stream;
if (parallel) {
stream = IntStream.range(0, ITERATIONS).parallel();
} else {
stream = IntStream.range(0, ITERATIONS);
}
int hits = stream
.map(iteration -> {
var random = ThreadLocalRandom.current();
double x = random.nextDouble();
double y = random.nextDouble();
return x * x + y * y <= 1 ? 1 : 0;
})
.sum();
return (double) hits / ITERATIONS * 4;
}
}
Monte Carlo imperative: best time 3183 ms
Monte Carlo functional single-threaded: best time 3205 ms
Monte Carlo functional multi-threaded: best time 473 ms
Функциональный стиль не проигрывает императивному для однопоточного кода и выигрывает примерно в 7 раза при использовании 8-ядерного процессора.