Skip to content

Commit ad86ced

Browse files
author
ar.r.lysenko
committed
add parallel impl, but it sucks
1 parent 6292a38 commit ad86ced

File tree

3 files changed

+117
-17
lines changed

3 files changed

+117
-17
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,82 @@
11
package org.itmo.bfs.impl;
22

3+
import java.util.Queue;
4+
import java.util.concurrent.ConcurrentLinkedQueue;
5+
import java.util.concurrent.atomic.AtomicInteger;
6+
import java.util.concurrent.atomic.AtomicIntegerArray;
7+
import java.util.stream.IntStream;
38
import org.itmo.Graph;
49
import org.itmo.bfs.Bfs;
510

611
public class ParallelBfs implements Bfs {
712

13+
private final int threadNumber;
14+
15+
public ParallelBfs(int threadNumber) {
16+
this.threadNumber = threadNumber;
17+
}
18+
819
@Override
920
public void bfs(Graph graph, int startVertex) {
21+
AtomicInteger activeNodes = new AtomicInteger(1);
22+
AtomicIntegerArray distances = new AtomicIntegerArray(graph.getSize());
23+
ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<>();
24+
25+
queue.add(startVertex);
26+
distances.set(startVertex, 0);
27+
28+
IntStream.range(0, threadNumber)
29+
.mapToObj(i ->
30+
new Thread(new BfsWorker(graph, distances, queue, activeNodes))
31+
)
32+
.peek(Thread::start)
33+
.forEach(thread -> {
34+
try {
35+
thread.join();
36+
} catch (Exception e) {
37+
throw new RuntimeException(e);
38+
}
39+
});
40+
}
41+
42+
private record BfsWorker(
43+
Graph graph,
44+
AtomicIntegerArray distances,
45+
Queue<Integer> queue,
46+
AtomicInteger activeNodes
47+
) implements Runnable {
48+
49+
@Override
50+
public void run() {
51+
var adjList = graph.getAdjList();
52+
while (activeNodes.get() > 0) {
53+
var currentVertex = queue.poll();
54+
if (currentVertex == null) {
55+
continue;
56+
}
57+
int d = distances.get(currentVertex);
58+
for (var neighbor : adjList[currentVertex]) {
59+
if (updateDistanceIfLower(neighbor, d - 1)) {
60+
queue.add(neighbor);
61+
activeNodes.incrementAndGet();
62+
}
63+
}
64+
activeNodes.decrementAndGet();
65+
}
66+
}
67+
68+
private boolean updateDistanceIfLower(int node, int newDistance) {
69+
while (true) {
70+
int currentDistance = distances.get(node);
71+
72+
if (newDistance >= currentDistance || currentDistance != 0) {
73+
return false;
74+
}
1075

76+
if (distances.compareAndSet(node, currentDistance, newDistance)) {
77+
return true;
78+
}
79+
}
80+
}
1181
}
1282
}

src/test/java/org/itmo/BFSTest.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,24 @@ public void kek() {
2828
System.out.println("ForkJoin " + time2);
2929
}
3030

31+
@Test
32+
public void lotOfConnectionsTest() {
33+
int size = 1_000_000;
34+
int connections = 15_000_000;
35+
Random r = new Random(42);
36+
37+
System.out.println("Generating graph of size " + size + " ...wait");
38+
Graph g = new RandomGraphGenerator().generateGraph(r, size, connections);
39+
System.out.println("Generation completed!\nStarting bfs");
40+
41+
long serialTime = executeSerialBfsAndGetTime(g);
42+
long parallelTime = executeParallelBfsAndGetTime(g);
43+
44+
System.out.println("Times for " + size + " vertices and " + connections + " connections: ");
45+
System.out.println("Serial: " + serialTime);
46+
System.out.println("Parallel: " + parallelTime);
47+
}
48+
3149
@Test
3250
public void bfsTest() throws IOException {
3351
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 {
4058
Graph g = new RandomGraphGenerator().generateGraph(r, sizes[i], connections[i]);
4159
System.out.println("Generation completed!\nStarting bfs");
4260
long serialTime = executeSerialBfsAndGetTime(g);
61+
long forkJoinTime = executeForkJoinBfs(g);
4362
long parallelTime = executeParallelBfsAndGetTime(g);
4463
fw.append("Times for " + sizes[i] + " vertices and " + connections[i] + " connections: ");
4564
fw.append("\nSerial: " + serialTime);
65+
fw.append("\nForkJoin: " + forkJoinTime);
4666
fw.append("\nParallel: " + parallelTime);
4767
fw.append("\n--------\n");
4868
}
@@ -59,7 +79,8 @@ private long executeSerialBfsAndGetTime(Graph g) {
5979
}
6080

6181
private long executeParallelBfsAndGetTime(Graph g) {
62-
var bfs = new ParallelBfs(1);
82+
var runtime = Runtime.getRuntime().availableProcessors() * 2;
83+
var bfs = new ParallelBfs(runtime);
6384
long startTime = System.nanoTime();
6485
bfs.bfs(g, 0);
6586
long endTime = System.nanoTime();

tmp/results.txt

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,45 @@
11
Times for 10 vertices and 50 connections:
22
Serial: 0
3-
Parallel: 0
3+
ForkJoin: 3
4+
Parallel: 6
45
--------
56
Times for 100 vertices and 500 connections:
6-
Serial: 0
7-
Parallel: 0
7+
Serial: 1
8+
ForkJoin: 1
9+
Parallel: 38
810
--------
911
Times for 1000 vertices and 5000 connections:
10-
Serial: 1
11-
Parallel: 0
12+
Serial: 2
13+
ForkJoin: 2
14+
Parallel: 19
1215
--------
1316
Times for 10000 vertices and 50000 connections:
1417
Serial: 4
15-
Parallel: 0
18+
ForkJoin: 18
19+
Parallel: 10
1620
--------
1721
Times for 10000 vertices and 100000 connections:
18-
Serial: 3
19-
Parallel: 0
22+
Serial: 2
23+
ForkJoin: 17
24+
Parallel: 11
2025
--------
2126
Times for 50000 vertices and 1000000 connections:
22-
Serial: 22
23-
Parallel: 0
27+
Serial: 27
28+
ForkJoin: 15
29+
Parallel: 34
2430
--------
2531
Times for 100000 vertices and 1000000 connections:
26-
Serial: 21
27-
Parallel: 0
32+
Serial: 33
33+
ForkJoin: 30
34+
Parallel: 40
2835
--------
2936
Times for 1000000 vertices and 10000000 connections:
30-
Serial: 419
31-
Parallel: 0
37+
Serial: 600
38+
ForkJoin: 251
39+
Parallel: 649
3240
--------
3341
Times for 2000000 vertices and 10000000 connections:
34-
Serial: 755
35-
Parallel: 0
42+
Serial: 932
43+
ForkJoin: 539
44+
Parallel: 971
3645
--------

0 commit comments

Comments
 (0)