From 11cc80192ec28530166e5292d1684125ca0de5b6 Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 16:40:44 +0000 Subject: [PATCH 1/9] Setting up GitHub Classroom Feedback From f904c6cee3f7d6b02e721f38cdbda0ce83e43c6d Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Tue, 30 Sep 2025 16:40:52 +0000 Subject: [PATCH 2/9] add deadline --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6495c30..0eb4312 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[![Review Assignment Due Date](https://classroom.github.com/assets/deadline-readme-button-22041afd0340ce965d47ae6ef1cefeee28c7c493a6346c4f15d667ab976d596c.svg)](https://classroom.github.com/a/AwTYhPar) # Лабораторная работа № 1: определение достижимости параллелизма и реализация параллельных алгоритмов. Шаги выполнения: From 16602c09853fc9f1673774a2c0609a0bc3113fbf Mon Sep 17 00:00:00 2001 From: DaniilStepanov Date: Wed, 1 Oct 2025 10:30:58 +0300 Subject: [PATCH 3/9] RandomGraphGenerator fix (cherry picked from commit a14bb99b347b181a405c97f9813fcf5f1e27d846) --- build.gradle.kts | 21 ++++++++- src/main/java/org/itmo/UnsafeCounter.java | 13 ++++++ .../java/org/itmo/RandomGraphGenerator.java | 45 ++++++++++++++++--- src/test/java/org/itmo/UnsafeCounterTest.java | 27 +++++++++++ 4 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 src/main/java/org/itmo/UnsafeCounter.java create mode 100644 src/test/java/org/itmo/UnsafeCounterTest.java diff --git a/build.gradle.kts b/build.gradle.kts index 3341beb..5370e10 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,6 @@ plugins { kotlin("jvm") version "1.9.20" + java application } @@ -12,6 +13,8 @@ repositories { dependencies { testImplementation(kotlin("test")) + testImplementation("org.openjdk.jcstress:jcstress-core:0.16") + testAnnotationProcessor("org.openjdk.jcstress:jcstress-core:0.16") } tasks.test { @@ -24,4 +27,20 @@ kotlin { application { mainClass.set("MainKt") -} \ No newline at end of file +} + +// JCStress runner task: runs JCStress tests located on the test runtime classpath +// Use: ./gradlew jcstress [-PjcstressArgs="-v -m quick"] +tasks.register("jcstress") { + group = "verification" + description = "Run JCStress stress tests" + mainClass.set("org.openjdk.jcstress.Main") + classpath = sourceSets.test.get().runtimeClasspath + dependsOn("testClasses") + + val argsProp = project.findProperty("jcstressArgs") as String? + if (!argsProp.isNullOrBlank()) { + args = argsProp.split("\\s+".toRegex()) + } +} + diff --git a/src/main/java/org/itmo/UnsafeCounter.java b/src/main/java/org/itmo/UnsafeCounter.java new file mode 100644 index 0000000..1041a21 --- /dev/null +++ b/src/main/java/org/itmo/UnsafeCounter.java @@ -0,0 +1,13 @@ +package org.itmo; + +public class UnsafeCounter { + private int counter = 0; + + public void increment() { + counter++; // <-- гонка данных + } + + public int get() { + return counter; + } +} diff --git a/src/test/java/org/itmo/RandomGraphGenerator.java b/src/test/java/org/itmo/RandomGraphGenerator.java index fdb888c..1a57226 100644 --- a/src/test/java/org/itmo/RandomGraphGenerator.java +++ b/src/test/java/org/itmo/RandomGraphGenerator.java @@ -1,7 +1,9 @@ package org.itmo; import java.util.Arrays; +import java.util.HashSet; import java.util.Random; +import java.util.Set; import java.util.SplittableRandom; import java.util.concurrent.ForkJoinPool; import java.util.stream.IntStream; @@ -11,22 +13,27 @@ public class RandomGraphGenerator { private long pack(int u, int v) { return (((long) u) << 32) | (v & 0xffffffffL); } + private int unpackU(long key) { return (int) (key >>> 32); } + private int unpackV(long key) { return (int) (key & 0xffffffffL); } Graph generateGraph(Random r, int size, int numEdges) { + if (size < 1) throw new IllegalArgumentException("size must be >= 1"); if (numEdges < size - 1) throw new IllegalArgumentException("We need min size-1 edges"); long maxDirected = (long) size * (size - 1); if (numEdges > maxDirected) throw new IllegalArgumentException("Too many edges for directed graph without self-loops"); - int[] perm = java.util.stream.IntStream.range(0, size).toArray(); - for (int i = size - 1; i > 1; i--) { - int j = 1 + r.nextInt(i); - int tmp = perm[i]; perm[i] = perm[j]; perm[j] = tmp; + int[] perm = IntStream.range(0, size).toArray(); + for (int i = size - 1; i > 0; i--) { + int j = r.nextInt(i + 1); + int tmp = perm[i]; + perm[i] = perm[j]; + perm[j] = tmp; } final int chainCount = size - 1; @@ -74,7 +81,7 @@ Graph generateGraph(Random r, int size, int numEdges) { while (unique < numEdges) { int missing = numEdges - unique; - int extra = Math.max(missing / 2, 10_000); // небольшой запас + int extra = Math.max(missing / 2, 10_000); int add = missing + extra; long[] more = new long[unique + add]; @@ -109,6 +116,31 @@ Graph generateGraph(Random r, int size, int numEdges) { keys = more; } + Set chainSet = new HashSet<>(chainCount * 2); + for (int i = 1; i < size; i++) { + chainSet.add(pack(perm[i - 1], perm[i])); + } + + int p = 0; + for (int i = 0; i < unique && p < chainCount; i++) { + long e = keys[i]; + if (chainSet.remove(e)) { + // swap keys[p] и keys[i] + long tmp = keys[p]; + keys[p] = keys[i]; + keys[i] = tmp; + p++; + } + } + + SplittableRandom shuf = base.split(); + for (int i = p; i < numEdges; i++) { + int j = i + shuf.nextInt(unique - i); + long tmp = keys[i]; + keys[i] = keys[j]; + keys[j] = tmp; + } + Graph g = new Graph(size); for (int i = 0; i < numEdges; i++) { long key = keys[i]; @@ -118,5 +150,4 @@ Graph generateGraph(Random r, int size, int numEdges) { } return g; } - -} +} \ No newline at end of file diff --git a/src/test/java/org/itmo/UnsafeCounterTest.java b/src/test/java/org/itmo/UnsafeCounterTest.java new file mode 100644 index 0000000..a831605 --- /dev/null +++ b/src/test/java/org/itmo/UnsafeCounterTest.java @@ -0,0 +1,27 @@ +package org.itmo; + +import org.openjdk.jcstress.annotations.*; +import org.openjdk.jcstress.infra.results.I_Result; + +@JCStressTest +@Outcome(id = "5", expect = Expect.ACCEPTABLE, desc = "Все 5 инкрементов выполнены корректно") +@Outcome(id = "1", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Гонка данных: часть инкрементов потерялась") +@Outcome(id = "2", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Гонка данных: часть инкрементов потерялась") +@Outcome(id = "3", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Гонка данных: часть инкрементов потерялась") +@Outcome(id = "4", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Гонка данных: часть инкрементов потерялась") +@State +public class UnsafeCounterTest { + + private UnsafeCounter counter = new UnsafeCounter(); + + @Actor public void actor1() { counter.increment(); } + @Actor public void actor2() { counter.increment(); } + @Actor public void actor3() { counter.increment(); } + @Actor public void actor4() { counter.increment(); } + @Actor public void actor5() { counter.increment(); } + + @Arbiter + public void arbiter(I_Result r) { + r.r1 = counter.get(); + } +} From ede1988b8a4e71c16d906949561016d06292f3e5 Mon Sep 17 00:00:00 2001 From: "ar.r.lysenko" Date: Sat, 4 Oct 2025 22:49:28 +0300 Subject: [PATCH 4/9] refactor task --- build.gradle.kts | 2 +- src/main/java/org/itmo/Graph.java | 35 +++++-------------- src/main/java/org/itmo/bfs/Bfs.java | 7 ++++ .../java/org/itmo/bfs/impl/ParallelBfs.java | 12 +++++++ .../java/org/itmo/bfs/impl/SimpleBfs.java | 31 ++++++++++++++++ src/test/java/org/itmo/BFSTest.java | 17 ++++----- .../java/org/itmo/RandomGraphGenerator.java | 2 +- tmp/results.txt | 14 +++++--- 8 files changed, 76 insertions(+), 44 deletions(-) create mode 100644 src/main/java/org/itmo/bfs/Bfs.java create mode 100644 src/main/java/org/itmo/bfs/impl/ParallelBfs.java create mode 100644 src/main/java/org/itmo/bfs/impl/SimpleBfs.java diff --git a/build.gradle.kts b/build.gradle.kts index 5370e10..4716601 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -22,7 +22,7 @@ tasks.test { } kotlin { - jvmToolchain(8) + jvmToolchain(21) } application { diff --git a/src/main/java/org/itmo/Graph.java b/src/main/java/org/itmo/Graph.java index 141a0b6..8c3de6c 100644 --- a/src/main/java/org/itmo/Graph.java +++ b/src/main/java/org/itmo/Graph.java @@ -1,16 +1,13 @@ package org.itmo; import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -class Graph { - private final int V; +public class Graph { + private final int size; private final ArrayList[] adjList; Graph(int vertices) { - this.V = vertices; + this.size = vertices; adjList = new ArrayList[vertices]; for (int i = 0; i < vertices; ++i) { adjList[i] = new ArrayList<>(); @@ -23,28 +20,12 @@ void addEdge(int src, int dest) { } } - void parallelBFS(int startVertex) { + public int getSize() { + return size; } - //Generated by ChatGPT - void bfs(int startVertex) { - boolean[] visited = new boolean[V]; - - LinkedList queue = new LinkedList<>(); - - visited[startVertex] = true; - queue.add(startVertex); - - while (!queue.isEmpty()) { - startVertex = queue.poll(); - - for (int n : adjList[startVertex]) { - if (!visited[n]) { - visited[n] = true; - queue.add(n); - } - } - } + // not safe, but today I don't care + public ArrayList[] getAdjList() { + return adjList; } - } diff --git a/src/main/java/org/itmo/bfs/Bfs.java b/src/main/java/org/itmo/bfs/Bfs.java new file mode 100644 index 0000000..1970d86 --- /dev/null +++ b/src/main/java/org/itmo/bfs/Bfs.java @@ -0,0 +1,7 @@ +package org.itmo.bfs; + +import org.itmo.Graph; + +public interface Bfs { + void bfs(Graph graph, int startVertex); +} diff --git a/src/main/java/org/itmo/bfs/impl/ParallelBfs.java b/src/main/java/org/itmo/bfs/impl/ParallelBfs.java new file mode 100644 index 0000000..bc9606a --- /dev/null +++ b/src/main/java/org/itmo/bfs/impl/ParallelBfs.java @@ -0,0 +1,12 @@ +package org.itmo.bfs.impl; + +import org.itmo.Graph; +import org.itmo.bfs.Bfs; + +public class ParallelBfs implements Bfs { + + @Override + public void bfs(Graph graph, int startVertex) { + + } +} diff --git a/src/main/java/org/itmo/bfs/impl/SimpleBfs.java b/src/main/java/org/itmo/bfs/impl/SimpleBfs.java new file mode 100644 index 0000000..21f3d31 --- /dev/null +++ b/src/main/java/org/itmo/bfs/impl/SimpleBfs.java @@ -0,0 +1,31 @@ +package org.itmo.bfs.impl; + +import java.util.LinkedList; +import org.itmo.Graph; +import org.itmo.bfs.Bfs; + +public class SimpleBfs implements Bfs { + + //Generated by ChatGPT + @Override + public void bfs(Graph graph, int startVertex) { + boolean[] visited = new boolean[graph.getSize()]; + + LinkedList queue = new LinkedList<>(); + + visited[startVertex] = true; + queue.add(startVertex); + + var adjList = graph.getAdjList(); + while (!queue.isEmpty()) { + startVertex = queue.poll(); + + for (int n : adjList[startVertex]) { + if (!visited[n]) { + visited[n] = true; + queue.add(n); + } + } + } + } +} diff --git a/src/test/java/org/itmo/BFSTest.java b/src/test/java/org/itmo/BFSTest.java index 7bf9098..9dc6e41 100644 --- a/src/test/java/org/itmo/BFSTest.java +++ b/src/test/java/org/itmo/BFSTest.java @@ -1,14 +1,11 @@ package org.itmo; -import org.junit.jupiter.api.Test; - import java.io.FileWriter; import java.io.IOException; -import java.nio.Buffer; -import java.util.HashSet; import java.util.Random; -import java.util.function.BiFunction; -import java.util.stream.IntStream; +import org.itmo.bfs.impl.ParallelBfs; +import org.itmo.bfs.impl.SimpleBfs; +import org.junit.jupiter.api.Test; public class BFSTest { @@ -34,19 +31,19 @@ public void bfsTest() throws IOException { } } - private long executeSerialBfsAndGetTime(Graph g) { + var bfs = new SimpleBfs(); long startTime = System.currentTimeMillis(); - g.bfs(0); + bfs.bfs(g, 0); long endTime = System.currentTimeMillis(); return endTime - startTime; } private long executeParallelBfsAndGetTime(Graph g) { + var bfs = new ParallelBfs(); long startTime = System.currentTimeMillis(); - g.parallelBFS(0); + bfs.bfs(g, 0); long endTime = System.currentTimeMillis(); return endTime - startTime; } - } diff --git a/src/test/java/org/itmo/RandomGraphGenerator.java b/src/test/java/org/itmo/RandomGraphGenerator.java index 1a57226..11c5049 100644 --- a/src/test/java/org/itmo/RandomGraphGenerator.java +++ b/src/test/java/org/itmo/RandomGraphGenerator.java @@ -150,4 +150,4 @@ Graph generateGraph(Random r, int size, int numEdges) { } return g; } -} \ No newline at end of file +} diff --git a/tmp/results.txt b/tmp/results.txt index 027e7f9..c02a280 100644 --- a/tmp/results.txt +++ b/tmp/results.txt @@ -11,22 +11,26 @@ Serial: 1 Parallel: 0 -------- Times for 10000 vertices and 50000 connections: -Serial: 3 +Serial: 4 Parallel: 0 -------- Times for 10000 vertices and 100000 connections: -Serial: 2 +Serial: 3 Parallel: 0 -------- Times for 50000 vertices and 1000000 connections: -Serial: 30 +Serial: 22 Parallel: 0 -------- Times for 100000 vertices and 1000000 connections: -Serial: 18 +Serial: 21 Parallel: 0 -------- Times for 1000000 vertices and 10000000 connections: -Serial: 307 +Serial: 419 +Parallel: 0 +-------- +Times for 2000000 vertices and 10000000 connections: +Serial: 755 Parallel: 0 -------- From 6292a3896c8b40fb27ab468ace07d094a7e0d205 Mon Sep 17 00:00:00 2001 From: "ar.r.lysenko" Date: Sun, 5 Oct 2025 18:24:40 +0300 Subject: [PATCH 5/9] add forkjoin impl on parallel streams --- .../java/org/itmo/bfs/impl/ForkJoinBfs.java | 33 ++++++++++++++ src/test/java/org/itmo/BFSTest.java | 45 ++++++++++++++++--- 2 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 src/main/java/org/itmo/bfs/impl/ForkJoinBfs.java diff --git a/src/main/java/org/itmo/bfs/impl/ForkJoinBfs.java b/src/main/java/org/itmo/bfs/impl/ForkJoinBfs.java new file mode 100644 index 0000000..df265ba --- /dev/null +++ b/src/main/java/org/itmo/bfs/impl/ForkJoinBfs.java @@ -0,0 +1,33 @@ +package org.itmo.bfs.impl; + +import java.util.Collection; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicIntegerArray; +import org.itmo.Graph; +import org.itmo.bfs.Bfs; + +public class ForkJoinBfs implements Bfs { + + @Override + public void bfs(Graph graph, int startVertex) { + var visited = new AtomicIntegerArray(graph.getSize()); + visited.set(startVertex, 1); + + // we can use faster collection, bz we don't remove elements and queue is sequential (linearizable) on CAS + Collection frontier = new ConcurrentLinkedQueue<>(); + frontier.add(startVertex); + + while (!frontier.isEmpty()) { + Queue nextFrontier = new ConcurrentLinkedQueue<>(); + + // actually this need bulk optimization for unbalanced graphs + frontier.parallelStream() + .flatMap(v -> graph.getAdjList()[v].stream()) + .filter(neighbor -> visited.compareAndSet(neighbor, 0, 1)) + .forEach(nextFrontier::add); + + frontier = nextFrontier; + } + } +} diff --git a/src/test/java/org/itmo/BFSTest.java b/src/test/java/org/itmo/BFSTest.java index 9dc6e41..2c4f00a 100644 --- a/src/test/java/org/itmo/BFSTest.java +++ b/src/test/java/org/itmo/BFSTest.java @@ -3,12 +3,31 @@ import java.io.FileWriter; import java.io.IOException; import java.util.Random; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ForkJoinPool; +import org.itmo.bfs.impl.ForkJoinBfs; import org.itmo.bfs.impl.ParallelBfs; import org.itmo.bfs.impl.SimpleBfs; import org.junit.jupiter.api.Test; public class BFSTest { + @Test + public void kek() { + int size = 1_000_000; + int connections = 10_000_000; + + Random r = new Random(42); + + var g = new RandomGraphGenerator().generateGraph(r, size, connections); + + long time1 = executeSerialBfsAndGetTime(g); + long time2 = executeForkJoinBfs(g); + + System.out.println("Serial " + time1); + System.out.println("ForkJoin " + time2); + } + @Test public void bfsTest() throws IOException { int[] sizes = new int[]{10, 100, 1000, 10_000, 10_000, 50_000, 100_000, 1_000_000, 2_000_000}; @@ -33,17 +52,29 @@ public void bfsTest() throws IOException { private long executeSerialBfsAndGetTime(Graph g) { var bfs = new SimpleBfs(); - long startTime = System.currentTimeMillis(); + long startTime = System.nanoTime(); bfs.bfs(g, 0); - long endTime = System.currentTimeMillis(); - return endTime - startTime; + long endTime = System.nanoTime(); + return (endTime - startTime) / 1_000_000; } private long executeParallelBfsAndGetTime(Graph g) { - var bfs = new ParallelBfs(); - long startTime = System.currentTimeMillis(); + var bfs = new ParallelBfs(1); + long startTime = System.nanoTime(); bfs.bfs(g, 0); - long endTime = System.currentTimeMillis(); - return endTime - startTime; + long endTime = System.nanoTime(); + return (endTime - startTime) / 1_000_000; + } + + private long executeForkJoinBfs(Graph g) { + var bfs = new ForkJoinBfs(); + long startTime = System.nanoTime(); + try { + ForkJoinPool.commonPool().submit(() -> bfs.bfs(g, 0)).get(); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + long endTime = System.nanoTime(); + return (endTime - startTime) / 1_000_000; } } From 96590b473e611e2a7d9809f13198819a9b7d92c2 Mon Sep 17 00:00:00 2001 From: "ar.r.lysenko" Date: Sun, 5 Oct 2025 20:40:54 +0300 Subject: [PATCH 6/9] add parallel impl, but it sucks --- .../java/org/itmo/bfs/impl/ParallelBfs.java | 69 +++++++++++++++++++ src/test/java/org/itmo/BFSTest.java | 23 ++++++- tmp/results.txt | 41 ++++++----- 3 files changed, 116 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/itmo/bfs/impl/ParallelBfs.java b/src/main/java/org/itmo/bfs/impl/ParallelBfs.java index bc9606a..5aa211e 100644 --- a/src/main/java/org/itmo/bfs/impl/ParallelBfs.java +++ b/src/main/java/org/itmo/bfs/impl/ParallelBfs.java @@ -1,12 +1,81 @@ package org.itmo.bfs.impl; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicIntegerArray; +import java.util.stream.IntStream; import org.itmo.Graph; import org.itmo.bfs.Bfs; public class ParallelBfs implements Bfs { + private final int threadNumber; + + public ParallelBfs(int threadNumber) { + this.threadNumber = threadNumber; + } + @Override public void bfs(Graph graph, int startVertex) { + AtomicInteger activeNodes = new AtomicInteger(1); + AtomicIntegerArray distances = new AtomicIntegerArray(graph.getSize()); + ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>(); + + queue.add(startVertex); + + IntStream.range(0, threadNumber) + .mapToObj(i -> + new Thread(new BfsWorker(graph, distances, queue, activeNodes)) + ) + .peek(Thread::start) + .forEach(thread -> { + try { + thread.join(); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + + private record BfsWorker( + Graph graph, + AtomicIntegerArray distances, + Queue queue, + AtomicInteger activeNodes + ) implements Runnable { + + @Override + public void run() { + var adjList = graph.getAdjList(); + while (activeNodes.get() > 0) { + var currentVertex = queue.poll(); + if (currentVertex == null) { + continue; + } + int d = distances.get(currentVertex); + for (var neighbor : adjList[currentVertex]) { + if (updateDistanceIfLower(neighbor, d - 1)) { + queue.add(neighbor); + activeNodes.incrementAndGet(); + } + } + activeNodes.decrementAndGet(); + } + } + + private boolean updateDistanceIfLower(int node, int newDistance) { + while (true) { + int currentDistance = distances.get(node); + + if (newDistance >= currentDistance || currentDistance != 0) { + return false; + } + if (distances.compareAndSet(node, currentDistance, newDistance)) { + return true; + } + } + } } } diff --git a/src/test/java/org/itmo/BFSTest.java b/src/test/java/org/itmo/BFSTest.java index 2c4f00a..4aa5557 100644 --- a/src/test/java/org/itmo/BFSTest.java +++ b/src/test/java/org/itmo/BFSTest.java @@ -28,6 +28,24 @@ public void kek() { System.out.println("ForkJoin " + time2); } + @Test + public void lotOfConnectionsTest() { + int size = 1_000_000; + int connections = 15_000_000; + Random r = new Random(42); + + System.out.println("Generating graph of size " + size + " ...wait"); + Graph g = new RandomGraphGenerator().generateGraph(r, size, connections); + System.out.println("Generation completed!\nStarting bfs"); + + long serialTime = executeSerialBfsAndGetTime(g); + long parallelTime = executeParallelBfsAndGetTime(g); + + System.out.println("Times for " + size + " vertices and " + connections + " connections: "); + System.out.println("Serial: " + serialTime); + System.out.println("Parallel: " + parallelTime); + } + @Test public void bfsTest() throws IOException { int[] sizes = new int[]{10, 100, 1000, 10_000, 10_000, 50_000, 100_000, 1_000_000, 2_000_000}; @@ -40,9 +58,11 @@ public void bfsTest() throws IOException { Graph g = new RandomGraphGenerator().generateGraph(r, sizes[i], connections[i]); System.out.println("Generation completed!\nStarting bfs"); long serialTime = executeSerialBfsAndGetTime(g); + long forkJoinTime = executeForkJoinBfs(g); long parallelTime = executeParallelBfsAndGetTime(g); fw.append("Times for " + sizes[i] + " vertices and " + connections[i] + " connections: "); fw.append("\nSerial: " + serialTime); + fw.append("\nForkJoin: " + forkJoinTime); fw.append("\nParallel: " + parallelTime); fw.append("\n--------\n"); } @@ -59,7 +79,8 @@ private long executeSerialBfsAndGetTime(Graph g) { } private long executeParallelBfsAndGetTime(Graph g) { - var bfs = new ParallelBfs(1); + var runtime = Runtime.getRuntime().availableProcessors() * 2; + var bfs = new ParallelBfs(runtime); long startTime = System.nanoTime(); bfs.bfs(g, 0); long endTime = System.nanoTime(); diff --git a/tmp/results.txt b/tmp/results.txt index c02a280..63d5f29 100644 --- a/tmp/results.txt +++ b/tmp/results.txt @@ -1,36 +1,45 @@ Times for 10 vertices and 50 connections: Serial: 0 -Parallel: 0 +ForkJoin: 3 +Parallel: 6 -------- Times for 100 vertices and 500 connections: -Serial: 0 -Parallel: 0 +Serial: 1 +ForkJoin: 1 +Parallel: 38 -------- Times for 1000 vertices and 5000 connections: -Serial: 1 -Parallel: 0 +Serial: 2 +ForkJoin: 2 +Parallel: 19 -------- Times for 10000 vertices and 50000 connections: Serial: 4 -Parallel: 0 +ForkJoin: 18 +Parallel: 10 -------- Times for 10000 vertices and 100000 connections: -Serial: 3 -Parallel: 0 +Serial: 2 +ForkJoin: 17 +Parallel: 11 -------- Times for 50000 vertices and 1000000 connections: -Serial: 22 -Parallel: 0 +Serial: 27 +ForkJoin: 15 +Parallel: 34 -------- Times for 100000 vertices and 1000000 connections: -Serial: 21 -Parallel: 0 +Serial: 33 +ForkJoin: 30 +Parallel: 40 -------- Times for 1000000 vertices and 10000000 connections: -Serial: 419 -Parallel: 0 +Serial: 600 +ForkJoin: 251 +Parallel: 649 -------- Times for 2000000 vertices and 10000000 connections: -Serial: 755 -Parallel: 0 +Serial: 932 +ForkJoin: 539 +Parallel: 971 -------- From a1ef4db1e766205416b7ee50b2e4a2192b7fc1ec Mon Sep 17 00:00:00 2001 From: "ar.r.lysenko" Date: Mon, 6 Oct 2025 23:18:02 +0300 Subject: [PATCH 7/9] add butching --- .../itmo/bfs/impl/ParallelFrontierBfs.java | 69 +++++++++++++++++++ src/test/java/org/itmo/BFSTest.java | 50 ++++---------- tmp/results.txt | 59 +++++++++------- 3 files changed, 117 insertions(+), 61 deletions(-) create mode 100644 src/main/java/org/itmo/bfs/impl/ParallelFrontierBfs.java diff --git a/src/main/java/org/itmo/bfs/impl/ParallelFrontierBfs.java b/src/main/java/org/itmo/bfs/impl/ParallelFrontierBfs.java new file mode 100644 index 0000000..73f4edd --- /dev/null +++ b/src/main/java/org/itmo/bfs/impl/ParallelFrontierBfs.java @@ -0,0 +1,69 @@ +package org.itmo.bfs.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicIntegerArray; +import org.itmo.Graph; +import org.itmo.bfs.Bfs; + +public class ParallelFrontierBfs implements Bfs { + + private final int threadNumber; + + public ParallelFrontierBfs(int threadNumber) { + this.threadNumber = threadNumber; + } + + @Override + public void bfs(Graph graph, int startVertex) { + var adjList = graph.getAdjList(); + var visited = new AtomicIntegerArray(graph.getSize()); + visited.set(startVertex, 1); + + Collection frontier = new ArrayList<>(); + frontier.add(startVertex); + + try (var es = Executors.newFixedThreadPool(threadNumber)) { + while (!frontier.isEmpty()) { + // queue is bad for large parallelism factor + Queue nextFrontier = new ConcurrentLinkedQueue<>(); + + var butchSize = Math.max(1, frontier.size() / threadNumber); + + List> futures = new ArrayList<>(); + for (int i = 0; i < frontier.size(); i += butchSize) { + var startIndex = i; + var lastIndex = Math.min(i + butchSize, frontier.size()); + + var future = es.submit(() -> + { + for (int vertex = startIndex; vertex < lastIndex; vertex++) { + for (int neighbor : adjList[vertex]) { + if (visited.compareAndSet(neighbor, 0, 1)) { + nextFrontier.add(neighbor); + } + } + } + } + ); + + futures.add(future); + } + + for (Future f : futures) { + f.get(); + } + + frontier = nextFrontier; + } + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/test/java/org/itmo/BFSTest.java b/src/test/java/org/itmo/BFSTest.java index 4aa5557..0909972 100644 --- a/src/test/java/org/itmo/BFSTest.java +++ b/src/test/java/org/itmo/BFSTest.java @@ -7,45 +7,12 @@ import java.util.concurrent.ForkJoinPool; import org.itmo.bfs.impl.ForkJoinBfs; import org.itmo.bfs.impl.ParallelBfs; +import org.itmo.bfs.impl.ParallelFrontierBfs; import org.itmo.bfs.impl.SimpleBfs; import org.junit.jupiter.api.Test; public class BFSTest { - @Test - public void kek() { - int size = 1_000_000; - int connections = 10_000_000; - - Random r = new Random(42); - - var g = new RandomGraphGenerator().generateGraph(r, size, connections); - - long time1 = executeSerialBfsAndGetTime(g); - long time2 = executeForkJoinBfs(g); - - System.out.println("Serial " + time1); - System.out.println("ForkJoin " + time2); - } - - @Test - public void lotOfConnectionsTest() { - int size = 1_000_000; - int connections = 15_000_000; - Random r = new Random(42); - - System.out.println("Generating graph of size " + size + " ...wait"); - Graph g = new RandomGraphGenerator().generateGraph(r, size, connections); - System.out.println("Generation completed!\nStarting bfs"); - - long serialTime = executeSerialBfsAndGetTime(g); - long parallelTime = executeParallelBfsAndGetTime(g); - - System.out.println("Times for " + size + " vertices and " + connections + " connections: "); - System.out.println("Serial: " + serialTime); - System.out.println("Parallel: " + parallelTime); - } - @Test public void bfsTest() throws IOException { int[] sizes = new int[]{10, 100, 1000, 10_000, 10_000, 50_000, 100_000, 1_000_000, 2_000_000}; @@ -59,10 +26,12 @@ public void bfsTest() throws IOException { System.out.println("Generation completed!\nStarting bfs"); long serialTime = executeSerialBfsAndGetTime(g); long forkJoinTime = executeForkJoinBfs(g); + long frontierTime = executeParallelFrontierBfsAndGetTime(g); long parallelTime = executeParallelBfsAndGetTime(g); fw.append("Times for " + sizes[i] + " vertices and " + connections[i] + " connections: "); fw.append("\nSerial: " + serialTime); fw.append("\nForkJoin: " + forkJoinTime); + fw.append("\nFrontier: " + frontierTime); fw.append("\nParallel: " + parallelTime); fw.append("\n--------\n"); } @@ -87,11 +56,20 @@ private long executeParallelBfsAndGetTime(Graph g) { return (endTime - startTime) / 1_000_000; } + private long executeParallelFrontierBfsAndGetTime(Graph g) { + var runtime = Runtime.getRuntime().availableProcessors() * 2; + var bfs = new ParallelFrontierBfs(runtime); + long startTime = System.nanoTime(); + bfs.bfs(g, 0); + long endTime = System.nanoTime(); + return (endTime - startTime) / 1_000_000; + } + private long executeForkJoinBfs(Graph g) { var bfs = new ForkJoinBfs(); long startTime = System.nanoTime(); - try { - ForkJoinPool.commonPool().submit(() -> bfs.bfs(g, 0)).get(); + try (var pool = ForkJoinPool.commonPool()) { + pool.submit(() -> bfs.bfs(g, 0)).get(); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); } diff --git a/tmp/results.txt b/tmp/results.txt index 63d5f29..a54ef5e 100644 --- a/tmp/results.txt +++ b/tmp/results.txt @@ -1,45 +1,54 @@ Times for 10 vertices and 50 connections: Serial: 0 -ForkJoin: 3 -Parallel: 6 +ForkJoin: 1 +Frontier: 2 +Parallel: 5 -------- Times for 100 vertices and 500 connections: -Serial: 1 -ForkJoin: 1 -Parallel: 38 +Serial: 0 +ForkJoin: 0 +Frontier: 3 +Parallel: 4 -------- Times for 1000 vertices and 5000 connections: -Serial: 2 -ForkJoin: 2 -Parallel: 19 +Serial: 0 +ForkJoin: 1 +Frontier: 4 +Parallel: 4 -------- Times for 10000 vertices and 50000 connections: Serial: 4 -ForkJoin: 18 -Parallel: 10 +ForkJoin: 17 +Frontier: 8 +Parallel: 18 -------- Times for 10000 vertices and 100000 connections: -Serial: 2 -ForkJoin: 17 -Parallel: 11 +Serial: 1 +ForkJoin: 2 +Frontier: 41 +Parallel: 24 -------- Times for 50000 vertices and 1000000 connections: -Serial: 27 -ForkJoin: 15 -Parallel: 34 +Serial: 22 +ForkJoin: 24 +Frontier: 50 +Parallel: 58 -------- Times for 100000 vertices and 1000000 connections: -Serial: 33 -ForkJoin: 30 -Parallel: 40 +Serial: 35 +ForkJoin: 28 +Frontier: 29 +Parallel: 46 -------- Times for 1000000 vertices and 10000000 connections: -Serial: 600 -ForkJoin: 251 -Parallel: 649 +Serial: 649 +ForkJoin: 286 +Frontier: 279 +Parallel: 587 -------- Times for 2000000 vertices and 10000000 connections: -Serial: 932 -ForkJoin: 539 -Parallel: 971 +Serial: 930 +ForkJoin: 555 +Frontier: 420 +Parallel: 964 -------- From e9bfdc959121bdb35df925c77d1c6f8f97523153 Mon Sep 17 00:00:00 2001 From: "ar.r.lysenko" Date: Mon, 6 Oct 2025 23:44:15 +0300 Subject: [PATCH 8/9] fix bug --- .../itmo/bfs/impl/ParallelFrontierBfs.java | 14 ++--- tmp/results.txt | 62 +++++++++---------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/main/java/org/itmo/bfs/impl/ParallelFrontierBfs.java b/src/main/java/org/itmo/bfs/impl/ParallelFrontierBfs.java index 73f4edd..d00ff87 100644 --- a/src/main/java/org/itmo/bfs/impl/ParallelFrontierBfs.java +++ b/src/main/java/org/itmo/bfs/impl/ParallelFrontierBfs.java @@ -1,10 +1,8 @@ package org.itmo.bfs.impl; import java.util.ArrayList; -import java.util.Collection; +import java.util.Collections; import java.util.List; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -26,13 +24,15 @@ public void bfs(Graph graph, int startVertex) { var visited = new AtomicIntegerArray(graph.getSize()); visited.set(startVertex, 1); - Collection frontier = new ArrayList<>(); + List frontier = new ArrayList<>(); frontier.add(startVertex); try (var es = Executors.newFixedThreadPool(threadNumber)) { while (!frontier.isEmpty()) { - // queue is bad for large parallelism factor - Queue nextFrontier = new ConcurrentLinkedQueue<>(); + final List currentFrontier = frontier; + + // we only need write synchronization, java doesn't have such list, writing it vpadlu + List nextFrontier = Collections.synchronizedList(new ArrayList<>()); var butchSize = Math.max(1, frontier.size() / threadNumber); @@ -44,7 +44,7 @@ public void bfs(Graph graph, int startVertex) { var future = es.submit(() -> { for (int vertex = startIndex; vertex < lastIndex; vertex++) { - for (int neighbor : adjList[vertex]) { + for (int neighbor : adjList[currentFrontier.get(vertex)]) { if (visited.compareAndSet(neighbor, 0, 1)) { nextFrontier.add(neighbor); } diff --git a/tmp/results.txt b/tmp/results.txt index a54ef5e..374c3f1 100644 --- a/tmp/results.txt +++ b/tmp/results.txt @@ -2,53 +2,53 @@ Times for 10 vertices and 50 connections: Serial: 0 ForkJoin: 1 Frontier: 2 -Parallel: 5 +Parallel: 3 -------- Times for 100 vertices and 500 connections: Serial: 0 -ForkJoin: 0 -Frontier: 3 -Parallel: 4 +ForkJoin: 6 +Frontier: 7 +Parallel: 3 -------- Times for 1000 vertices and 5000 connections: Serial: 0 -ForkJoin: 1 -Frontier: 4 -Parallel: 4 +ForkJoin: 2 +Frontier: 37 +Parallel: 50 -------- Times for 10000 vertices and 50000 connections: -Serial: 4 -ForkJoin: 17 -Frontier: 8 -Parallel: 18 +Serial: 3 +ForkJoin: 16 +Frontier: 73 +Parallel: 29 -------- Times for 10000 vertices and 100000 connections: -Serial: 1 -ForkJoin: 2 -Frontier: 41 -Parallel: 24 +Serial: 2 +ForkJoin: 3 +Frontier: 16 +Parallel: 7 -------- Times for 50000 vertices and 1000000 connections: -Serial: 22 -ForkJoin: 24 -Frontier: 50 -Parallel: 58 +Serial: 28 +ForkJoin: 29 +Frontier: 72 +Parallel: 37 -------- Times for 100000 vertices and 1000000 connections: -Serial: 35 -ForkJoin: 28 -Frontier: 29 -Parallel: 46 +Serial: 53 +ForkJoin: 19 +Frontier: 48 +Parallel: 107 -------- Times for 1000000 vertices and 10000000 connections: -Serial: 649 -ForkJoin: 286 -Frontier: 279 -Parallel: 587 +Serial: 683 +ForkJoin: 307 +Frontier: 472 +Parallel: 679 -------- Times for 2000000 vertices and 10000000 connections: -Serial: 930 -ForkJoin: 555 -Frontier: 420 -Parallel: 964 +Serial: 927 +ForkJoin: 533 +Frontier: 775 +Parallel: 1113 -------- From 0146c0063217ac7bf0eddaf018dfabfd509ab9c8 Mon Sep 17 00:00:00 2001 From: "ar.r.lysenko" Date: Tue, 7 Oct 2025 20:22:13 +0300 Subject: [PATCH 9/9] add jcstress and jmh --- artifacts/graphSize.png | Bin 0 -> 138526 bytes artifacts/jmh/graph-size.txt | 29 +++++ artifacts/jmh/threads.txt | 15 +++ artifacts/threads.png | Bin 0 -> 47273 bytes build.gradle.kts | 12 ++ gradle/wrapper/gradle-wrapper.properties | 2 +- .../kotlin/org/itmo/bfs/JmhBfsResourceTest.kt | 63 ++++++++++ src/jmh/kotlin/org/itmo/bfs/JmhBfsTest.kt | 75 ++++++++++++ src/main/java/org/itmo/UnsafeCounter.java | 13 -- .../java/org/itmo/bfs/impl/ParallelBfs.java | 3 +- src/test/java/org/itmo/BFSTest.java | 29 +++++ src/test/java/org/itmo/ParallelBfsTest.java | 114 ++++++++++++++++++ .../java/org/itmo/RandomGraphGenerator.java | 2 +- src/test/java/org/itmo/UnsafeCounterTest.java | 27 ----- tmp/results.txt | 60 ++++----- tmp/threads_results.txt | 21 ++++ 16 files changed, 392 insertions(+), 73 deletions(-) create mode 100644 artifacts/graphSize.png create mode 100644 artifacts/jmh/graph-size.txt create mode 100644 artifacts/jmh/threads.txt create mode 100644 artifacts/threads.png create mode 100644 src/jmh/kotlin/org/itmo/bfs/JmhBfsResourceTest.kt create mode 100644 src/jmh/kotlin/org/itmo/bfs/JmhBfsTest.kt delete mode 100644 src/main/java/org/itmo/UnsafeCounter.java create mode 100644 src/test/java/org/itmo/ParallelBfsTest.java delete mode 100644 src/test/java/org/itmo/UnsafeCounterTest.java create mode 100644 tmp/threads_results.txt diff --git a/artifacts/graphSize.png b/artifacts/graphSize.png new file mode 100644 index 0000000000000000000000000000000000000000..55d6e958f75f0463bf628ff0762045304f167517 GIT binary patch literal 138526 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 z z)}p#rn=jD^*Hwqk|J}(WkD{GH$pGQ+(uc)fxdU}7y0Aq4v$CYf|MO`+j5QfkG5nSw zKE`;F`z|}A245Au<$9rVj=te#{0sGz-PDnQV{sP&Zg)PS3&z&)Sx%4OI>e2fAHJWT zVkM<}^z>Bh^ITFl@2SS#Uk99lfCI+KC1#eH9Mm*ufe?t6ul^;bU6Lu10oP>=Ak`dA z#4HD!@CVE@%SYoL&76aUdywbtfUGqryM^IS-!G~Fwj-LYQvWEKy2h&Z2Vx$qetPstSnwIuR z>C=C%yHh(ay24`iNLqB#-1lKMxI?(A3kwaAj1A>h4epFdlZkI9P;6`rJ4lnQzdtzt zbj7!-()m}doVXO&}SZtKVM9jx^&b-7q7 z*kejSqgmj9-*@hhQzy2(Gxh_XVbsg;&!wkqUFB%?Xe=e{-frX=&DXi5)Tg zs_ceODU;|PlpWs=#3v4Q?L}y+DOQtladEk@fgkBlt|QsH8{TNuqUe(-9oyKk$Eah< zq!9B%d5e@K$V7{FjHGTI>AY*0@6Bj^sj7QgHKT-o?9S3hx8Rce6@4#n&Sq_$uWp7B z07i99vZuQJiwby>p$%CU)CR)L!RTOXfxdRsP-8YN0L7~O%xeihPM%xIA^My8wd|db z8>-?>1->*Pl9@`Dq2<_@^jkYT^j?as&?-X+GCa**P(-|l)YCmJ-lh;f=uWe3@Rj`~ z=C@kyxvBjt48*7xZTyWwRW6DV%BbKj9eL6oAFTgiXwh~%uCL0quP{B)kiXU(?%cE^Xj`q3@A z#KhfFmlKDX%=PW>22G=#`|9pmhhM+B=I)Sv;ZeCxFgn~|fhc8#OjzHV4hT*CgSEKZ zcZ<~Ud*lnq&PwG%aU8GBc9Cx4q4%O3DQ)*nLQfnD(PU(VMIxHCpx9!OYsmAZN)7e+ z6M?#_LzuJkz@_czip&fq&=V9PHG`vkb(BC68UY+9>PHDj}b%b9n7rLXzv& ztseZDa!bR(d_5W@U3;**8W9;u^eiZ-X)ao@b?Zl2+I?pb4hXL`pbI#!(0X`!uK$d) zNd^3$k(dSx{~uiRk0mx989pMMJhEuGN@ONT$MT)*5qkI7L%ye1z*X9VcVn$+hHP0; zrx3Vog{J<|SdAH1n;-5jkADbFZ&zDQw8Z62yy4U@+Sx4JA?q&6{p-{mt_b1N@ZJ65 z526R-jA|kTCRv`@GcB075z*0wL9tmXz`N9*)_)gN78yz2!kQbluGo{BL}r_WL_@#$ zZcsC@OeGUwg0$*9Tr&uTShS1NS@el7%fAsfGh^Y@`}pveV7%UGC+?X+ zbd-CLLT`3AHF^QZhaaai*4k%b2?DCbQ zUjni2C)}qhGK5P4xD^Tb<45 zKIC@f@6F9W5ah)1YXPQ)1Ll2BbWBUsWpcDn@2zhr$jLRUDq&7{PpB3(RM6bY;7m8? zZwNdu&WW!kr=ZkC@-(rbd(Ko0gNO+jM3>a=X^fm1v7igoqG%04`FH>y_N}~*QWxo(?V(3U zC)MZ^#&0!ha0#%WI8if1GkYQ1Wo;E(dcA{Yd~YUEjDuC5IQLjM)$=M~W5I#TuYsUt56AxXUPY6~qD6{~2P^zqEhjNQ){ z<+^fEGgj!nYu$^b=J=itA2t)0MbpfaNtu7hD!Z?aRw&UbxxVD`ysF?ihwgb|1!?Im z6v2o%Sv0*BhC9L(X04Gjb6F;{zFQa_UT}$;7w0F6-gxjD{hGyStT|(+xtW zTS7xa)<5}U-$2AURi`gX4+n*RFExMNgIVVMl1aMxv$)?hbJD>0)_1eM^x(>$Z^XX6 zw5hFSSO0KngQ<(?Aq^SX<#BektjNz1h&Ne~z;31+@-F#hsKd2+k&r0FTV92ptUDj; z(zQ3#>%BZvf}l?_cqe1idZJEmq_0%BuO%!NI&iWCqCJ#X+}vY0^>oZ$iw=**EoCWY zb+tz$qzz)i>lobJRShIvUy*0m-cfaPe~oqLhMT))j>dTk&Id$wcbL<)YirH(gxn&% zw(9(*Qx>1*m}b|qhJ!8op;Lw9#{6s&QH*! zd183pL-Zcve5`w8Y3hmb?LN(q0oi$;heNVG&M~ETR#mIpw}{=6mgE`iwtuN(U}93O zFr%TNH5bVo;#k_~PB6&ESIp+Y!qLb$4qCA5{WT4#R{2gL9 zcN&nU9WQ*Ou8K(B$y|(8Wk@*{N(E7t}! z1zyFn$rx(y>zYh_@^mp@R?xaoiy^8n>QXh`ne|Fbdh3qH7IB5e&^J-Z`iSKEgPYFp zBQ9Q>=b>6)b`YVdis-R=3MYb6Brtb{d0v9rt}LSPP_*&0&G}oqP_1Znn3u9kOe(bR zSQgQ9ct6HY?mG0twgH%b>hW1JwQz7lP0F-gWrYo>R<+WwR)Yn=0AJ)CU$oIW>pOOYQxlSVv@sdSw#wkhZ+Q z_Yno}lZe2&h1)%j^Eb~MbY9zH>~=z&@nO>a6yXerJMpx@MSamKxtCv?yx{(QAD9Ep zGGFEC&aBp``M7y+GR}sBOTQ(vIjt?7KGlV6mgbrF%Bd`A0S+*to{9Z+mp;r^4*nE~ z=QM=Yt~+0>oXBqlhTp`CeR^k;1=f_Ftzw81=h-TK28mb zCpZ^#NcAdxHEQzdV$U~Dbmk{j67t`}CG*KvMGcirZNA)=ve=xjVPU z!$^DI)9d&q5~z#&b4e7TKE3(=2h--?Btl)nXa(P&``zwD>*P2cQ& z>M2nR8qAr@B(FxW<1><{x^J{!ZAmpNWjC^x2u(gSYbDxkCU%ovYY4|Qz=Gd2SI z13~9bB#((tlDAyT!!6n6t%TA;)cm{gIHVkA=2=C-MU|FEdRlf*FgFh8+8QPBdihe9 z75RV)I}}dyd<_p~+qfB9HwsA|-xIj{n&*TAC5tm_ z!_+yK!Op! z=WAxtp4H1|QeDaxwyu!ka$E}0RFvnh>Iw(OJn3qw4bz9&dCRA?_aYintte$*P%@T3 zjTiO21rPbl<+Shp$ZJnqX>1I)=6j75+W4#xhA{MOj2_Q4Nl1YjiPVcui~b>+x4MNl zUyPu=Do;!g7&Ra57?YZ~K6vk}P@KNt_?emE9hy9sAFyYrV1Ws`FM5OLE~?Ud&oHAs z4foA%u@?Cijh`-zCup}`EM5d_wSS25x5-EE$bVn>wQZIY57pY&-*(yUb*PQIZU4GV zF9j-o*dAO;q+q=-#Zmb6Uywa3F&&Q5dCS}zJruZ$M#o~2OINUSH8Z!S=uF6K##&C3ee)sp8LU;`Fe#$o(|;Xl5!f7@e`0Uko1eNilqWy(HNd#;^yw22J=bd zgDYjIil^ysS)EfMvxG^*b61vnT}Ftw$0>I9wQ=~17oiH%OoJ6wZ}BCqdeOGMhn6A#yC~Q3qw)$y_Fat zz3|)KaTv)pNh9WV-KvqHH}igoxR8&ByQ>sQFX=yDEvtx$p@`)*XUZ4+q2x5HYh$A$ z6uyzlS`4_OX0`(6+e~5>s;N*Lm}=!%+j9l`Kky4U{(BFgC)^?loELZ^J=FFC;|}_s z%T=JA!qFSc(vD@iE7;@gYd;J&iNYP75DyKKVAiCD~sC}6n;*4?^lDy$8TB; z5dDT=P-YXILfCiFT*k)cV5u;>6jyfRe1B;A_|%Zhf$jQ-mt z16Y9B3@mO?Pu*Eov`T4{`d!&VY4pL8uS8VR#s;vIo~i{q{I6D4wfc_OEI;zwt4jws zeR$tGwunj5_sal;S>ERPyhXf4m)Y&;2_US;`CT{VC5Cx9o_WX??fe6U+XO}BZqM(-j7QoaBy&l+5q%r)xw9%j<^9J3;-cm z4(3lS9cmvP;J8J2=nTq6PW*;qDQ!yB4rLKq71jx6N^p?d3F(^5yTk*Wv;3K&eh#t| z0ZV{gxI8HyEHlfAIgQIc9F`^8I>j%3zc}CF`D`3&TNsR>=~HY=#0g-`Xq^3fCwRS! zR;u`b1^XDwLSF(Tq$uvnj!53!_F~I{Z=&d3)jWKj>t$JK&!94}i|;qI{mdI7osJoG zTWxT{_NRp{!7gz_oDHA&myPdQGlRH{;g$`|5r&H-N*6ERRNoTXsw`5vF;gK^qa>X8 zVE59F0V1NuNBL-QlS_?LO>k7y&;ET)-Y;errM{FL&u3l?5=s47NWAIbx#bcDXZd^b z4!1pn#Ij_$;5PBBW&}SR)d6R}^QXbT&}IEiIdt%!lq^>Sj>{^KsuIAzB~^vlgH+s0 z>-a!ituM>Xt*!Tsl#aT>VeftG$MBiC3i|Bhr>D1QRq=jftuJ}Yw#`X=4kIPqw`kwn zb`bwi50TLlprsSKMcdvU{nKT7@ zjBv4JSX9Fp)S{aSVXtw;&lriF;2do@(rTm#$qU}= zx1};f@B#^5OdHV(u4)*zE^Y9<;ZmdT4CJ^im4b7-4apXW+&d&slMgTAYx{)BamP$9 z;rm%}sEGVw+ZEJBEc9@-L+=tZKaN=xs(zS2NLk<_-iha27??sCn5 zfY;JgJKVi{m8>OazS2yMFpm>@A2wqgIf_7OVaRjc`Ej|q&|ytCa4VAb?zS|4fGTxV`ec^5Jn-;r^LK*Z&>feVvlSE*Hk8g-5mCAzkv2 zu1}0+cu)p1#2)1l^W2oBa89itG%8jUJesl=DIrTZS$d{$E~Y2>AvyQcH7XS^DKy6ji=alGw2LsB+;z8>{M9}9;`%?`D#{R%;@ zgxKCiI+uAy7+qcKv}?*fKQEke138=P?^7%?>_H>Nt?>-ImR5))K&>RBXcdsdF49JL zo-)Hz9L#iNgt2XMtFG?uk83p3<%nI_K7IOhMxwSm4WSfu>!zLLgaB$Z$#PHgm;;cDt_No5r(b;DCs>3YI41c*Uk)MIA(UqWydDk2Ojg z#A<0+yWUCz#AwxTV@VA^SQTIF&QE32ih7JVoehP#Dj&AT`2KK4d;Ak!R6=~Q-uF3b zAfZ7uxywnf*ePZ?@$?^JDD~DEl3|Oq#nKw5s;nVdW5*~>Kqs{{+FK*J z>f^q8r^$vDy_ZOL3g>*lFenYC8l#_8&#y6U#gCB$X9ri7OeehkW^={wc!08{k^6-r zW-j;&C&9Q$RX|89aPdU+WN&5!_URBj&b&vHo0Ze>mdB*ozdUF_^Bdv0a}xeo=L@0M z?$V`8kUD$BVo)dSv@*t;p(GgSb5oUS72k z1~D&Tlk>okg$FNRLPtkeDKS+9!d}`#1Jc@f+8iL~VcHQ`Q(MR$c~Iw}UCNs97{=X9 zSR0U!B5J3f3gA@0eTM^}DTaZ8!BotX>=7;KnIq+VATXn&o~NTek|5@-fA<(5UeV_` zginS~U_e0dSTJ<-g=)3)_d+uRR5XzN7gGiu&P>xts_YBZ`bW?L7`vH+{$u1;2^`l* znPto#2NRRzti(R?z&OnMNZM5OXB7-&!@`;G^_*g&4nX#wnqPM9@zIeK2Pp|LJv}Gz zWmll$?^<}8l~8tVw&HdIX;z-OT)Mt`2A`1U0WWZg&kRED)RVV_Qc(0ia$Ht*PZDw_ zfD(c)Ec4cXW44Umm5F+T8YQ=jz?rF`SpR=HGlk*j(=7jsGJ_VwluGg~`WAVsyRnzy zZC}mjN_g!tSYTiv zJ-OscX8jTV2W7i(L3`la6S0rHQg*@SZU?#ZaBsRjPan<>|n-puP2^&1zm zpM7qI7b5a6XbXM9Ai)!vpboH3Q;!6I0bn){2eJGu;)C5*GX{yBfh%qd62md}UEsFV z-G~87t1VKSL1F^Lfi3c}kqba!eTx#E23ZFVF7EX)Squz}=O$rbyc~BEdI%AHw}+o- zcw!uThviq?WstDz*)A!Ls8lI|U*L9^G&9E&!`yG0`!_Tc1EBU$;RG-ti*pDgk~LEp z?glPw%Vf?|%E=Q$!Y$dPJ%)Xk*p0zx*Ynv+Q9t88B>k3B!M_kN?hKsYjH7|f0Zy&n zi!s@GBo<0X|IJl>rq~vQccy(jL^Kf~+0Ih*nA_t*IODfWmRE7zt?xQpY!^Ob-QFd> zs?-V_tERR3O`93|qc8_Cv8Cg++ZY10IMwzoYc}UCD1ZvAju>&XVox+U6n@qJsy9^& z?`UL2wmClZQ@(0-`YM3R1ILmN5f^I#tv^1*ITn>XRa~@SurqO|fm7wgW6zK>`g1^b z%w-~a&=X@nwNh`Hd8safdqdYBft31{9}o2arsOV*%c;M~a)p)l6*zI)RFcI}+dvvf z3psuzX>fyv!*1smuxGO@4=M}Opo=6No&rK+VIw12A0(gGe=G7n^~yZbF*=j5Ml8bY zw2vTYrr-iW8@y|8O0 z4=k5SUu>yIFF%YX;;2_FpKVZ`gk9==Vqhq(dGRtiiyF3B1qzP6HAQj71Xh06gXh^U zI_@*IyFQ1j&aCnA_VG3D*Ri@NpYh649}NGBu-kp%pA?a#F!w6>HreT4nmUsw;kQ5f zyeHI4OL67>5)oM5%YD-?u%Q=iCCOvsoG=-+ms!QxG%ke0UIW60iVPR8N$4(q=%Q_y zsQP|*MG?)^tB}UBm!eJ%9g8r7uHgXzYc*}#GG!3MBQV*(yv^{5@VmE9MNGxQ zoDpT~_$@r|oXfowUM2l!qc4LjyiY3{K1x7FzwyN$x9I*Bb{*%B-VrW$6@M{?Xoh!0 z`BL3T57m74L%?)~5~&qPb=kf<^Vt5qOABIGd71qMo1k?e=ona^Ess`o_Xax2X@7Lc zUdsNL2c%?A4i>B)$8@UCsm;HRZ?<=N@*xikBkKI%4Z0*LLK%`Ll5SH>Yl%V>EII>Q zk+KCeVW-y)l3Y&ef1WmFCWw;Ni%OMXwSX&Y`6qV8I|p7&g%pglQRJ8>r$XD+-u*-9&> zb4;vnu=5ej)t$rZ5{HELdB`_@ak={3hgq#LkVoKYm5Lv>F?hcK+IzZ-f1-INLX3cc z!IHdFmH6?T)fsQ+iQA<~(Yblfjvg1f5>Tl<(bcNzOp;%F>@h~#Y$&;4rZrm@7J=FK^fyjILk<81_uj|oH-grX+hxsgy#`jH zw|rLA8@Skn^rdH%=V1S4LLDPCYBn}7SKdzAuZKie>a72~@S^24g2tx)JU%tX4ME#U z6n%pOH<|TcGXxBCZtEe2%kDlq-|^M$h0UJQX5?DS=6vp#3UOSB|H_ z)QqUB3@132AOL2C+-&r7eOd2wt(1IBO@w|5@o?KfGm50MB-!!4VF_OZ)gx7$kis%Eq_9s1byc6&2~FW+Up1l4|nl&`_T8{rCblxmfl<5+kZ{BKQtOw zD(xyQD;qleP{C{A7CBUV&B|KIL$r@X>9v--Js%zZ7xOj&8DAk|zlICAwrrOXH+#n& z#+MzgqTyJ*>1i+U3Iz`(8y|%WUt4tfl z|7L$rKOxnFIi&nsRsJ`i$ZBf=Ryin|Q2WLt z^ifY51Yb)A z?6w0q(=5;@Fo?qW^0wWtPDu1@o^+w zM!tU&c&Uj;#huvz9xZZ^+#BMhfhPPYB4L;K+cq)Av6w&NS)EBfAU0^>+9j4bc>WiW zSHa(+v^)(nQ@6|Cku%@wyF8RtK*TMqn-0rH8ieozKnw{EztJbV_g-H-Z}ZgO`^YQZ zZLaO)RT6V*FG|b`v#|;K`Y->>Yr_ksEDzv)H9m#Bs3eVDns z_*wLrWN{d{C2W zM5H7f9iGWY&>NzOiP!Y_PE)Z%hzaP8Gp4@uW76r|w%&~pxSr3`U1g%8hjD2Y3n(flI| ze{n&o3v*}-v+shB@wGC{(PO--CF`%WhBCVoYwYCOZYx@%2 zer3NvBe%-jTP&zg1>?4{dut7fm9E7Zad<$PQcm-d8}^82ZKc`|?c^y6pO{4w+gGoB zgFYs;5vu5^P{zFMs}wwHJ-)|GZHQ&pZa2?YM594(5KL50^o5R_!ioto_OJ=jtp^>) zo`lj-w4vW0kq2MC(FHLIwR$#DRsDD-mpK&lIVgX;0})) z)F+y7?M2VK?AEBYUM)@3Pn?l;!-Z}wd_yOU z!cscPaxu0OW4BL>E$m#$y_Cs2arax;r{fCf%(f42oB5W>onys0m40f@g7xL%6-F$e zP+_1OfQDz(j;?V18d6R+ww(rg3gLq4RQd2jtMJ=y807!lM)K2((`N~m;Gas^@H6q z_Dm^THwzzPXxt0^=zal=2}Nf_rD2FnbAMyI9o-O3etY|mrdLtVm%p{^7N`l{ZLwTs z@J6|-!}b$~uBFGdc`W*5gskCYw>4+AYK)iX@)<6dak=U{!=;e}o(Tuk9LUb0iU2Av zcvt2HrCtAFX;yXS1ridIGx{WG%Dla95_z*7`cEraIB`m5dK5ItdnBwqcS$&y&RKKY zV|*(y5XDluUwfXZTQ*hg8i?R>`KBPYY@s zX8IKYCd)5xd8S`RXB=C$01_m=aKR6(MTU@yV4T_Vw>FQ-`J)f;$N)xRR}x|ZL{AX1 z#)Fgd9<73U2TX~ByWxEW9RD|RMf&E@{ulKaf6Ebft~-gM09r&Z>q99k)yc`pv@i|7 zH7U>D-rhy{&UB3wq^}_%?t{PZtDK@@3kdWkZ3UXYqW%x19$iA)UkH}mRrPm+s*#Zq z)88ZG4MkpvP5^1Cw7h)C+W$bYd-&IQEe3F^oma`Nl%Z_)%{5)}YNzE3Nz$NxrDPTJ zL%0LdpZ-4(765T5I5k6eGDeUv+nC9W|87Up-zb)ok58kNzl`;V{2LDK`wwU~q>E z{mn)G|MYty;o;;3?a}!>bh=r}j4v6=SS9At%iq5ZhF1@95w9KW(o7-Gi4F16IBjfu2k70>o-3aD6~IIy^?R&X78I#c z!560g2N&7*Cg1b-^mrA<^yftSEiIn*<&KZ1q@+ws956!3oU~B?c9nX`z&L4JqKNx- zUInY<3jY1~dj>SPlxB-I$?4ey99I9tZOy{x$M9% zQl|;~lr0Aab%_Vw`j(gBX&Ns`2Rr5gZd zVy6jN$^~X?uniHSWCCGhZNrZrX4HQOTO+99{}I_ezhD9)l(MU4QL>jjb}wAE09BLlP$_( z0I$R8G=RdZSD9ZN4JAK?#u3%YEzLRPYv*@@HmMkZoos@gDjsz!P3B*fhR z9(h6j15__F5!8Y!HO%^%p2u`GD@z#K<%!=yoV-h$_V+f;l#5ZL&+7+*LMrC?w|7MG z)^7kJ{hRNFFj5ZikKjXkYKKFGgl8tHQh<|P;n}!AFHXzTwStE7m{R^q1v=uimpN8h|UlsuC} zM;u2Q8vRJucpW`dg{3gE)L_VKykB$|JmZzazd1{gk2QnrzvRdR;$X6j8pq84Vc*^g z%Whp)yLCuDDTmD_nj2PkJ^0+j1Ibl`Y9>+&yKG}-(!?9|Yte_nl}q#2$8Mf*B9)t- z`#W0Pwx}D}v;5ag;l|{IYf6^h6$88x?2wuEs_2AF@$y}H`9=tVDKz|qRwR^?iOhk8 z8mqGz8RyL0?MMngT&;PTnrAr(GPa^e^6{3Mm(sSL?xwO4Tr3x-BGne5!6695$0NKZ zH5{x*oOB_gnr%ElaJO6Hxi`)iKP1YooX`X-dG5pC7yn$MJApqoVJm1VxrVBl%w!t@ zMa`r|h&Gx;hy(^Pcu^+G!^rl`*7uUKu8L!KT-`(TEzUSbD zZ$-yWv>L~-ui1qu|FQf=^4ECur#&Y2gqJd|q`F6~ydCr=_dD`4yn;mFO~-Y&V22g| zdxvFKItbpGXOOfTEIIVuc_IwB$>7F82oB_i3^+|0yObocEb&Kd3}i1$e+ z%b6^3Zir5jn02@=?9MHjGWUut5T-X`kN0OZR$E(r<~CWy--_+SgF?N^ii6s>UK0)& z2c`@K?1ei|hY5ENe}R;vm#^)mHl5#UxZ#t91hW3&-6hX^ex|vteYuh z&F}B`T^&{Y6#96AsGz`O?|jHuzjnvm?Dy9^W~~>~1^aBh^A36PhXwXbZ`^+YqYm{N z+Ji>*FNzRwj0x6n(rONJ7UhcyLKdRb0j6iAVLC@AOyle^wfYF2f5XLy!CX0_z#-sQ zJQTy%4rQD{FcaMo=s(4L6VFS1{ix`eP?-0SF4}IUl{$CgPm^EDBCPI+@_fo}I;m(~; zsnVf6FzSC67|6sG86W@Tj2j!*L;TS#waJN-hAJ{28?WT=XvyO0nI5K(OCH_9|3CnN zla)SM)8~~<2c;U?wvGEMXzE)E_nVqGjT8f?a=se;=$I!O@>)5V@O{s~@|d(fmj#_IB#-$3Z_9M)62^brM;D#6IQ|w_XiOD=rnRrX z-wsTVQ~u;dVh;0>doRM@f2XRj8oeUAxw9kl?)oEJ$OKsb2+0cqPD^ho z=O8YKf`@o&YKqC*!Xy>Q{b>OU*qm6Xc0_@%@sgjve*l+Xe#=6CCNT*K`v2J8P~4{f zk2)5%JJMf3W!?nSglC*t|C^>i?d3P`lX~#9BWdY##rU{`9xIn;k#MnImHlNuKR@Mv zb~tHt*;cHksYXqK(>guwr0iup=Fv#IU}fDv>phmaiR*hU@jm6eu$WcFVQSq27%CXmQFLkrBcbfwX?%0`q(E+lx|?*4e0;(JYgXJO&myC`-IC3?s+ytU8dAM*y<=(msx*D z{P-{J#c6l)+<+J;T>sB*XX}*Df*)S4Ly_w%Y=Y+9rIrn6!NK&XF4BDe^Jq!iHm8e2Xr(3KSnTrqd z>?|30rsgp`N=|9kPa2;4y43yLlq@O!Jve|pPT6J8g5?9`-lx=;ite#G2tiX3H24r3*&&Z=>S|0Ew|7&8%7)IdVOLD zdwy|UtjSamy-^Ze|FdD*J|cOp#lWshh@sH!yyQw2o+ee5+a(ze8pgy3vzutE74Bl1 z!#|9W+oF|SWUNZTomQhmYAsi~V}rb<(ldJdz0JEib=E`74iqw4*waL9%2JGQZ^U^s zg=m_uwGRG2%Fa40sEA4$T$llOqj0rO+ z5(=P9KG+ZOKD^SVwc;8Ub0gxl71KEbGQ)1g{rjzMaoDT+J5I<$27u~l_f8()|DIPg z8Pa2F`CoPm*FJM3lil~d>1XansEs*cmn?-AWT|2w%cNrH=9ZHWi?dLK7=#&!2>Rn& zIQ9f~1o#Zcco&Yi6_fw@1xp?tmqyu!9s*JfMe=p9%a`T;%a2iG8+4Dh_yNu9U>XB! z&b2|GiC0YS@gJ(%wB0Ug5pvN+&(@@VYh2W&OFTOk9clAT;ZaF^nU3}Cn#h(@5lOJb zzf?aVU~*SS#8BXw+^;$z+H|Vd%c}UlD*gw{w3L(qRw@vyaOJ>blQ$#>jV#8wkTkUL z+qYEjtmtkO9o|&zf6-rj*g^kU++TL6UXi$7p(aJTYs&ekI=lMr$;p`+y@N&@UuO2i z!)!itp9XTEPZ`{rrfT?ltkFq!E1O#_&EuzfEAClj6F4Y&9Xca% zw3k@^UxKI#=%q`K-(hqWJeaNS+&K$;j}CeN&56QqpB(7g^C9okQHXiaa<4i(mI*aF zY0VFo?VjH`W}M2Xn~mHzmmd?D+t9o;Ctug>zPy&qrMX)_*cBc3v_{cysT}O|ke^sr zRNnS>b7LMQt*lB(KDlsSg7h$RyJ=z{`!uCZp98R=@wa{sQ}h zoXDazRBA~D?i%c}VM=IRTSH?b%;?gv-RbFA%uLO-c&Tm*x`253`Do03z^~pha{ScI zlg`TnexleOf5II?%X`STl{IT)+LV7jyrR9J4m@uO-d@ar6ACqN9`9+SLfr(aOra4>8?4#y6`2U|RCy4#R8`O`e?R-bt$!T7(k`U9I}Mf2*dtMiZat zmTQPog4?5JV0@hWnq=sDhxDQUqm}MMY>Mg=Ds9?7KVk_CoG(T2SqvrujLiK^@jK?f ze0uzt5NA8ya`>-aE#OA*WVt^qY*RDa0WWtf2vPk^yklQOnUqAnLr*AMNJus;p}x-| zb*6q8k1$y=Va80HKC*k@oQV+T*xZ3Mo( z7?-H;^5aVhn;|v@D1k@`(4Rgcyl2CmtQc9y%)v34R|JIIb%$bg*_*R5afv+AtbAUpoU$ zscU#tA`xUF&a__4XWbiT0A38wUN#{wEeJ9=BVRdRp(~P19uIGXKPj1qU$)iDjW)%d zPq~c6pra7;JbhhLvlWm+X#tP~7yk`{cDxT(+oA!?d}DE#I!U9-b@soa%;@N24Dw@l z_r))Ug&NfPnJ~32ZEHUaHMsPC0+=no`g15!$Zyi|ix{WZ6&lks$=&+>pU*Z}K6Z z+@8#B9W&?(<->drRl;r48whSzBjO0{#kN#fNke_ z?qU*9)rvB{U>9G@1vqvlX=l!*`uzv~t1XP|CaBcL|KyB$Uv^Ck(pB^n`&I*$cTPK> ze$sJJ8{(&c4<6Ml+XwA$(U);tQZrZSjJw>7P&QCAKOK1+$O{X- z5Ocsc(N66?=H+@3+>$6_j-GN0XF@`hLo>vV}N1>V&jwBhzW$*04r(y#j! z>#8jObuBM>t>&c|Y=joo=gC*PeR|cPHgj8nhTdHZU}}2m!;Uww;Ldj%CHj<*bA!=; zj?MAimRbZ=D6&wKMVzj!Bn0)wDlTA39hTc&x#Tx{)iJ(VYMiD;!2QQFwxA=@+TCwA zS_IfQf;dXF{Tg_`KSOTFilr7_dWTtd1js6|@-vii&oH3}M$X|A%kM4=KDCNvd6!D>f<1&rFju+vW&5D2xzOwU z-JH2AO@+Hv&iLLd$_3xcy+mjjh_1)t2^v36FTI@|tP z2h4LiE-o(Ho)rA8r7?l>h;)g%_81Y7Ta#H5sCk(~1)sI_6`dk;1=hbZL0AsmXkfrt z!3ln)C4L{sd4#h(NK#NxTUt|(Zi6IbBZM*-b<#30oO9&` z+f+eoo{38!XRE|x@fMK!ktEZp-?@{%g9D~Mi;8M{D`wNYhzm9Vba{>I*Xc}bK$6uT zTSra_35m2+V8E0!>cg2;(Ip@aHXK+V5~R6~z*zN{Vb$@PqsAYN`9n1PxAWn=!NbgY zB4T243&LHQpU#KLxj9~ITwcLWzW3_1$}rGpezIM5o9mha01<1*BOn{M1fO;qt?dV# z$AmcJYI!>G+7(Q}XrDyZ!N*AdMT{93s75mu2mqJntXer(Q=Z(_i9ZSAQfVBoi7vL> zuKsC%$X{kwp3thUA7F6rv}+ex`0aj3XG{g)pvG@%o$Ly}dI+wC_+OS)mH3S+upqPO z6D;Gh1H=%laL=l*-*C2$>enmAXHBXl_qLykYsB@A)_`uk(s}Bkts4$VQdg&{s@kGD zLHfEr`4!{Hc&?GXQ|P0iAN>;7%8&i3@BeT=d=x3zXZ+v$Mn9+D`^JNpj`wgoI-osE zXDofaz|BWgiZiTkZ#vBUTsIa1VhHH0f!Fg9(AlA%+}{MvtjKXIUUX#wxC#cI(y6L( zxSS)~jNE=0gsxh=wmnX97^SF?LZ>Np#F*8cAc0e}l?ntj1LjOiDFIkqen&1C0y}Ei zHlXA-SK-{N|C1-OtS|yhtUYDDNGZ^g5^hSo0@jFT-~xVf4(FwKddC5@)O$wXwSYTf z-cK{|eN9wK`B@XtcK=q=?RlJa)Qzvf>Fvz=GLMyXK!9i0V#`r-=L&`IwlKMq6Y*^WTl2G)IO06}@RB^QeFP?*GMs91kglr{;Z(@YNOT8Zxm3&iERy4s%S z<3S5NJFTsaQ?pMH!5pny`%9|EaDvpjkGHVGI4sHP%X%ja_pN2~2(FH&oU)?K^kn*| zIS(cEk0~!IHgV324+Y0N(?i9F{)>T_zb>WF%VIsM&2qwpccTQv#I1k;wqDC@ko#rGHqingUy>bl7B+aB_Uj4 z!P(|7HMiLd7p8*ucb;sVSt_bs3(e;2dMie3R{f>6qZRBHdMlhPY5^(=Y%G-~L$pr} z{s&fV#R!irb}xZj4fBQY_!Z?iQ2+IK)2Iiwl_Zv3td5C!72~dBQB%PDLGWhcM0ztp zi!p&v7QuL6Yj@0ZP6pc|X?wcoab$$V4tanT&N`X3>mnI!;<%MC@rY_h_SutB2f92s z54E83#{-_JuD>+1!(ip+OPPO=HO=CpnkJ37ulq(0VewcVCV3jO2RIM+~Z>a_mYv`2~c2eJy0pK_&N z%M!)-8NhuB`?eYg%C=PP*QY@=K^YVL@_N`9X&mJ0x}{rO{FQZmJI(t4gogHuA1ix_ z`auTcmY93F!$_1{kEh2*w8QvNF74rx8#fg|+N zB`(z!AE{MM2mr6mOGIn>gt7(r53e%GaTE-09IT@Ta?pz_>Rol*syk#IPxbzP|qA zy=MD_XEN~8Cmm-#OED$#x~pBcreJ<^{~2&=szj%pSt0z(eRlSz?2`q4IqV&d%p!Qf zQvl(7IzUY_DYPD%@gLm0PNmlXd=|O>bb7F$qq5&YB&Gd56rKxpr6^t$np`HaoEt?) ziAr5QF?K3HARh5+yRCP5-w9c8$R@wDHT_yF&^4TUlexGw{#I>jbP ze%bGJ*Ni7!ZxkMR_~T&cH#&C zcu04m%TTG8VMQVld_t!U2U#kMHCaBQAJ9H8^6zTv?Xm!-4%3O#lsDq=ln$Vy zkFNw@YROa7-A8e4#T`-~Zi+=DE5Czov)grCptx<1AI4yp^`zD|Zt|3tJXiTTkL|rP zj_SKOMWj};B3P;CUHcD@4OvZk7^*bVn2SG~uE*;1bL2_w1yMj@Y)%+|)R#Pz?WMIo#iB2cau z%S|x0=t(#7q?!WnjF}T6wdETU8%2X0ihEdyJl>yWY)Sa>EbbYg$yxWLD1(iNSR{v% z@VEewumMvUp~c=D4R!12=;(h?H7eQ}!0tj2)4GO3GeXD`RkXQ#G$4pn9u0R!so1drcYASEBe% zh~%DqGs*Dbov2h%%SOa1?K7KR?7-5?ko1@N(7YoswIn8z>4W#+seaN0_=o{CuXeiV^EY@uSPF#5kh?ORie$N|$L}p5 z2`~Wz<@VkOn8marc3+Zb&z#4!%76HuYS5WMlo7^bNnce9)SL=oJ3+2=Pz)YPE-SrH zapLFu!IN4tX7Baw`)Sp-(`9aqe>p>Dz_ilL3Y2cIxoSY|+L08Bn+L8*o;QHaCPs_c ziO|rHAuPz~@`aaUGO;mBWUsyxBp4C?2sAL6n?((y-YvsJqwplm@m0cwBtL=MUqZlu zpd$tn7&sDD|Ki~gN%(=b-?+D+cA>>L&-3R|F%|^NwUFjE?y+IU@uGUN+9O#Sx;s~F zfi^{aFcNHd*;ZV8to2{0e%SCRy7=fz|C}9S|0#==yI&h_;v%!Ebnaip_V3GXgg|b& z6Ln$9gDq&iJxqz{3LT6Sq?9X&Y+~?h#_1RBNNvAg-+c$|91a&UO;C4FW^wuI1JLbR zp~Cr>UbA8b0!Pb@X%|28!k6pa#@eYoVbAM@MK*UW3Csqy?0f zQ(PFIvMK5Ln2%5OL`99KzDLRdkV9`O$_W`V8A(WJn0uH$aCYPE5O13I<(6EQUW=fS z-D^?&=CnR$`&F2qtM9fn$u_I@Gx|7pQr-4=SnUUWv{m!He}M%YUU$@;fxlLOx#i&@ z384FzrGxm`=&whLT??(i4;4AlRnW`emt|HNc|gQ^2;q~W$(A7C)28>)#|<9F$FqfS zViw!rEjt*W{+yySNiRh{D$A0u2IMF))O? z0L)5P%TAeQFb^^jq!o7fEp*Gy?hPYDEevOdn8O4c9opc8Io|an>(&(wl+i3bhk9cQK<=zb+o<&lfG2Y~Dt}@K?@;cXeLBas|#&z-~wLua6o|s6cRQ^Vq4U zikPOSkJjrwYUwoQ60qOel&Xc52EgK+@SZGk7R@V4O@DAh#~^esGv0b(P^N`6HZCU| zD$L-y4lAm^DB2}J3~Lbr2sfx93y>9{c(vseg{cCQgQ&t;Nzd{^;BfSXV(g(-eA|5c zZUTa*Mnp0YZt$k|jJZ~|*GXUxUS2ych`$E@Hh#1LLisC0h(OKdFA9lZUygq8F9V@u ztN1q*`3rgUML5Tyn^>rUT7Yq3NNNO3G6<4bL2%bLE)*gyN*Qaxh^q|{LRz>&wqul~ zOkZW6?72Z1(l#2LwtKXWYje5Dqm`Z~4Tr7(HvR)V#M?xj+Q!nm8U;qWqgKyD4HD%b z(b4FYqU)gsPrK$GVuG>$v4A8UFgHIMYS5K5Y^KAbzO?<@Nb?2g^D^m**#md1bQC(i zE7MCJ>$E7KVQWXD9MAUD_wfh6aX7N^>z}{LVY|uLbC*~9O?m7#fo3NmgLqHov}vss z1~)`yeAjE>WHCYV+>>3$0X(05NWne38vN=>v0(|FY{?$ii!}R^G`n2R{x5DlPE-F_12=XeXo>Sn zz;$Z4Hy%%!6U0YnpPT`YMY3m403}dVxioj~W+8zT7=$IKD<+}L-UBZ!y8Z)gB1!8J>BnTlQ* zyvZLo9fOB6#bD7$2qm*^OP>EO9zc$|aQ9S}2%(j{Fs!m#^MXf10y@-A27W96s`B6+ zxxoLp;pK6HQ~+X*V6pk|00{3(vyPFH-A%x^?N1>sOGUMV%A2L*tRpY-+M%#2JWWO9ZIQWFJ3Mp^a5?R*Y0PkBR~tZ|a#@=MRVLSrru( z@65>h`}!u2cb1BZ>Tznw=6N=(Uet zCw1Q8g+z`p7D`-R;2>#`O36BYHvQ2C$J^xtzv0zpkaEednB*^>p{c|Z2n|XI{JFT+` zn9^*Icq22UM1_dx#iP%2-G#MI5GX|A=_mJl8rN2un`ro0othj_dYZ+M`vRBBF`ivu z;xKUuP!YaMgHh>QkT+6n1?0e)brc756sG?8f%QtykW7r;poH$%I6zFlj*5~Lap_LF z9%fLL6Tob+GOrXBI;~%9apBt+C4eUl-_rxH6JSjGvfMH1hFoR^@f>|X-hEPo&mci5N$DnB%{kf+cYJ7?Ec=My&W&*q^6-k^7rO%5ODd7%-Yx2x3wi7tQ7(I z;&ElAw99>9=Pq^}m0UFfD4b%Yz<^j+ph0&2@mW+SN6hm z{%JdRc6*0Vcw}dcNV2quPMxoZ%MYM%YxV%18T#@KrB+;A7f5OWq06vhF#kTDVb?P0 z41*DNv{c!D7+|~o9$=@c`2D8#0BxC<8q5EWW5)K{Z9I>~p%#Eoz3iuZA2&Asb9Rl; zXwzwlL5HJXx$<0nBX~advPT}1_Mrk-q#^Mzxye7nK_jpc|P1B2!ujb$+TPUnzY=Dx(yo2^s6O`9%YPyAO# zc3;K`=!1uk`kjZ({GKP7_xA)`s=6`p?$VTtGacar=Kj;}b<*`@sK&FV1!gR57Jigv zOGqVvPefnBVxyt~rV=Lts}@?A`M97p9R&$OwRI2&ZS9%j8<|@1hz&PnRzW@hvOPM+vb3K%v!I+qU>JIE--#Qn6oi3a$bA&( z%VgD@V)6qWdK~t!0&ET&6|E5%M;xyR7{iwm<-E{aCQbRk9rU8n>f$M0P4}I>Jy|fJ zZsrDHmJ-|EGr={qEG*Zs!KZ-n2B0DS)p*lqtf}QCU0y%$d>ytWy%E-5uW)mp)P^n6 zu}GR#SLMhdzN(BZaz>Xeazi}B4VO_iXNReQ@yi&WRyU4o(y4N-eH2&_&NS5w|9FL} zjfo@p_Q7W0*CFCMtORT1GO}MY_1PA3WF-Q!43!TY*$ca-sNehKHAvyw2J?_F%ecI_ z2QP7_K92whcd4e&y>*k`8|>mzzoWCXICK(C%0iEFngTA!O1&ZJ_Kb=a|H#nf^|Z%6^gd z+T{S$t69|0iYf8WsT#D8h=sx9BpiF{G7@je*PIm7{aFgKeWQjN&{_g(wpY~_rA*gy zezxdU6EPKYfw-hTQM2Rpmugz(bLy(CNda3%qL*Gg%>pE7zDnLyY8}Ks3$Jb(k8gGb zwdAQyfRql`)(Uk8r4&Bx?SPay(UdJYm<1Q7Cv~wW=YyvKXGCH+qgxMvByR0$T$`y5rI8hC{q9ofLLNx^QRH>G}yA=;eqB;c0g4_FDAj2a5 zeq_@C0fT;j_8E1zw;uCVicW8i2QGp&N_d{gECr{P6WX(OHQYB@u#HemMVZR2L~1`_w_le0Z!Mifon4E&@Wb&O{%sugBGJLqCz7>G`~{xfD&F{Iwj!Mcz}W5 z(Fbl9K2zyn$Vm~rXb#AG0fIa~{2XHZlE$kHTR}AEjA7S zILQPZR?R^mVg6z(k+*C)h9i5GOndh9h^mO^Kh2rJi>o zYzwUi5Cy_%ErR&uAvMb%SZ0kI9|oV}CZr(u5L~hMGnFnIgJ4XuyB_>NRD%F;sTd?7 z43b2VM<6#XRGcvGkZJ?Kz+EX~X(+=ti3`81>CS~xPhwB@c)fB&YiV48;s6122kfu9 zESS^2hl5>30^=@-U3~qQbB7%W4ncS$AUR#&J&EgNSI<&Ko+y{kQpjT4us0LABl>NU zCH(!9J+9OljmZ@eR8katN7p!BJ(4gNnJ@H0>x9Ttt1k~h7HPmfXC`IeG{$e+91E)- zB@V))!jha#>K|X6)JGe%_^=*vJ3+{+d(rY#49W!M!Xg^@+_%1^5dO_Wx{!0jV zk;BAgzvG0&w6`wlnFJCJ1jJN$9DyXYM{$tVHU`d}fg)7STiDE=dt=H?=qxXov=S({ zVBJ=B=TKoH_T9WU2==xOuI_KVTwL(cy8Yu@$;vj^b}5JToJ*y2n79JEiT&Rpj5GQ_ zmqljHhX8Ad!!yu;Y!P!2Ams3x2#`WoI7Q*qyh+#H-4Xw6S^2o?&7ay+ef`oPqjT!Y z%co#w(cFseKC7OL=h&>j{RrA`0rRJarLUv541m4{ot^(mV5luRrcA`@=W`@3MwKh0 zvzmMTqXX0UjJjo@8DY^PK|(?yeNiJCPbkZdMRve<=G!zqTRvlv;{K1!>DT;djw;{u zV-4#mUo9ZAvGIS8i@5vatKCL`=SGX`V1F6uG7+%N1=31!T&BmQr+UDu6@(;lf>d^p zOq8(07z~UF4X3Ky7he3!cih@Zn}Kgq+l^Z2pC%IDVU3Y|Ag&-e6euavhd5*WsqO%R zDhYvp4Mq(DMlL<`c@s#5$KAw%!CA7{P*h^c z^r3hWbVrYsK+lJnPfu?BQH%)jQ;OcC{#sRI`D>yWY&FK9w&Z|v^ zi>Aemgh0Y8c!9*=7P5pxAELQ+KzNm)F@gm2AdTRX_9BCVet_JX@K4q2U2>~nx!kC` zy1xD|F?>esLH92fCk0-Tfq`6BO5{oIq6C>_T<{~DHRrj$6-kc=b&tQib_(-z*VCUj zsaCvXEayz1FJz>we9ZUHef}AqnlS@H-E`Jz6spMIC>oq@s_}JRreK+b)Ew{0@y6qN@tNclJYvI@Gk7I3dFU#W? zUK~9Smp|td#^Jw$k9)cQ0O`xX{z;csTJ5zgte7rcqxC}?)`Q(cyxKvO@U8NKa1 z*057Ix4d#uIwJw>ElyQgZ!;U}#gb7{(swsCHa1T@e~$G$csEB%T2+(i@u1YIiRhoF zGH#=*Sw}=ibru5VuQ^;zR@>jMp9XoBHP6#3sKJUarGqME&;t6d8fu?V?l(0-3!JO4 z$M1*Qrmmo+dU4^ZAb7!@RaCA_g23h}$k+>;)_;-4sn+d>e?v+B*~!Ci1Q|sqF?ol{!TFDD5(+`5kj)Rc@c*bUkelFB2 z%f!9~8Cl|1M1(qSFo^(sb$%LAZ4>zfb@Lobv*e3)@D+3DfD&%edd&n@mu#1&%&$NN z9IPb5cfHanW=^MP;bq;!C$0w*o4w^jm9l8#snY|?qBMTgPoI?yJMBoV-uM>g;wio79(EX@?c=XYYegYz8T9bw~Hb!75J2Ey5GwccId(qYGK!y zYjK*$5*veRD1m0E!IM+FwE^YaEG=F@b8Uh-6Z6}}QX&-NXM1Sf( zQrzt(d*0SJ(9O65hHFTJ$7_{;

?s}Ls)19_kO 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 KEhwk2-~A7qI_sza literal 0 HcmV?d00001 diff --git a/artifacts/jmh/graph-size.txt b/artifacts/jmh/graph-size.txt new file mode 100644 index 0000000..dce6cae --- /dev/null +++ b/artifacts/jmh/graph-size.txt @@ -0,0 +1,29 @@ +Benchmark (graphSize) Mode Cnt Score Error Units +JmhBfsTest.forkJoinBfs 100 avgt 4 0.043 ± 0.026 ms/op +JmhBfsTest.forkJoinBfs 1000 avgt 4 0.226 ± 0.066 ms/op +JmhBfsTest.forkJoinBfs 10000 avgt 4 2.217 ± 0.288 ms/op +JmhBfsTest.forkJoinBfs 50000 avgt 4 11.955 ± 2.038 ms/op +JmhBfsTest.forkJoinBfs 100000 avgt 4 23.961 ± 2.808 ms/op +JmhBfsTest.forkJoinBfs 1000000 avgt 4 234.495 ± 69.199 ms/op +JmhBfsTest.forkJoinBfs 2000000 avgt 4 437.866 ± 152.712 ms/op +JmhBfsTest.parallelBfs 100 avgt 4 2.571 ± 0.988 ms/op +JmhBfsTest.parallelBfs 1000 avgt 4 2.468 ± 0.873 ms/op +JmhBfsTest.parallelBfs 10000 avgt 4 4.318 ± 1.568 ms/op +JmhBfsTest.parallelBfs 50000 avgt 4 12.274 ± 1.017 ms/op +JmhBfsTest.parallelBfs 100000 avgt 4 26.078 ± 1.949 ms/op +JmhBfsTest.parallelBfs 1000000 avgt 4 459.465 ± 286.051 ms/op +JmhBfsTest.parallelBfs 2000000 avgt 4 772.640 ± 393.633 ms/op +JmhBfsTest.parallelFrontierBfs 100 avgt 4 2.187 ± 1.741 ms/op +JmhBfsTest.parallelFrontierBfs 1000 avgt 4 2.117 ± 0.881 ms/op +JmhBfsTest.parallelFrontierBfs 10000 avgt 4 5.444 ± 3.305 ms/op +JmhBfsTest.parallelFrontierBfs 50000 avgt 4 16.782 ± 11.075 ms/op +JmhBfsTest.parallelFrontierBfs 100000 avgt 4 32.159 ± 9.104 ms/op +JmhBfsTest.parallelFrontierBfs 1000000 avgt 4 354.178 ± 72.852 ms/op +JmhBfsTest.parallelFrontierBfs 2000000 avgt 4 626.251 ± 216.028 ms/op +JmhBfsTest.serialBfs 100 avgt 4 0.002 ± 0.001 ms/op +JmhBfsTest.serialBfs 1000 avgt 4 0.046 ± 0.005 ms/op +JmhBfsTest.serialBfs 10000 avgt 4 0.721 ± 0.172 ms/op +JmhBfsTest.serialBfs 50000 avgt 4 5.449 ± 3.297 ms/op +JmhBfsTest.serialBfs 100000 avgt 4 20.219 ± 4.305 ms/op +JmhBfsTest.serialBfs 1000000 avgt 4 383.653 ± 34.153 ms/op +JmhBfsTest.serialBfs 2000000 avgt 4 622.543 ± 70.652 ms/op diff --git a/artifacts/jmh/threads.txt b/artifacts/jmh/threads.txt new file mode 100644 index 0000000..7ab66aa --- /dev/null +++ b/artifacts/jmh/threads.txt @@ -0,0 +1,15 @@ +Benchmark (runtime) Mode Cnt Score Error Units +JmhBfsResourceTest.parallelBfs 1 avgt 4 811.736 ± 532.065 ms/op +JmhBfsResourceTest.parallelBfs 2 avgt 4 800.443 ± 213.065 ms/op +JmhBfsResourceTest.parallelBfs 4 avgt 4 786.551 ± 188.788 ms/op +JmhBfsResourceTest.parallelBfs 6 avgt 4 746.592 ± 310.785 ms/op +JmhBfsResourceTest.parallelBfs 12 avgt 4 726.113 ± 108.879 ms/op +JmhBfsResourceTest.parallelBfs 16 avgt 4 746.983 ± 143.357 ms/op +JmhBfsResourceTest.parallelBfs 24 avgt 4 787.820 ± 211.231 ms/op +JmhBfsResourceTest.parallelFrontierBfs 1 avgt 4 967.328 ± 479.491 ms/op +JmhBfsResourceTest.parallelFrontierBfs 2 avgt 4 623.180 ± 302.594 ms/op +JmhBfsResourceTest.parallelFrontierBfs 4 avgt 4 558.315 ± 282.455 ms/op +JmhBfsResourceTest.parallelFrontierBfs 6 avgt 4 732.789 ± 298.786 ms/op +JmhBfsResourceTest.parallelFrontierBfs 12 avgt 4 798.175 ± 286.191 ms/op +JmhBfsResourceTest.parallelFrontierBfs 16 avgt 4 746.080 ± 201.253 ms/op +JmhBfsResourceTest.parallelFrontierBfs 24 avgt 4 775.214 ± 253.786 ms/op diff --git a/artifacts/threads.png b/artifacts/threads.png new file mode 100644 index 0000000000000000000000000000000000000000..1831877a28214a1da133b984326a7444cc81bdee GIT binary patch literal 47273 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 literal 0 HcmV?d00001 diff --git a/build.gradle.kts b/build.gradle.kts index 4716601..d2c376d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,6 +2,8 @@ plugins { kotlin("jvm") version "1.9.20" java application + id("me.champeau.jmh") version "0.7.3" + // id("org.openjdk.jcstress") version "0.15" } group = "org.itmo" @@ -29,6 +31,16 @@ application { mainClass.set("MainKt") } +jmh { + jvmArgs = listOf("--enable-native-access=ALL-UNNAMED", "--add-opens=java.base/java.lang=ALL-UNNAMED") +} + +sourceSets { + test { + java.srcDirs("src/test/kotlin", "src/test/java") + } +} + // JCStress runner task: runs JCStress tests located on the test runtime classpath // Use: ./gradlew jcstress [-PjcstressArgs="-v -m quick"] tasks.register("jcstress") { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 62f495d..b82aa23 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/jmh/kotlin/org/itmo/bfs/JmhBfsResourceTest.kt b/src/jmh/kotlin/org/itmo/bfs/JmhBfsResourceTest.kt new file mode 100644 index 0000000..7178381 --- /dev/null +++ b/src/jmh/kotlin/org/itmo/bfs/JmhBfsResourceTest.kt @@ -0,0 +1,63 @@ +package org.itmo.bfs + +import org.itmo.Graph +import org.itmo.RandomGraphGenerator +import org.itmo.bfs.impl.ParallelBfs +import org.itmo.bfs.impl.ParallelFrontierBfs +import org.openjdk.jmh.annotations.Benchmark +import org.openjdk.jmh.annotations.BenchmarkMode +import org.openjdk.jmh.annotations.Fork +import org.openjdk.jmh.annotations.Measurement +import org.openjdk.jmh.annotations.Mode +import org.openjdk.jmh.annotations.OutputTimeUnit +import org.openjdk.jmh.annotations.Param +import org.openjdk.jmh.annotations.Scope +import org.openjdk.jmh.annotations.Setup +import org.openjdk.jmh.annotations.State +import org.openjdk.jmh.annotations.Warmup +import org.openjdk.jmh.infra.Blackhole +import java.util.concurrent.TimeUnit +import kotlin.math.min + +@Fork(1) +@State(Scope.Benchmark) +@Warmup(iterations = 1, time = 5) +@Measurement(iterations = 4, time = 5) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +open class JmhBfsResourceTest { + + @Param("1", "2", "4", "6", "12", "16", "24") + private var runtime = 0 + + private var connections = 0 + private lateinit var graph: Graph + + private lateinit var parallelFrontierBfs: Bfs + private lateinit var parallelBfs: Bfs + + @Setup + fun setup() { + val graphSize = 2_000_000 + connections = min(graphSize * 10, 10_000_000) + + println("Генерация графа размером $graphSize с $connections рёбрами...") + + graph = RandomGraphGenerator().generateGraph(java.util.Random(42), graphSize, connections) + + println("Генерация завершена.") + + parallelBfs = ParallelBfs(runtime) + parallelFrontierBfs = ParallelFrontierBfs(runtime) + } + + @Benchmark + fun parallelBfs(bh: Blackhole) { + bh.consume(parallelBfs.bfs(graph, 0)) + } + + @Benchmark + fun parallelFrontierBfs(bh: Blackhole) { + bh.consume(parallelFrontierBfs.bfs(graph, 0)) + } +} diff --git a/src/jmh/kotlin/org/itmo/bfs/JmhBfsTest.kt b/src/jmh/kotlin/org/itmo/bfs/JmhBfsTest.kt new file mode 100644 index 0000000..8a1e160 --- /dev/null +++ b/src/jmh/kotlin/org/itmo/bfs/JmhBfsTest.kt @@ -0,0 +1,75 @@ +package org.itmo.bfs + +import org.itmo.Graph +import org.itmo.RandomGraphGenerator +import org.itmo.bfs.impl.ForkJoinBfs +import org.itmo.bfs.impl.ParallelBfs +import org.itmo.bfs.impl.ParallelFrontierBfs +import org.itmo.bfs.impl.SimpleBfs +import org.openjdk.jmh.annotations.Benchmark +import org.openjdk.jmh.annotations.BenchmarkMode +import org.openjdk.jmh.annotations.Fork +import org.openjdk.jmh.annotations.Measurement +import org.openjdk.jmh.annotations.Mode +import org.openjdk.jmh.annotations.OutputTimeUnit +import org.openjdk.jmh.annotations.Param +import org.openjdk.jmh.annotations.Scope +import org.openjdk.jmh.annotations.Setup +import org.openjdk.jmh.annotations.State +import org.openjdk.jmh.annotations.Warmup +import org.openjdk.jmh.infra.Blackhole +import java.util.concurrent.TimeUnit +import kotlin.math.min + +@Fork(1) +@State(Scope.Benchmark) +@Warmup(iterations = 1, time = 5) +@Measurement(iterations = 4, time = 5) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +open class JmhBfsTest { + + @Param("10", "100", "1000", "10000", "50000", "100000", "1000000", "2000000") + private var graphSize = 0 + + private var connections = 0 + private lateinit var graph: Graph + + private val runtime = Runtime.getRuntime().availableProcessors() * 2 + + private val simpleBfs = SimpleBfs() + private val forkJoinBfs = ForkJoinBfs() + private val parallelFrontierBfs = ParallelFrontierBfs(runtime) + private val parallelBfs = ParallelBfs(runtime) + + @Setup + fun setup() { + connections = min(graphSize * 10, 10_000_000) + + println("Генерация графа размером $graphSize с $connections рёбрами...") + + graph = RandomGraphGenerator().generateGraph(java.util.Random(42), graphSize, connections) + + println("Генерация завершена.") + } + + @Benchmark + fun serialBfs(bh: Blackhole) { + bh.consume(simpleBfs.bfs(graph, 0)) + } + + @Benchmark + fun parallelBfs(bh: Blackhole) { + bh.consume(parallelBfs.bfs(graph, 0)) + } + + @Benchmark + fun parallelFrontierBfs(bh: Blackhole) { + bh.consume(parallelFrontierBfs.bfs(graph, 0)) + } + + @Benchmark + fun forkJoinBfs(bh: Blackhole) { + bh.consume(forkJoinBfs.bfs(graph, 0)) + } +} diff --git a/src/main/java/org/itmo/UnsafeCounter.java b/src/main/java/org/itmo/UnsafeCounter.java deleted file mode 100644 index 1041a21..0000000 --- a/src/main/java/org/itmo/UnsafeCounter.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.itmo; - -public class UnsafeCounter { - private int counter = 0; - - public void increment() { - counter++; // <-- гонка данных - } - - public int get() { - return counter; - } -} diff --git a/src/main/java/org/itmo/bfs/impl/ParallelBfs.java b/src/main/java/org/itmo/bfs/impl/ParallelBfs.java index 5aa211e..c44c912 100644 --- a/src/main/java/org/itmo/bfs/impl/ParallelBfs.java +++ b/src/main/java/org/itmo/bfs/impl/ParallelBfs.java @@ -8,6 +8,7 @@ import org.itmo.Graph; import org.itmo.bfs.Bfs; +// unfortunately, this implementation is not working public class ParallelBfs implements Bfs { private final int threadNumber; @@ -38,7 +39,7 @@ public void bfs(Graph graph, int startVertex) { }); } - private record BfsWorker( + public record BfsWorker( Graph graph, AtomicIntegerArray distances, Queue queue, diff --git a/src/test/java/org/itmo/BFSTest.java b/src/test/java/org/itmo/BFSTest.java index 0909972..da138ec 100644 --- a/src/test/java/org/itmo/BFSTest.java +++ b/src/test/java/org/itmo/BFSTest.java @@ -39,6 +39,35 @@ public void bfsTest() throws IOException { } } + @Test + public void bfsThreadsTest() throws IOException { + int graphSize = 2_000_000; + int connections = 10_000_000; + int[] threadCounts = new int[]{1, 2, 4, 8, 12, 16, 24}; + Random r = new Random(42); + + System.out.println("Generating graph of size " + graphSize + " with " + connections + " connections... wait"); + Graph g = new RandomGraphGenerator().generateGraph(r, graphSize, connections); + System.out.println("Graph generation completed!"); + + try (FileWriter fw = new FileWriter("tmp/threads_results.txt")) { + for (int threads : threadCounts) { + System.out.println("--------------------------"); + System.out.println("Running BFS with " + threads + " threads"); + var bfs = new ParallelFrontierBfs(threads); + long startTime = System.nanoTime(); + bfs.bfs(g, 0); + long endTime = System.nanoTime(); + long result = (endTime - startTime) / 1_000_000; + + fw.append("Times for " + graphSize + " vertices, " + connections + " connections and " + threads + " threads:\n"); + fw.append("Frontier: " + result + "\n"); + fw.append("--------\n"); + fw.flush(); + } + } + } + private long executeSerialBfsAndGetTime(Graph g) { var bfs = new SimpleBfs(); long startTime = System.nanoTime(); diff --git a/src/test/java/org/itmo/ParallelBfsTest.java b/src/test/java/org/itmo/ParallelBfsTest.java new file mode 100644 index 0000000..d467ff7 --- /dev/null +++ b/src/test/java/org/itmo/ParallelBfsTest.java @@ -0,0 +1,114 @@ +package org.itmo; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; +import java.util.Random; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicIntegerArray; +import org.itmo.bfs.impl.ParallelBfs.BfsWorker; +import org.openjdk.jcstress.annotations.Actor; +import org.openjdk.jcstress.annotations.Arbiter; +import org.openjdk.jcstress.annotations.Expect; +import org.openjdk.jcstress.annotations.JCStressTest; +import org.openjdk.jcstress.annotations.Outcome; +import org.openjdk.jcstress.annotations.State; +import org.openjdk.jcstress.infra.results.I_Result; + +@JCStressTest +@Outcome(id = "0", expect = Expect.ACCEPTABLE, desc = "Нет нарушений") +@State +public class ParallelBfsTest { + + private final Graph graph = new RandomGraphGenerator().generateGraph(new Random(42), 1000, 100000); + + private final AtomicInteger activeNodes = new AtomicInteger(1); + private final AtomicIntegerArray distances = new AtomicIntegerArray(graph.getSize()); + private final ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>(); + + { + queue.add(0); + } + + @Actor + public void actor1() { + Thread t = new Thread(new BfsWorker(graph, distances, queue, activeNodes)); + t.start(); + + try { + t.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + @Actor + public void actor2() { + Thread t = new Thread(new BfsWorker(graph, distances, queue, activeNodes)); + t.start(); + + try { + t.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + @Actor + public void actor3() { + Thread t = new Thread(new BfsWorker(graph, distances, queue, activeNodes)); + t.start(); + + try { + t.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + @Actor + public void actor4() { + Thread t = new Thread(new BfsWorker(graph, distances, queue, activeNodes)); + t.start(); + + try { + t.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + @Arbiter + public void arbiter(I_Result r) { + List distancesSimple = new ArrayList<>(); + for (int i = 0; i < distances.length(); i++) { + distancesSimple.add(0); + } + + Queue queue = new LinkedList<>(); + + queue.add(0); + + while (!queue.isEmpty()) { + int vertex = queue.poll(); + + for (int neighbor : graph.getAdjList()[vertex]) { + if (distancesSimple.get(neighbor).equals(0)) { + distancesSimple.set(neighbor, distancesSimple.get(vertex) - 1); + queue.add(neighbor); + } + } + } + + int result = 0; + for (int i = 0; i < graph.getSize(); i++) { + if (!distancesSimple.get(i).equals(distances.get(i))) { + result++; + } + } + + r.r1 = result; + } +} diff --git a/src/test/java/org/itmo/RandomGraphGenerator.java b/src/test/java/org/itmo/RandomGraphGenerator.java index 11c5049..efd7885 100644 --- a/src/test/java/org/itmo/RandomGraphGenerator.java +++ b/src/test/java/org/itmo/RandomGraphGenerator.java @@ -22,7 +22,7 @@ private int unpackV(long key) { return (int) (key & 0xffffffffL); } - Graph generateGraph(Random r, int size, int numEdges) { + public Graph generateGraph(Random r, int size, int numEdges) { if (size < 1) throw new IllegalArgumentException("size must be >= 1"); if (numEdges < size - 1) throw new IllegalArgumentException("We need min size-1 edges"); long maxDirected = (long) size * (size - 1); diff --git a/src/test/java/org/itmo/UnsafeCounterTest.java b/src/test/java/org/itmo/UnsafeCounterTest.java deleted file mode 100644 index a831605..0000000 --- a/src/test/java/org/itmo/UnsafeCounterTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.itmo; - -import org.openjdk.jcstress.annotations.*; -import org.openjdk.jcstress.infra.results.I_Result; - -@JCStressTest -@Outcome(id = "5", expect = Expect.ACCEPTABLE, desc = "Все 5 инкрементов выполнены корректно") -@Outcome(id = "1", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Гонка данных: часть инкрементов потерялась") -@Outcome(id = "2", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Гонка данных: часть инкрементов потерялась") -@Outcome(id = "3", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Гонка данных: часть инкрементов потерялась") -@Outcome(id = "4", expect = Expect.ACCEPTABLE_INTERESTING, desc = "Гонка данных: часть инкрементов потерялась") -@State -public class UnsafeCounterTest { - - private UnsafeCounter counter = new UnsafeCounter(); - - @Actor public void actor1() { counter.increment(); } - @Actor public void actor2() { counter.increment(); } - @Actor public void actor3() { counter.increment(); } - @Actor public void actor4() { counter.increment(); } - @Actor public void actor5() { counter.increment(); } - - @Arbiter - public void arbiter(I_Result r) { - r.r1 = counter.get(); - } -} diff --git a/tmp/results.txt b/tmp/results.txt index 374c3f1..fae4a4f 100644 --- a/tmp/results.txt +++ b/tmp/results.txt @@ -1,54 +1,54 @@ Times for 10 vertices and 50 connections: Serial: 0 ForkJoin: 1 -Frontier: 2 +Frontier: 1 Parallel: 3 -------- Times for 100 vertices and 500 connections: Serial: 0 -ForkJoin: 6 -Frontier: 7 +ForkJoin: 3 +Frontier: 5 Parallel: 3 -------- Times for 1000 vertices and 5000 connections: -Serial: 0 -ForkJoin: 2 -Frontier: 37 -Parallel: 50 +Serial: 1 +ForkJoin: 7 +Frontier: 25 +Parallel: 20 -------- Times for 10000 vertices and 50000 connections: -Serial: 3 -ForkJoin: 16 -Frontier: 73 -Parallel: 29 +Serial: 4 +ForkJoin: 15 +Frontier: 33 +Parallel: 33 -------- Times for 10000 vertices and 100000 connections: -Serial: 2 -ForkJoin: 3 -Frontier: 16 -Parallel: 7 +Serial: 7 +ForkJoin: 4 +Frontier: 19 +Parallel: 5 -------- Times for 50000 vertices and 1000000 connections: Serial: 28 -ForkJoin: 29 -Frontier: 72 -Parallel: 37 +ForkJoin: 21 +Frontier: 38 +Parallel: 43 -------- Times for 100000 vertices and 1000000 connections: -Serial: 53 -ForkJoin: 19 -Frontier: 48 -Parallel: 107 +Serial: 47 +ForkJoin: 36 +Frontier: 66 +Parallel: 60 -------- Times for 1000000 vertices and 10000000 connections: -Serial: 683 -ForkJoin: 307 -Frontier: 472 -Parallel: 679 +Serial: 525 +ForkJoin: 304 +Frontier: 538 +Parallel: 576 -------- Times for 2000000 vertices and 10000000 connections: -Serial: 927 -ForkJoin: 533 -Frontier: 775 -Parallel: 1113 +Serial: 876 +ForkJoin: 531 +Frontier: 702 +Parallel: 1061 -------- diff --git a/tmp/threads_results.txt b/tmp/threads_results.txt new file mode 100644 index 0000000..8f52319 --- /dev/null +++ b/tmp/threads_results.txt @@ -0,0 +1,21 @@ +Times for 2000000 vertices, 10000000 connections and 1 threads: +Frontier: 1027 +-------- +Times for 2000000 vertices, 10000000 connections and 2 threads: +Frontier: 767 +-------- +Times for 2000000 vertices, 10000000 connections and 4 threads: +Frontier: 694 +-------- +Times for 2000000 vertices, 10000000 connections and 8 threads: +Frontier: 733 +-------- +Times for 2000000 vertices, 10000000 connections and 12 threads: +Frontier: 816 +-------- +Times for 2000000 vertices, 10000000 connections and 16 threads: +Frontier: 887 +-------- +Times for 2000000 vertices, 10000000 connections and 24 threads: +Frontier: 814 +--------