From 6f4dd96b4f2e94bfe82a39ca1f2061fbac2cace6 Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 16:19:38 +0000 Subject: [PATCH 1/4] Setting up GitHub Classroom Feedback From 38ae4eff3dbffc06927074db80564d4aeee722b6 Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 16:19:41 +0000 Subject: [PATCH 2/4] 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 e152a8669e368b3f52381cf1df4a92204971b44f Mon Sep 17 00:00:00 2001 From: poma12390 Date: Tue, 14 Oct 2025 03:02:48 +0300 Subject: [PATCH 3/4] lab1 done --- bench_bfs.py | 171 ++++++++++++++ build.gradle.kts | 13 ++ gradle.properties | 1 + results/index.html | 124 +++++++++++ ...g.itmo.BucketsPublicationViaQueueTest.html | 208 ++++++++++++++++++ results/org.itmo.VisitCASRaceTest.html | 208 ++++++++++++++++++ .../itmo/BucketsPublicationViaQueueTest.java | 38 ++++ .../java/org/itmo/VisitCASRaceTest.java | 41 ++++ src/main/java/org/itmo/Graph.java | 176 ++++++++++++--- tmp/plot_parallel_vs_cpu.png | Bin 0 -> 43806 bytes tmp/plot_serial_vs_parallel_vs_size.png | Bin 0 -> 45799 bytes tmp/results.txt | 28 ++- 12 files changed, 971 insertions(+), 37 deletions(-) create mode 100644 bench_bfs.py create mode 100644 results/index.html create mode 100644 results/org.itmo.BucketsPublicationViaQueueTest.html create mode 100644 results/org.itmo.VisitCASRaceTest.html create mode 100644 src/jcstress/java/org/itmo/BucketsPublicationViaQueueTest.java create mode 100644 src/jcstress/java/org/itmo/VisitCASRaceTest.java create mode 100644 tmp/plot_parallel_vs_cpu.png create mode 100644 tmp/plot_serial_vs_parallel_vs_size.png diff --git a/bench_bfs.py b/bench_bfs.py new file mode 100644 index 0000000..9bab283 --- /dev/null +++ b/bench_bfs.py @@ -0,0 +1,171 @@ +import argparse +import csv +import os +import re +import shutil +import subprocess +import sys +import time +from pathlib import Path +from typing import List, Dict, Any, Tuple + +RESULTS_FILE_NAME = "results.txt" +RESULTS_PATTERN = re.compile( + r"Times for\s+(\d+)\s+vertices\s+and\s+(\d+)\s+connections:\s*" + r"Serial:\s*(\d+)\s*" + r"Parallel:\s*(\d+)\s*", + re.IGNORECASE | re.MULTILINE +) + +def run_gradle_test(project: Path, test_filter: str, cpu: int, clean: bool, extra_args: List[str]) -> None: + is_windows = os.name == "nt" + gradlew = "gradlew.bat" if is_windows else "./gradlew" + + cmd = [gradlew] + if clean: + cmd.append("clean") + cmd += ["test", "--no-daemon", "--tests", test_filter] + cmd += extra_args + + env = os.environ.copy() + jto = ( + f"-Xms4g -Xmx4g " + f"-XX:+UseG1GC -XX:ParallelGCThreads=1 -XX:ConcGCThreads=1 -XX:+AlwaysPreTouch " + f"-Dbfs.threads={cpu} -Dfile.encoding=UTF-8" + ) + env["JAVA_TOOL_OPTIONS"] = (env.get("JAVA_TOOL_OPTIONS", "") + " " + jto).strip() + env["GRADLE_OPTS"] = (env.get("GRADLE_OPTS", "") + f" -Dbfs.threads={cpu}").strip() + + print(f"[run] CPU={cpu} :: {' '.join(cmd)}") + subprocess.run(cmd, cwd=str(project), env=env, check=True) + + + +def parse_results(text: str) -> List[Tuple[int, int, int, int]]: + out = [] + for m in RESULTS_PATTERN.finditer(text): + v = int(m.group(1)) + e = int(m.group(2)) + s = int(m.group(3)) + p = int(m.group(4)) + out.append((v, e, s, p)) + return out + + +def main(): + ap = argparse.ArgumentParser(description="Benchmark Parallel vs Serial BFS via Gradle test runs") + ap.add_argument("--project", required=True, help="Путь к проекту с tmp\\results.txt") + ap.add_argument("--test", default="org.itmo.BFSTest", help="Фильтр теста (--tests)") + ap.add_argument("--cpu", default="1,2,4,6,8", help="Список CPU для -XX:ActiveProcessorCount (через запятую)") + ap.add_argument("--no-clean", action="store_true", help="Не выполнять gradle clean перед каждым тестом") + ap.add_argument("--plot", action="store_true", help="Строить PNG-графики после парсинга") + ap.add_argument("--extra", default="", help="Доп. аргументы для Gradle, например: --info") + args = ap.parse_args() + + project = Path(args.project).resolve() + tmp_dir = project / "tmp" + tmp_dir.mkdir(parents=True, exist_ok=True) + raw_results = tmp_dir / RESULTS_FILE_NAME + cpu_list = [int(x) for x in args.cpu.split(",") if x.strip()] + clean_each = not args.no_clean + extra_args = args.extra.split() if args.extra.strip() else [] + + combined_rows: List[Dict[str, Any]] = [] + + for cpu in cpu_list: + if raw_results.exists(): + raw_results.unlink() + + start = time.time() + run_gradle_test(project, args.test, cpu, clean_each, extra_args) + dur = time.time() - start + print(f"[ok] CPU={cpu} :: build+test finished in {dur:.1f}s") + + if not raw_results.exists(): + print(f"[warn] {raw_results} not found after test run.", file=sys.stderr) + continue + + snapshot = tmp_dir / f"results_{cpu}cpu.txt" + shutil.copyfile(raw_results, snapshot) + print(f"[save] Snapshot -> {snapshot}") + + text = raw_results.read_text(encoding="utf-8", errors="ignore") + parsed = parse_results(text) + if not parsed: + print(f"[warn] No blocks parsed for CPU={cpu}", file=sys.stderr) + + for (v, e, s, p) in parsed: + combined_rows.append({ + "vertices": v, + "connections": e, + "serial_ms": s, + "parallel_ms": p, + "cpu": cpu, + }) + + csv_path = tmp_dir / "perf_data.csv" + with csv_path.open("w", newline="", encoding="utf-8") as f: + w = csv.DictWriter(f, fieldnames=["vertices", "connections", "cpu", "serial_ms", "parallel_ms"]) + w.writeheader() + for row in sorted(combined_rows, key=lambda r: (r["vertices"], r["connections"], r["cpu"])): + w.writerow(row) + + print(f"[csv] Written {csv_path} with {len(combined_rows)} rows") + + if args.plot: + try: + import matplotlib.pyplot as plt + except Exception as e: + print(f"[plot] matplotlib не установлен: {e}. Установите: pip install matplotlib", file=sys.stderr) + return + + if combined_rows: + all_sizes = {(r["vertices"], r["connections"]) for r in combined_rows} + pick_vertices = max(v for (v, _) in all_sizes) + pick_conns = max(e for (v, e) in all_sizes if v == pick_vertices) + + rows1 = [r for r in combined_rows if r["vertices"] == pick_vertices and r["connections"] == pick_conns] + rows1.sort(key=lambda r: r["cpu"]) + + xs = [r["cpu"] for r in rows1] + ys = [r["parallel_ms"] for r in rows1] + + plt.figure() + plt.title(f"Parallel BFS time vs CPU\n(V={pick_vertices}, E={pick_conns})") + plt.xlabel("ActiveProcessorCount (CPU)") + plt.ylabel("Time, ms (parallel)") + plt.plot(xs, ys, marker="o") + out1 = tmp_dir / "plot_parallel_vs_cpu.png" + plt.savefig(out1, dpi=150, bbox_inches="tight") + print(f"[plot] {out1}") + + if combined_rows: + max_cpu = max(r["cpu"] for r in combined_rows) + rows2 = [r for r in combined_rows if r["cpu"] == max_cpu] + agg: Dict[int, Dict[str, float]] = {} + for r in rows2: + v = r["vertices"] + if v not in agg: + agg[v] = {"serial": r["serial_ms"], "parallel": r["parallel_ms"]} + else: + agg[v]["serial"] = min(agg[v]["serial"], r["serial_ms"]) + agg[v]["parallel"] = min(agg[v]["parallel"], r["parallel_ms"]) + + vs_sorted = sorted(agg.keys()) + serials = [agg[v]["serial"] for v in vs_sorted] + pars = [agg[v]["parallel"] for v in vs_sorted] + + plt.figure() + plt.title(f"Serial vs Parallel vs Size (CPU={max_cpu})") + plt.xlabel("Vertices") + plt.ylabel("Time, ms") + plt.plot(vs_sorted, serials, marker="o", label="Serial") + plt.plot(vs_sorted, pars, marker="s", label="Parallel") + plt.legend() + out2 = tmp_dir / "plot_serial_vs_parallel_vs_size.png" + plt.savefig(out2, dpi=150, bbox_inches="tight") + print(f"[plot] {out2}") + + +if __name__ == "__main__": + main() diff --git a/build.gradle.kts b/build.gradle.kts index 3341beb..b6b8edb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,7 @@ plugins { kotlin("jvm") version "1.9.20" application + id("io.github.reyerizo.gradle.jcstress") version "0.8.15" } group = "org.itmo" @@ -17,6 +18,18 @@ dependencies { tasks.test { useJUnitPlatform() } +jcstress { + mode = "default" + timeMillis = "300" + forks = "2" + jcstressDependency = "org.openjdk.jcstress:jcstress-core:0.16" +} + +tasks.withType().configureEach { + useJUnitPlatform() + minHeapSize = "2g" + maxHeapSize = "6g" +} kotlin { jvmToolchain(8) diff --git a/gradle.properties b/gradle.properties index 7fc6f1f..7638915 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1,2 @@ kotlin.code.style=official +#org.gradle.jvmargs=-Xms2g -Xmx6g -XX:MaxMetaspaceSize=512m -Dfile.encoding=UTF-8 diff --git a/results/index.html b/results/index.html new file mode 100644 index 0000000..95a5116 --- /dev/null +++ b/results/index.html @@ -0,0 +1,124 @@ + + + +Java Concurrency Stress test report + + + + + + + + +
+

+100% +

+ + + +
 
Overall pass rate: 1/1 
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
java.specification.nameJava Platform API Specification
java.specification.vendorOracle Corporation
java.specification.version1.8
java.vendorTemurin
java.version1.8.0_462
java.vm.nameOpenJDK 64-Bit Server VM
java.vm.vendorTemurin
java.vm.version25.462-b08
os.archamd64
os.nameWindows 11
os.version10.0
+
+
+

FAILED tests

+

Strong asserts were violated. Correct implementations should have no assert failures here.

+ +
+None! +
+
+
+

ERROR tests

+

Tests break for some reason, other than failing the assert. Correct implementations should have none.

+ +
+None! +
+
+
+

INTERESTING tests

+

Some interesting behaviors observed. This is for the plain curiosity.

+ +
+None! +
+
+
+

All tests

+

+ + + + + + + +
   org.itmo.VisitCASRaceTest108PASSED
+
+ + diff --git a/results/org.itmo.BucketsPublicationViaQueueTest.html b/results/org.itmo.BucketsPublicationViaQueueTest.html new file mode 100644 index 0000000..6b2d1ad --- /dev/null +++ b/results/org.itmo.BucketsPublicationViaQueueTest.html @@ -0,0 +1,208 @@ + + + +Java Concurrency Stress test report + + + +

org.itmo.BucketsPublicationViaQueueTest

+

Description and references

+

null

+

Environment

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
java.specification.nameJava Platform API Specification
java.specification.vendorOracle Corporation
java.specification.version1.8
java.vendorTemurin
java.version1.8.0_462
java.vm.nameOpenJDK 64-Bit Server VM
java.vm.vendorTemurin
java.vm.version25.462-b08
os.archamd64
os.nameWindows 11
os.version10.0
+

Results

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Compilation ModeScheduling ClassJava OptionsStatusObserved States
-11
AcceptableAcceptable
Маркер не полученПосле получения маркера данные видны
unified across all actors
+
    writer: package group free, core group free
+    reader: package group free, core group free
+
+
[-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2025.1\lib\idea_rt.jar=61169, -Dfile.encoding=UTF-8, -XX:+UseBiasedLocking, -XX:-TieredCompilation]
+
OK288830941210237
unified across all actors
+
    writer: package group free, core group free
+    reader: package group free, core group free
+
+
[-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2025.1\lib\idea_rt.jar=61169, -Dfile.encoding=UTF-8, -XX:+UseBiasedLocking, -XX:-TieredCompilation, -XX:+StressLCM, -XX:+StressGCM]
+
OK1392440295273186
unified across all actors
+
    writer: package group free, core group free
+    reader: package group free, core group free
+
+
[-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2025.1\lib\idea_rt.jar=61169, -Dfile.encoding=UTF-8, -XX:+UseBiasedLocking, -XX:TieredStopAtLevel=1]
+
OK175852062329565
unified across all actors
+
    writer: package group free, core group free
+    reader: package group free, core group free
+
+
[-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2025.1\lib\idea_rt.jar=61169, -Dfile.encoding=UTF-8, -XX:+UseBiasedLocking, -Xint]
+
OK194560690125
unified across all actors
+
    writer: package group free, core group free
+    reader: package group free, core group free
+
+
[-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2025.1\lib\idea_rt.jar=61169, -Dfile.encoding=UTF-8, -XX:-UseBiasedLocking, -XX:-TieredCompilation]
+
OK405590811228330
unified across all actors
+
    writer: package group free, core group free
+    reader: package group free, core group free
+
+
[-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2025.1\lib\idea_rt.jar=61169, -Dfile.encoding=UTF-8, -XX:-UseBiasedLocking, -XX:-TieredCompilation, -XX:+StressLCM, -XX:+StressGCM]
+
OK1307938125613323
unified across all actors
+
    writer: package group free, core group free
+    reader: package group free, core group free
+
+
[-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2025.1\lib\idea_rt.jar=61169, -Dfile.encoding=UTF-8, -XX:-UseBiasedLocking, -XX:TieredStopAtLevel=1]
+
OK24239428938703
unified across all actors
+
    writer: package group free, core group free
+    reader: package group free, core group free
+
+
[-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2025.1\lib\idea_rt.jar=61169, -Dfile.encoding=UTF-8, -XX:-UseBiasedLocking, -Xint]
+
OK212527694775
+

Messages

+

VM Output Streams

+

VM Error Streams

+ + diff --git a/results/org.itmo.VisitCASRaceTest.html b/results/org.itmo.VisitCASRaceTest.html new file mode 100644 index 0000000..f04f735 --- /dev/null +++ b/results/org.itmo.VisitCASRaceTest.html @@ -0,0 +1,208 @@ + + + +Java Concurrency Stress test report + + + +

org.itmo.VisitCASRaceTest

+

Description and references

+

null

+

Environment

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
java.specification.nameJava Platform API Specification
java.specification.vendorOracle Corporation
java.specification.version1.8
java.vendorTemurin
java.version1.8.0_462
java.vm.nameOpenJDK 64-Bit Server VM
java.vm.vendorTemurin
java.vm.version25.462-b08
os.archamd64
os.nameWindows 11
os.version10.0
+

Results

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Compilation ModeScheduling ClassJava OptionsStatusObserved States
0, 11, 0
AcceptableAcceptable
Второй поток пометил вершинуПервый поток пометил вершину
unified across all actors
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2025.1\lib\idea_rt.jar=49689, -Dfile.encoding=UTF-8, -XX:+UseBiasedLocking, -XX:-TieredCompilation]
+
OK2896803327749298
unified across all actors
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2025.1\lib\idea_rt.jar=49689, -Dfile.encoding=UTF-8, -XX:+UseBiasedLocking, -XX:-TieredCompilation, -XX:+StressLCM, -XX:+StressGCM]
+
OK128878180134504955
unified across all actors
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2025.1\lib\idea_rt.jar=49689, -Dfile.encoding=UTF-8, -XX:+UseBiasedLocking, -XX:TieredStopAtLevel=1]
+
OK1892906915659622
unified across all actors
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2025.1\lib\idea_rt.jar=49689, -Dfile.encoding=UTF-8, -XX:+UseBiasedLocking, -Xint]
+
OK24457932887218
unified across all actors
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2025.1\lib\idea_rt.jar=49689, -Dfile.encoding=UTF-8, -XX:-UseBiasedLocking, -XX:-TieredCompilation]
+
OK3098236030465851
unified across all actors
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2025.1\lib\idea_rt.jar=49689, -Dfile.encoding=UTF-8, -XX:-UseBiasedLocking, -XX:-TieredCompilation, -XX:+StressLCM, -XX:+StressGCM]
+
OK117894093119674002
unified across all actors
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2025.1\lib\idea_rt.jar=49689, -Dfile.encoding=UTF-8, -XX:-UseBiasedLocking, -XX:TieredStopAtLevel=1]
+
OK1811750115887510
unified across all actors
+
    actor1: package group free, core group free
+    actor2: package group free, core group free
+
+
[-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2025.1\lib\idea_rt.jar=49689, -Dfile.encoding=UTF-8, -XX:-UseBiasedLocking, -Xint]
+
OK23690822329049
+

Messages

+

VM Output Streams

+

VM Error Streams

+ + diff --git a/src/jcstress/java/org/itmo/BucketsPublicationViaQueueTest.java b/src/jcstress/java/org/itmo/BucketsPublicationViaQueueTest.java new file mode 100644 index 0000000..2143e1f --- /dev/null +++ b/src/jcstress/java/org/itmo/BucketsPublicationViaQueueTest.java @@ -0,0 +1,38 @@ +package org.itmo; + +import org.openjdk.jcstress.annotations.Actor; +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; + +import java.util.ArrayList; +import java.util.concurrent.LinkedBlockingQueue; + +@JCStressTest +@State +@Outcome(id = "1", expect = Expect.ACCEPTABLE, desc = "После получения маркера данные видны") +@Outcome(id = "-1", expect = Expect.ACCEPTABLE, desc = "Маркер не получен") +@Outcome(id = "0", expect = Expect.FORBIDDEN, desc = "Маркер получен, но данных не видно") +public class BucketsPublicationViaQueueTest { + + private final ArrayList[] buckets = new ArrayList[1]; + private final LinkedBlockingQueue q = new LinkedBlockingQueue<>(); + + @Actor + public void writer() { + buckets[0] = new ArrayList<>(); + q.offer(1); + } + + @Actor + public void reader(I_Result r) { + Integer m = q.poll(); + if (m == null) { + r.r1 = -1; + } else { + r.r1 = (buckets[0] != null) ? 1 : 0; + } + } +} diff --git a/src/jcstress/java/org/itmo/VisitCASRaceTest.java b/src/jcstress/java/org/itmo/VisitCASRaceTest.java new file mode 100644 index 0000000..1d3f2c9 --- /dev/null +++ b/src/jcstress/java/org/itmo/VisitCASRaceTest.java @@ -0,0 +1,41 @@ +package org.itmo; + +import org.openjdk.jcstress.annotations.Actor; +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.II_Result; + +import java.util.concurrent.atomic.AtomicIntegerArray; + +@JCStressTest +@State +@Outcome(id = "1, 0", expect = Expect.ACCEPTABLE, desc = "Первый поток пометил вершину") +@Outcome(id = "0, 1", expect = Expect.ACCEPTABLE, desc = "Второй поток пометил вершину") +@Outcome(id = "1, 1", expect = Expect.FORBIDDEN, desc = "Обе пометки прошли — гонка!") +@Outcome(id = "0, 0", expect = Expect.FORBIDDEN, desc = "Никто не пометил") +public class VisitCASRaceTest { + + private final AtomicIntegerArray dist = new AtomicIntegerArray(2); + private final int level = 0; + + public VisitCASRaceTest() { + dist.set(0, 0); + dist.set(1, -1); + } + + @Actor + public void actor1(II_Result r) { + int v = 1; + boolean won = (dist.get(v) == -1) && dist.compareAndSet(v, -1, level + 1); + r.r1 = won ? 1 : 0; + } + + @Actor + public void actor2(II_Result r) { + int v = 1; + boolean won = (dist.get(v) == -1) && dist.compareAndSet(v, -1, level + 1); + r.r2 = won ? 1 : 0; + } +} diff --git a/src/main/java/org/itmo/Graph.java b/src/main/java/org/itmo/Graph.java index 141a0b6..2085fac 100644 --- a/src/main/java/org/itmo/Graph.java +++ b/src/main/java/org/itmo/Graph.java @@ -1,50 +1,176 @@ package org.itmo; -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicIntegerArray; class Graph { private final int V; - private final ArrayList[] adjList; + private final ArrayList[] adj; Graph(int vertices) { this.V = vertices; - adjList = new ArrayList[vertices]; - for (int i = 0; i < vertices; ++i) { - adjList[i] = new ArrayList<>(); + this.adj = new ArrayList[vertices]; + for (int i = 0; i < vertices; i++) { + adj[i] = new ArrayList<>(); } } - void addEdge(int src, int dest) { - if (!adjList[src].contains(dest)) { - adjList[src].add(dest); + void addEdge(int u, int v) { + if (u < 0 || v < 0 || u >= V || v >= V) return; + adj[u].add(v); + adj[v].add(u); + } + + void bfs(int startVertex) { + if (startVertex < 0 || startVertex >= V) return; + boolean[] visited = new boolean[V]; + ArrayDeque q = new ArrayDeque<>(); + visited[startVertex] = true; + q.add(startVertex); + + while (!q.isEmpty()) { + int u = q.pollFirst(); + for (int v : adj[u]) { + if (!visited[v]) { + visited[v] = true; + q.addLast(v); + } + } } } - void parallelBFS(int startVertex) { + private static boolean markVisited(AtomicIntegerArray bits, int v) { + int idx = v >>> 5; + int mask = 1 << (v & 31); + int old; + do { + old = bits.get(idx); + if ((old & mask) != 0) return false; // уже посещена + } while (!bits.compareAndSet(idx, old, old | mask)); + return true; } - //Generated by ChatGPT - void bfs(int startVertex) { - boolean[] visited = new boolean[V]; + void parallelBFS(int startVertex) { + if (startVertex < 0 || startVertex >= V) return; - LinkedList queue = new LinkedList<>(); + final int n = V; - visited[startVertex] = true; - queue.add(startVertex); + final int maxThreads = Math.max( + 1, + Math.min( + Integer.getInteger("bfs.threads", + Math.min(Runtime.getRuntime().availableProcessors(), 32)), + 128 + ) + ); + + final AtomicIntegerArray visitedBits = new AtomicIntegerArray((n + 31) >>> 5); + final int[] dist = new int[n]; + Arrays.fill(dist, -1); + + markVisited(visitedBits, startVertex); + dist[startVertex] = 0; + + int[] frontier = new int[]{startVertex}; + int frontierSize = 1; + int level = 0; - while (!queue.isEmpty()) { - startVertex = queue.poll(); + final ExecutorService pool = Executors.newFixedThreadPool(maxThreads, r -> { + Thread t = new Thread(r); + t.setDaemon(true); + t.setName("bfs-worker-" + t.getId()); + return t; + }); - for (int n : adjList[startVertex]) { - if (!visited[n]) { - visited[n] = true; - queue.add(n); + try { + final int GRAIN = Math.max(256, Integer.getInteger("bfs.grain", 1024)); + + while (true) { + int tasks = Math.min(maxThreads, Math.max(1, (frontierSize + GRAIN - 1) / GRAIN)); + + if (tasks == 1) { + ArrayList nextList = new ArrayList<>(Math.min(frontierSize * 2, n)); + for (int i = 0; i < frontierSize; i++) { + int u = frontier[i]; + for (int v : adj[u]) { + if (markVisited(visitedBits, v)) { + dist[v] = level + 1; + nextList.add(v); + } + } + } + if (nextList.isEmpty()) break; + int[] next = new int[nextList.size()]; + for (int i = 0; i < next.length; i++) next[i] = nextList.get(i); + frontier = next; + frontierSize = next.length; + level++; + continue; + } + + final CountDownLatch latch = new CountDownLatch(tasks); + final int chunk = (frontierSize + tasks - 1) / tasks; + + final ArrayList[] buckets = new ArrayList[tasks]; + for (int t = 0; t < tasks; t++) { + buckets[t] = new ArrayList<>(Math.min(Math.max(16, chunk * 2), 1 << 20)); + } + + for (int t = 0; t < tasks; t++) { + final int ti = t; + final int from = ti * chunk; + final int to = Math.min(frontierSize, from + chunk); + if (from >= to) { latch.countDown(); continue; } + + int[] finalFrontier = frontier; + int finalLevel = level; + pool.execute(() -> { + try { + ArrayList out = buckets[ti]; + for (int i = from; i < to; i++) { + int u = finalFrontier[i]; + for (int v : adj[u]) { + if (markVisited(visitedBits, v)) { + dist[v] = finalLevel + 1; + out.add(v); + } + } + } + } finally { + latch.countDown(); + } + }); } + + try { + latch.await(); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + break; + } + + int nextSize = 0; + for (int t = 0; t < tasks; t++) nextSize += buckets[t].size(); + if (nextSize == 0) break; + + int[] next = new int[nextSize]; + int p = 0; + for (int t = 0; t < tasks; t++) { + ArrayList b = buckets[t]; + for (int v : b) next[p++] = v; + } + + frontier = next; + frontierSize = nextSize; + level++; } + } finally { + pool.shutdownNow(); } } - } diff --git a/tmp/plot_parallel_vs_cpu.png b/tmp/plot_parallel_vs_cpu.png new file mode 100644 index 0000000000000000000000000000000000000000..542958179126f897a694976fc0a97eae62f7bf11 GIT binary patch literal 43806 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
?-Ff*yYBmZ=+oo0(J5$_6W1Euh zDIQMUcZkEt>CieX=RGWAwZH$AO|t(h?J3+W*MeR-yyHamB-I{CY7}!0No>h2j&xZ1DWn!0>g$@1 z<73rz!_;s|G_LPK*MZrLuqN7XTI|j3KieQp2;bQVF}jYbrJ!`@^)O(Hh52UNvfh`L zxQCnGCa7+BGG&Y1Bh|`vkpcdTpFZB%J>MVWciYL!pqk;f-S7@<@pa@0g;(oW648%I z`zx*^iae6{lTZxG?+M+T@-{jcyAjW(z7y`67)p3vt-Z|oLNinp#&A$=(=r!Ka5i#4R>AWXd zA^LyK?pbeBgax54;z)+4=@r7Yan0Tg5uV;C`Xv;c zSu&#-M&aFt%z(6~2Hk09$<3#1Z#<#c;E^jfdu&wYj5XO=Z(nyz@>AsWy5(S}rX7CT zLdWB>aDBgN@;20=$pWT-0VhGMLd-#AXDCg1p{lo{7E?qm56I})keyj+NutR177Wz0 z^C{6P*~ey-Q&N@Ul_xE*al|1%bORE5)$IOGWHr9 z|GO>+SK;YE>`P2jQ>uP<@GB5ooWE~>mYf!Zk|f6G@=OL~t@mWF%KV|uds91=g+4~d zE{`TpjkoQisU27(vClZxu|93XlH(;%{x?{XK%IIE8{j>-4FGa-$~1DX)!7x%p?GE$ zm`$?Uhco2>;<-KWX2d1+LEs-hU&t^Y=KAA`WBkyBU>YB4iho=~kY#|@GbxYnNNe`C zeE>!%HKYbIyDmXNPfSOfwohJFkN(S9_ng7;GDCUb=sUh}aUwE9?!7$&`NAUc(u12o zUM|OY^g@CBkJY)dPKdS~+5uRl=I~EXaH%lIm%aX3IXy0*-g^EomuU?6>9SBfaUWS6 zU`cxJ5K9)nkkySOf-L8-P;dySgI66bpPaIrpB^+9$4(Tvd1jcA2BA2(JDJl4*)k_5 zGA$&WaNyj#e{pfN5N3Ko-W3BRQu%`S#1)M1_^;s)46Y0c_fFoz#lPcSa885KHwhc->=!K$h>Gbfn&E>ogeI3xtwC4jJ zjmIF^c`KL)akbw#$7ha~95|P|5(4k6zq$$%&6`%{hHA=z;wZrv zsHgUsVInS8d~R{btzu_V=Q32umVi6aez{#?D|>?~WtPIt)$`Y$zR~KRMeHY(kN>)E zuUa6XGx%>sf{MzC7b{R&doaWeD$LgCDkx`_w|q`Q&I8P=9W>str9v<*Qb9;xUmD$; z4m6Ii?ZCe<3UWx2z=9E;4yAYlBT$e4YeugoKsKm>xVTpDRpXbEQDot3%sI5_F|5w` zXvs>6Ldr2Jo|K-CV-K-CK&s6j3_HLA+gtbRh$X^B)+eysEw2s2#spCBhaB;0j;b-E zBq*dyjk$>IlxTARj+_?ki}eDVjevVadQ-D5pm=!(INiOnC+7~?+#P$yW8;6lXW6%9 z?p>da+1xtm>JqOk@vMb3Na+4Rg?VT19K}aLR8bu>9q;2gw;%qJ`<3@TgWwEib;gaS zZaJUGPWx@*;H@d(W)6PcL8?!%{OD9y8BGHDp%8-P4NIMBugeSPECs`cz zQF?KdTzX{fO9b{hoBY2fF2l&b*2YOKCFXx`Lp&o(XS)BZ;rbu59<8_PVcEZ!TK`Jw OuTgCs$yFrZ3;zKSY6tfK literal 0 HcmV?d00001 diff --git a/tmp/plot_serial_vs_parallel_vs_size.png b/tmp/plot_serial_vs_parallel_vs_size.png new file mode 100644 index 0000000000000000000000000000000000000000..9d8b01d078e9d80ca249c4df5503e14aebc62bc9 GIT binary patch literal 45799 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 Q9q}lQ4Y2yfdgpHb7eNUJt^fc4 literal 0 HcmV?d00001 diff --git a/tmp/results.txt b/tmp/results.txt index 027e7f9..3d4f3b7 100644 --- a/tmp/results.txt +++ b/tmp/results.txt @@ -1,6 +1,6 @@ Times for 10 vertices and 50 connections: Serial: 0 -Parallel: 0 +Parallel: 1 -------- Times for 100 vertices and 500 connections: Serial: 0 @@ -8,25 +8,29 @@ Parallel: 0 -------- Times for 1000 vertices and 5000 connections: Serial: 1 -Parallel: 0 +Parallel: 2 -------- Times for 10000 vertices and 50000 connections: -Serial: 3 -Parallel: 0 +Serial: 10 +Parallel: 13 -------- Times for 10000 vertices and 100000 connections: -Serial: 2 -Parallel: 0 +Serial: 4 +Parallel: 29 -------- Times for 50000 vertices and 1000000 connections: -Serial: 30 -Parallel: 0 +Serial: 37 +Parallel: 20 -------- Times for 100000 vertices and 1000000 connections: -Serial: 18 -Parallel: 0 +Serial: 34 +Parallel: 16 -------- Times for 1000000 vertices and 10000000 connections: -Serial: 307 -Parallel: 0 +Serial: 961 +Parallel: 232 +-------- +Times for 2000000 vertices and 10000000 connections: +Serial: 1241 +Parallel: 329 -------- From 0f1388c3ae7f5847a107c1e182edd8f4a82b0bf8 Mon Sep 17 00:00:00 2001 From: poma12390 <67729109+poma12390@users.noreply.github.com> Date: Tue, 14 Oct 2025 03:06:52 +0300 Subject: [PATCH 4/4] Add script runner --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 0eb4312..072d291 100644 --- a/README.md +++ b/README.md @@ -13,3 +13,12 @@ \ **Загрузить графики в отдельную директорию в репозитории** \ **Для построения графиков можно воспользоваться чем угодно** + +Пример запуска скрипта для графиков +```bash +python .\bench_bfs.py ` + --project "" ` + --test org.itmo.BFSTest ` + --cpu 1,2,4,6,8 ` + --plot +```