From 73f5f074a4e6526f27abd20d120ef1c413c0cd0b Mon Sep 17 00:00:00 2001 From: Artemiy Romanov Date: Wed, 3 Dec 2025 19:27:01 +0300 Subject: [PATCH 1/3] IT WORKS! --- src/main/java/org/itmo/Graph.java | 132 +++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/itmo/Graph.java b/src/main/java/org/itmo/Graph.java index 141a0b6..e970996 100644 --- a/src/main/java/org/itmo/Graph.java +++ b/src/main/java/org/itmo/Graph.java @@ -3,18 +3,92 @@ import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; class Graph { private final int V; private final ArrayList[] adjList; + AtomicBoolean[] visited; + + private final ConcurrentLinkedQueue> globalQueue; + private final ConcurrentLinkedQueue> workerQueues; + private final ExecutorService executor; + private final int cpus; + private volatile CountDownLatch latch; + private final Lock lock = new ReentrantLock(true); + private final Condition queueReady = this.lock.newCondition(); + // private final Condition workersDone = lock.newCondition(); + private final AtomicBoolean isFinished = new AtomicBoolean(false); Graph(int vertices) { this.V = vertices; + this.visited = new AtomicBoolean[V]; adjList = new ArrayList[vertices]; + for (int i = 0; i < V; i++) { + visited[i] = new AtomicBoolean(false); + } for (int i = 0; i < vertices; ++i) { adjList[i] = new ArrayList<>(); } + + // this.cpus = Runtime.getRuntime().availableProcessors(); + this.cpus = 6; + this.executor = new ThreadPoolExecutor( + cpus, cpus, 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue<>(), + new ThreadPoolExecutor.CallerRunsPolicy() + ); + this.globalQueue = new ConcurrentLinkedQueue<>(); + this.workerQueues = new ConcurrentLinkedQueue<>(); + // this.levelSemaphore = new Semaphore(cpus, true); + this.latch = new CountDownLatch(cpus); + } + + class BFSRunnable implements Runnable { + private final int workerId; + private final Graph graph; + + public BFSRunnable(Graph graph, int workerId) { + this.graph = graph; + this.workerId = workerId; + } + + @Override + public void run() { + graph.latch.countDown(); + // while for each level of graph + while (!graph.isFinished.get()) { + List vertices = null; + try { + graph.lock.lock(); + graph.queueReady.await(); + vertices = graph.globalQueue.poll(); + } catch (InterruptedException e) { + System.out.println("Thread " + this.workerId + " is interrupted"); + break; + } finally { + graph.lock.unlock(); + } + + List newVertices = new ArrayList<>(); + while (vertices != null) { + for (Integer vertice : vertices) { + for (int n : graph.adjList[vertice]) { + if (!visited[n].getAndSet(true)) { + newVertices.add(n); + } + } + } + if (!newVertices.isEmpty()) { + graph.workerQueues.add(newVertices); + } + vertices = graph.globalQueue.poll(); + } + graph.latch.countDown(); + } + } } void addEdge(int src, int dest) { @@ -24,6 +98,62 @@ void addEdge(int src, int dest) { } void parallelBFS(int startVertex) { + try { + lock.lock(); + for (int i = 0; i < this.cpus; i++) { + executor.execute(new BFSRunnable(this, i)); + } + visited[startVertex].set(true); + List initial = new ArrayList<>(); + for (int v : adjList[startVertex]) { + visited[v].getAndSet(true); + initial.add(v); + } + this.globalQueue.add(initial); + } finally { + lock.unlock(); + } + // wait for workers to start + try { + this.latch.await(); + } catch (InterruptedException e) { + System.out.println("NOT SYNCED"); + } finally { + this.latch = new CountDownLatch(this.cpus); + } + + while (!globalQueue.isEmpty()) { + lock.lock(); + try { + queueReady.signalAll(); + System.out.println("Global queue before latch: " + globalQueue.size()); + } finally { + lock.unlock(); + } + + try { + latch.await(); + lock.lock(); + globalQueue.addAll(workerQueues); + workerQueues.clear(); + System.out.println("Global queue after latch: " + globalQueue.size()); + latch = new CountDownLatch(cpus); + } catch (InterruptedException e) { + System.out.println("MAIN GOES WRONG!!!"); + } finally { + lock.unlock(); + } + } + isFinished.set(true); + + lock.lock(); + try { + queueReady.signalAll(); + } finally { + lock.unlock(); + } + + executor.shutdownNow(); } //Generated by ChatGPT From 41acea62ae9ea5ee14e796c6ddc6a968b8665251 Mon Sep 17 00:00:00 2001 From: Artemiy Romanov Date: Sun, 14 Dec 2025 13:17:18 +0300 Subject: [PATCH 2/3] Add stats and batching --- images/stats.PNG | Bin 0 -> 42406 bytes src/main/java/org/itmo/Graph.java | 6 ++++++ 2 files changed, 6 insertions(+) create mode 100644 images/stats.PNG diff --git a/images/stats.PNG b/images/stats.PNG new file mode 100644 index 0000000000000000000000000000000000000000..de354c26733444f3a5180faf3cfbc3aaffb7d680 GIT binary patch literal 42406 zcmeFa3tWC{Y9!ELqdWOi2bKzqzwni47=K%lL*o=RnA zX_iXMQy$4k@r1Os$;^^@08#`hG86Warf7!yq;?;F)S8uhjc>aWi#WTBJdI9{V?xjmU;K!_lt$v?a z)O6Ymga14i^|AlQ78bSSe@uP$Jox|Y18aj5EG*uB5B{FDZtJ4^78WJm>sEifJtcfZ zfXH0hhlA91Uwr*8D&h5a{J(wo__^ezU*x3cBny&;U)mf}?07B=_e_5oHe8HY_0Bn$ z%Mrd7N7<-x@cCuW&nZ~Gr~ z15URmtEcw9{O z)e8>y`5MN2Nu>PQZY}4%l(H$R>?00#E18E)C?OftB!iBJBI#NwBrRV=G?bAvWlAl? zM>BP!$Jj*Tfrj$d^bB=f|J!PJ3-!?Kh=RG5_;sR) zw%L1cy`?&g342i^?9V4TYg3vzWVk-NHynLu$0sizc>5m0?dL&Vm6CWa}}+&XxO2v-yN`#gD6wP z=n|Spv#94t9rT(bO-{J2mx*?UH?QL>l`9y&O#$xThADNB?$zE_VdmZ zOT6b=q}lnV=`^Q~?rHJSo!eo*OLcX1wS7p^6)$65! z>h_a9t8&i8qACeM6;}|_gcEwp`|j&@s6W*CZ@k6n1-km!V7cT})25o!&&k==kgdc` zKlw6;f{q^8Ysd|@074e6ZR_Z1&+9vqi^~LNN?vQ#UTyGOrk<*{YWL$mV_~5!KPtl+ zs7L$W(z6N*Qw$?kLW_eQ8yAU7I7ce=_qQ^Eizpl7YxQ}$^{8iLHw7p(J5`+40N%{#@U1x5O1yM*Xxn(GmI-zyc7 z(S%|8i*3B*=Hvjup>FuH_OE3M^-(khRtRhlBv(jkn!p)h9Uu6mr5 zw@4#d`vIiUOmanuLzz*`u0B%cI~nNMZFm`B9y=qPy(PM@m=qI^LizH2))(wq-to9kEVDWuMEC@Xfn@f)uSSt%QxoY^~8H{w};YFC^MB`@61E3Q8r?SX!Tns*+4cdQ(yCIPEZvlpH#Je7|uJ@Pwrdr+RteoyVR&qu-FD02iS-3B*j8EHWEEUXgoi8gVb zar%o;MPJhaXYlBvc@hRRvzF?Wo={Sj@Pj+ zQmA5XEN^T$zan-Ao1yC*nYsY+VsL3JIp?N*K?psO%eF6JlNg)wg{4}X1SNj$ozAc3 z^AoExH9^sN`d~Gc8xoN-kU)u7cPAokGO*>boH2;%MH{)GZil{Q4K>B;go!Gz-A1#4 z&PFkU2iE&esLq}_jxXx941!+R?klt2qElZG-qlRv2vMPNQ&)QV>+N4jWQeWzRd3*l z_#+-d4PDsaw~tWGs&PHDEJRy`9?4AFq7BzpcGwW+?qE>rUh`wV**MA(Cw5ud2zs^* zw5B5(8xo3!SKe~9<99Wjyu82sHO-{7lv||rC3-F;@29c2@(o>0q;Kx_&Y#Co*i%j9G1bB)%3-IKULyCn0$Rj{V(q^O?cMmU z(^6rVFf4PtmRl)_iA=H|5$%!1(A>O5_KhzNk2Nuf0~uvVQOEGOjLBa{kR{p8TP5(# z-Qr6ew{i087)o_(qC4AeC~Koqs4kwBEEz3S(vM1}igy?gQaL9ELd0F~VuVqfiB&aU zEMK=x(dc)w$R(aIFs2v83D|ar62m>gZCsi$jcUD+-Hhd8i`AJS*E>rxo993YUiS!2 zvZ(p={p8OGYdCT4aW+y)nQ>cg4dyLEa@mska0T)VnT88JK1?#)Z6%T zmAOqQ#5m3;ZX~M0(pKaWMbx&COU5IU;u>qY3FX>h#Rqk0F+uwID{X|r46H1c%amTf zR7BLJ2)Gzk!m0kKD4VMxiXB&^r`NV^*nnOWrLvA@mh%c$ZsC?bocKMM53LA@z=(71@~7 zg6-BU#IP<=awIb~(gtN4C~s=3L8kOJ3?KQasBo{gTfCJO#_F@*8*|o+JG^S|uH^o* zzShgadks~YA*8iv_q_x}hW$nRzP(AfVLWxCY^k5%JzT8AzJjJ3O@%m;wn-6D6)_*G?Tt|( z!+5I&3%lo>TK)pVexH4eH%*r;30f(wEwo3(TS_HuglcT>>4rf?s%5O^%-t@R5ec@h zFG(OH+bk;*Bb(^dK9|o?ZzUHl8qQzhB|JroSkC9=a8ucn95&}Pmx;9;g19$TQKi== z^gG#{x#`+1`~cp;^8I0-p2me?Lkau6?p0IeNXs_DGf8c$UBhPQ<7QASy+w4aCHeR-E_}SI#I;2M~ zUEc4Tta|U>etQN*Jh_D>v|oxlE1npyZ;Q+>D(r6kJYcv1+Y*+mdsjfPsA91Q>$T@` zc=09Ow@V1O?rzdPHRTg>Ta;Grdi-Z;65K?iJng-1|NmKU;S$O3k zf>S16W*3tR4IwVrCyTo~3MRiC=w8`#`S{%|m)@~pYHeSVb~L0jqbM@*I%gr_M&`$k zWirvIPu{wMFl+(4n81;9f*Q0js1C7~zcJaxnjNBiqgrI$DNI%p3~_WtR6jYdDDrX{ z2Co*1Htdq*v1`_mlLgrYUaSG6j941c70F`1iun4}Xv%ts$0mn$7GuZ7SYm^$RE6Z6 zzToE-qigZzo|kRbOiZ+LwOBU(-#xsY)gBpL^P1T91j^Q^w&laM)^zONzAenwoE@AH z^g@AS%!qVUT1-7kV_A+I1Qh0S)369H_SIYo)vUU;Oh)B#UByRk^;z%n4Mgu1AISs$ zEaP}|yV<|o-6YU#r#8FBcSz@;bf^cX?EK>Io!*WksCOBfT!t*?oTAxZ>Itg9?5s=C zoZlkNAJSp$qkHOm#QRX&(df{6`vA!r>1bALllVd=?)#1Gatu?0;feDI^P$%3Tea?d z;ZpIO?{`W*B6M~0xVrN-)ihjVZ-KR>TT5Uw9%Ly_BxWwAZwiZRVOIz}bpPU`R>w{L ziwkULw2{TO;diC-JIInXyK3y2YP()CnHAWf3KF^oXLVjpTE2#y`PnXFy^z?_N!}Gz z*7+^o(HCdGM4Hvw?V`d4$wm?c8U9z!pRY@9%_L4V7F3+ zLzG3>KtY_83S!!d_CBkUefb5K19TJn!=O+`X+7UgUIlq|2Ms6fD!^lzHLNyFJk=f= z?G2)2)nk_k=;YRby8bu{T`Xg#hfyfBNZCq%ImO!#(8?;QxICta8o_8=AC?QH*mmUU zUP!tMJ141Ot|-0JbF8$FI!~0go{_~pyP5F*&mPUH+e;ZAkGu39dBtP#cIxn8=6Q56 zBUDa~3&VbZ`tiji_w<%gAZPWy_K2l@GZ|`h` z-lsd4R;!JxgD7iKT|7p z^Brk8O0+HtYHf&&*6CXKb8HXcIg>%G0a^Lj0z%$g$W=^q_vjqF?g_=T;Y&g!eTsh~ zEUoCBLe_j*o*fDyL}vD@L$;$B&PBulc|=M5uxqnrXPW~Q1PG&AcnF8b1q^9FT9)mQ zg(g_W`ssYVzSh~fAU*hTzJ*)))*_KWwspHa5RnvsQp}BJYU&`-uutAFp*t3ME!_`U z^qywEy6;>kw2K;tPO3QtoVJ38K%)2+tZiy~D=8O0PUH5m8@JElWO?mcQ^c2z)pJ*h z70Sp^NguoBXseJ=kB;jO$mIa7yO3Gk5uSzO3Y1vbQz7f8;%dTq>$JUOcDXC6O4)61}M=f7lLbXpw3?t(R;z{BXk4yk5Zi;PnuMuLY&7I`Yv9dVr`{Me}rQYKl zGVfAFcpzE5vX50p@zbpb9y~kb% z*1EPXmYp5nqRLR^3`(CZil?rd2Z}fNEpU+w{{~t8=wmq zRDW0eGDb~jF0RFuxO-!Vsx|+p6aJo!A|3ULLa=upxyTVGJ@gsMnNbz~Y)PRq;ls$0 zJ*Dc%`i-RBw(M=Thx~?f*`peN4J4jhS2Pxxbba_{8&=pI7JpBZDDz3M`H|t2aU)Cf z<<<_)Xr^@Z7@y^aQGbVY9&jlY`{MTxW1*W%u_NNu*AU8Y(QX3iI-H$ZjeHO8wfJmDRe24j{flQKqQFI$zL!xjsVf z8n?tYL}0HrFiky0faQFI)r->Px zw)3npq>sxZ$-Y?mgPo+8TR5ccjwm^1WaReogkSy~C8ZE7La$m#9NBV}87K?{4 zHHxSK9b?D~Jvnk_NET(aP2>BrhpjcDEvuQ>(KR=R=nwTLQe>kTrnV778Hkc)ZQ4xt z^NwK%m+!=dR@YEk1BT|F6gm@hMZhz)*Qy6<(^c;5rhsxU=cepq!~icEiD56U&&-jJ zZ4_yZsLbPHa{48jMs{7R;<6TL--eyl3<^%p)uOo{&@4af%=5TGr1f}I6UVwNPgms5 zQ%i)lXSPg^8%`%3Q7M%|ue$Ce87~+W6e@#q#4)`S2yp;JuNC%XoUQ%Cmb;PB^!K z#@MLCD_@jwwXPwhypS!!qj=8BZL;~S1;eprvR$m;f_Y`(JExV}bmV>dCI;)e{>23z zHG~2I&R33YbS8tO%O1_JltRM}PFu-j;h}Evr=lV}MPY(l*ROH;;+3udZWV3k8YJYL z;noj8j8)CW<+s^&r@D^i)r_e%={s@zRS9Pb#fqDmZDU;g>Sl<6Qd*ku)hz>?z_wpj zgcu&TYh>nzk8=U8X40)`TtueCPq`{gxy~!6$Ym*%R#KCjq&yt!?13jGvL-)|s^+;U z0yhYT#Z5Xt;i?nJuY)O3`714B@}-ke!ZI5k2#~U|gaK~Xr8s*nBz9?J;YqSu;fuPe zUh=T}tdVp8pe?PVWc1u3&F;G46Em0CqTZK8%;$*ZP0mo?K*qCg7V*OoT(%4`32@ifR}pv?E2)_+ zpoWN6olv-it*R>+CH*^D6@-)`Pc`6&_g95bqKqCnsA|x{G>HWTY3D-yTXnwwE>3vk z=BuE@l?r`#-uK^-^+Dpz3x*{0e5fhBbSwHD-Dg$8Z#1vQr}gkG-62tRcn|uMQ==K5 zkG~MimwV_(4}HwUlzOZPQ%Tw&}Gm^%X*!5}}M?Ir$35cQ83iay&kEb>fvauHtJ9dV(-rLe%UJ*o-D=(gH&7X`#^kX~wH>_Yn@!)5)qJqznH z=P#j$$|A9NT0#ZZUhE>h*`SCKKn<05&hw}g`!?~&sI_-_ zta@eOJQjm1kX4bOrXF#kM7FS?E}S?(T_LM!E28wgmbg@vat3diS1y*y(+OOViO?eU z9pkj^0ql<#h3R zzMSZ#oD|!DqT{jboO#`&%ve9 zpp(K}oZtekTbxi%*r%Bl=R@6LESQ8dz3p_jP<$%1T@{MI2is3MUfog{BgXCkIr3U{ zWX|Xz+^~E{=1^-{Z%Ub>AlxbAGy4!}O=l_tm4Q)T!#AJps$JLZB|B4KyDGA!p5KM- zN0q9Mhwcg-<~0y{G2Tsa1N>aORq~=9zCYU=>JLYI6&6YSXrpoa3e@?iCPp8g*-V$= z|3!IL5P+uYW7Wcib_As}y@lk9bC&6Tma8Ik6Q1ih>}G;UmRNfo07`$3QwSeHV-Q2} zLr|~R8k~=KQl#c#m1IUn;kJMf3F*U-j7?j9TuC7geR< zvTk0W6oT$?(7P3@E)w786%&>+(nCQxf$p!>A(Q3YrUBi*N?GsAQRK0dR+UR~GL(?ak$moDsg%c+D&IYI_wxex zdIBL)DoJdmH=%YqGV~fckt^?YQHyDrxMuoDQM09VjJ`$?Z@IN@Bl$=vH(MBi3nAF; zzT{{Wa$2u<_6VKng3%zaI(cIC`00|`Y64Xf!{|g1hHsW609ULl zq)F@QuJ51Hr1VT8rG#n#Yrt-FDJ8vziEkr9!kP@VRXb1`jYio@Q9Y<0FB#Wy@rRS# ztXW723!hpUAtwyQ_6Bhx80nn;Fj!;5@Bt{zKBXeW0IO4ii+|rCK&XqhtpSY!r#?_vwIjX3+ zqk1kT7JYZTGP69>E#vA&b)T%FwnA>75l}gZ?|V?FF5jx%p&NE}7h+$jIa>s1Y7&&D z^PbO!)>CM4E!sNGzzCv>k`Si8*(5n=3(RVu-1qg-uV-1zQ(t3OHG(lO5u+xXc|5a(KEzz|(ydpmmfw8ds$F{r z`TVV5u#>7-u05m$yGjE~W{oJW8?xWu{k+a_J>%$I-2uuo_m}?Hc1O+oZRTCrkA6TK z_jf0jw}O37ZGf*%rFCXbJzy;)Y4{@jI09TZkz$$*}HZQ zI+i_YN=FwFwc@w%72-;96)544g565pD7@{Bv@`DhUUA%#UE+?Jg10pd?)$vJ?qhPP zRh!qoaPd}hhSha=n7QU*KJq^|j70hRI`Y(GR9Na-9wCUxbRkUj#O#uV77^*G@Z0HRl~R z$mrk5JhH)7^g;I5#*OM*|I(G&NKxQ^x7>^y+PADGcqAQ9X>}ALb)uw(!zhE($cUke zNjwC>Te>_N}}>#`ZPvVxp`HHR{+XYNhD= zYOEB=)A!bTlGC?TVr4FYdqGWy!XQIvjrWhxL>_M?BS4q@4GWV8ZKc{bS2c($utPC> z%f$*TS5qKlsSFnPxtTIgnY&Vy(;&^UP2-KTgTqSiIINes5d5oo<>Db;FOEg1ahZ#7UE?(?Z!5cbU9y08 zj8At}^enR~U~IIHC>f6$iS()O7hz7+pAQ?}qi0yP*P%8sxwbNdt$i%j@yrsVw$hdw zcl4286n-?a?z=M|%8vGH0v&I)%^o;YT)D1s6jQL=#_{VI@3^g(9Hr5ppnGM~cBDF_ zLKkwiiCJ{!+=!$N+ly3#Qoj19xe$hPsqRMMhc&$6yVcrPrNmZpGxxTN2oa0hf8HYB zz-ZmZ@6u5vSUy8p0;)Egde!K8mOGNCvcce*hl6l^n5}AIW)xqRQ0W$D1(c~g4r}*d zz(>DcfjsPOnPm)-l@X%6w9j0;+3l( zFl@`@*dvG+P9<&xgQwV=MD)zQfB8dq2Rz%o6FOGM1LIyjJfSH(P<6DW+Y0A3+@E~| zvhFU?H@j|{C}D-5E6*!zi^6Nv9bHEss6sBef5B(I<-O^f@jVI4_j|P4jX75PB81&Zg7N5oG7Q^~=y%5N@&LmNUo<)fwzB46F_dn&Vie|%!nR2`~LAO!_0o9aNiJdy2Qh-)cfAI0dJ zIzzl`BvKdoIrX<%+2Gy?(9m*F5&?Hm+_Gu_I|k>ah7qQt>$bM`uJcSmc{$+%wgO|o z{d0@sel2~CmVOey^BO}kFBh2{F-#h*%}n6#bVOiUenx6T+p0bkO6~6A=zXX@A&_- zg6QwRr~XW+Y#n1)QhunlBZZv1CnCU8+6qzfevXwb5?5P& zq0Zbw{tm&+3KfTtci^*w{=p7)p%E`!vOC5w&5QJ=4r~T z6VG>6mpQHg*)>Tg7ZW$C10DVGcc7|pQFTOb_AT+wqzdQPi|#p?o-)943eq~Zt!TSMyoS-gy)c+^f2>vj$M=ABc~Lj`-P z^)J+{&&I6N$ZrN)zIMk!1}ml>))9bTuvoS>ojq?hkh;aL~dv=a{Y_)DqzuPcsn zF=^0T4Qh~>om9#zB7Ofc6tpujy?Ktutb(TPgtSxmVo1ct*awhBDTm-3aLA9)$V?Km(1GnPIO-3&s9T*BYjsm z^;i+#(k;6Mwi#Hg_FzGj$9G|T_~jiisiA~AA+a?_x$f?_XqcewNC29P_{Z@AB9{9+Djgp##$K#|9!Q??dX4ErmA^6vyW>u>lv*M{kZc7 z@-J4-{^^V-CsN9k)ndM^aXcL3y9Ur9x?e&6CVA8{KDCl?fz`Hd_`y$ePuV#Z999g1 z>LMbLn!pSmU}r>x;821Dx44bc6hX>m#iiVGl1!qn7U7oKimLc-xU>5P(DIZOrSi|u z0`<)x9O5=FyLbYh{s#Ev0b8?99oCUu)_`A_WADUsrxzjG=ED77JhQp)KB1Z$@f`R? z=n<1Yp3_qrUDkQA9=Zzr)xzQlon^h2C?+v-rvL2qQS1Ndoo4W2p3oatUgp2ZFb;ad z3=?89)1c}JAo<+UX=GFpDsbL#!oIMmaB+*I$=pA;J1QV=ZOv?+TQ*e$s2i2n%arD# zh?DvtMrnr3du+Z00XM7}znbwW3xXYY$8=*?jP7FVrpDNYy7UT)48vi*JCNP{=zWs| zbk^;(qjw8WE)%bgHw33^0y)pcA;LQfQ!~a2W#$gRgMs%yvugKx*L%|w+hgE?$5T0f3{nRhsD<)Z@7F1Koj&bE8)3o&rnP>T21nZhZK$cf0E7U!+E5I$K0 z+21=M7JJ8AwU;<1c#F|5xCB+cF+CK$~%wea_(!6ZGD(0?bQ3=!bv; zLPDzzHa|}Af13WKHr5@;;n;cN!s#Z-`#vH5GcA>-IApx||AID2c%Dx%-oLi7^MAcx zKL~{K@4;z=IM0_8p_xywaWlGy*=#P-$~G?I9hU8XP-oY3R7?RaqS_d!7P$AIHUf5c zaTdKjDopf<&)pPU1s*voB)cZcAzW5hx6%K7x~7p^qVYJ4k5^xh$ybNMv=IIpQIwMw zP706S)zjueR4I>hSn zaPc>8{sVAxS)oi7vp(QnQk&>?CqF92s(oU&W~QusDJZQ-5S^XOAQlbLyDK_`YSc{XV$(@c*B2gnfV6r z{?+LNR&9%?F94aT!@yw-oGpW|i%UQaVz$R;`G9-CUn8KCdiVGLufILTR$=#zQ6g7f zGs>%Y^UDW$w-vKYQiR)YfRJ7;vG~g_ymf?%V!CF%@?6~3_n*HaJD@)JrcobBS3t$Y z>Nme!?fT(uhp)C;w7iyVxz=bE#)9_W7s5hIy7F7`-1@f`nHPWRF{I}~AXBfAsU_YD zEE@-Nj<(i;AJ05<3)_JI$mAq`1M2pZl|GRR8XZETvZGcdCt~)uD!QhFEyDxGHOO}08^+s}SDSQRKP4Mj2fd|u& z`tLRZWh178{b1=7d}+p$XSp@IR*Z(YclRU0v+D+fjUnjf+2){a51Fx9PnLOW!8rwr z!S!7eg~D@Va1R1W%@e`0HW}uztGf?)-P>sYh9*_<{^6tjofCZK;5;MH2J=}lkAF|E zXs!O0Xx9l4Tu4*T`Lu;qExvhH=JUKZfnmbW13!SpHC}^>zhLizMibk*!T^fLa|FDhhhpgM7viGGPC%%Y+M;yQB74V%tRB3_@lNv4wDD@VF?N1o$Wvliphk-~g zdhk+T9+%((jLvP6%3Cm0110Q6*NnY6!iEY>2=#`V;5zsLDE?RhU4ADFl`OtVks;vY zJQfERDztm9?Jz>v6Q=xO)+-wufaT&73d(kqYSbp!F&Qt&n@%5i!ZN;xeawmb=Ex0f z;g`Bb;Wl_Y3(q^P0i~f|!SML^0{_ANl#gxU8^4i z$-iNgWp6mq1x}ZZ=SqypsT;}5m9k|~-V<F+oSpez5`-01v0) ze>7=hjPE9D$K_-{eYlCzkfv0nq*V=$$)+M^1R4&fPg0`UfWnV}BtF#4a)=98me0O- z=3@11$reO7>7U|mWVFP@(u{ht7~fb->^k(Dk;^B9*ZMtO$WTv#};JGntP8KF>&( z`Fu+MbUa;#_;Fdl__0TR9F_TiU%u4m0fOzF9LK{W^FZ~>SbDJ6Shp9QX{nw)Soo7b z=W(L$qf2W51ppUO++a`3#T1kc)&Eq8VU#rtwue9R0}1{H*EO_lAi#mT#y1EtDD=fm z1{V%qbvPjqt*u$tPa_qbW@e=?`3>Y4D*$kwZn7>@7&lf0<4;*?N%eu*?a}!ySZ3V- zb8)C4$1Fa$=<)R8gE{jz9MMR%XfwBc5Eqw!xtaobW{ak!%^W?*%EYFpDN4rWe|fQqr2U{o($cd#&_y0P%sc7b6+F9>pyo0orJ31) zQ?LZm+AW}*{1C({?iI{Hr?J#K2<&HO$upj0A;XC5O>>`SoM4`*Ga&)M0pgucLFr{i z%%+>b)t@W40rinL2Z15akWKFGIN?l8y$BbMw}8CCIMbP0ma*b=(N3*<_tQrFN5Ak) zY{TEn{okQoBTfY!flV6t7;GHQuW?)7!P%U{Piv8}5ehZM?+d``+L*oDKH=D*`GhW*L zPW*U{muiF)TcCu8HEN_8)5K$1J7ztA4R3HMoL{EQ2IOvwk>CMKfQtawhE8J$kR4!@ z!6XevcO!Q({Sp7sBcs7PVAFi=DWk%}E;&QyrbjbYcBiQpoUn#}`KL@5?j?962Ek@H zZ9On69Q`L?l;=&XQfRDG$PN@dve3uMYQ|9>7Au?qr{~@Rh08(k4Zja&njrl77{lN6 zLZ>zJu&f?0)~5^3kCoLUVP#sZkLL?d=NykW!O8na?}GCnay2*^GKx3u%NL5ym6>4wWFt%gdgc4GqpE83OLSzWW~o~d)OZT?@WRM4>W z0G#odBK)(_F%}CN5%$YcA8x0tg=^x!OP~IXhCro#Ap4Sgst;(lWWopIDp(}&#KLXH z9edzfe+IaJ-}>Rrq#DtLe0Cpr)}Lcu&+0f`>3vgkSk={E)6)L{R*aiQ&&B&MqA$-1 z{nbXyV62HN;cNWHj~h!C$S62d%LOHpq4=l=OO?p10n&<39QXCC zet@6i-iKS+cD*xs^S?KbCoIc5I||DP?@C9;RvwlR?~Yb=-tEqAv{loOlEcLgCpz5z`Y}RXv!)8cp4aBTSW3p7vIn4Z z_~3u$%pjgT%-tHV?F2nWUtAY0|62SXg`i&tt{UTpT;^XqS#v)>A9nrU%^Ih}=BqG8 z_4+ME{f%whxBe3}rs_L5Ni{}kQ<6G89Ej2nr^0`ZD+C>aV?O9ndgyL5Z0r%2d0Ybj z#OU|}%}JfxoT}JiZF@q;TVI zWTWs(A7!JzvDrUG6=RH)4~7>Lx1FYZzroU{DwfR5?G~I0!F7;dr9!`U+&{&;|2Ej& ze;e%I2KzU{e)l)Ra{ory|DP!V+|m{3aH1CRv?=h@s|;-UK7B3aZ(n$N!Ty;l-`{NG zZ?^IL|4O!DY^8oM*rD{*Pl!oyPxT}?p{WC>vPr4_%iPS()NJRHsmsVu4SkIx0U^D`a`?eNtN?U&z5DH| zhYyVY7e<@}p9ceM`|7B-&K+^!c5Vrz8_p_sk7d;5E2(x~^%D%nD_G z<+G`Oe6_;Vs7}r>P6I^dq4>KAEU+8V0kY@B5bzq*JUYM@o_UUso0ky2bS0=an9H(H zD8;UKhSwDfmu11F#Zz3I;NB!&N zG}DiE`>)56dTqv@E8q;_UtE~{n=G692L8-0?o)%p{|%+N2))`MA+0R%1Et|V-}vxH zsU8{b;U$Cm@SkrP`Xe~B6N4sxJ5YTGJO6)jm-~+HPt9`7fB^?gfp9Jm3bOzuYZPuT|UvPt56x}0wxAG5967EZyN731TTB=1Jg=oDc_nuLO=r1{h?KuS8D8{0v9Xd-!r$& zD%Hop$z5^Gb~o6TUcX+T=!b;ah;_Z!ylB z6>M5bOW@}h)svv;46pTA{FA~hQva%+G(|Cxd*E;hpAUPYXh`#xnytiiiLv_AJ+kgmn{G;S&a$10O|MZfmo1X2A#gMs zbpF6?4@UHOXr8~n{G2<;nhGN39!O&!BrFmmzQUq4 zIXUb$({q4_m{txD5G*b;JYQ^s;RhB1?0{y$nC^=X{#6-UBE?Mb28myDyyc_<$wsRo2 z_08LH1By7vY?5z*f z(mn-%2yXb0?tc|ZO_G@=`h!|;53BZ|ugs+qxLi_y2YI*brDXA@EwE5c;)ng35A^er z2^ij=nU^uhm=hASt<~QF5dFPL$!1-HAD7+&Z#DI}z-uupdOs-QEdWD+4kEMfzytm& z-kIENI_r6$D>!>}PulY2Z;g&H?GXEaB>WWc#xFC5?*s073GS|(8TQHE5xE4wJv@_N zW(?mU6|l-8A1impnyM# z`#s}h5%U_|Ito%>wUapY8r!YmmTT}0bZwcm`1@bX#SA<3fGy3~>I~cfCz@WQc?SD` z1XzD~1_sP%5D7o!<0%aYjFkKaa8NTyn}3+7PQ4gBD8j7lUz8YsN*P-P9-^Av+z7&9IP-<5I-5Km{59m0nCOYkvU{BNuPJ3T4WN6z4jV->Ri%+Gb320|3K%`WMvcmj?>Ou#{+Ysrvr#Fh~N`YQ=un; zcbKLLhZkdX_(kftfXRP64*1e`0{(6q|5uUa8a_e!57>-=!HqqH3}EK49*a|$e zOGfne)CC_)+S`c#KD$vB<#%<)VHT)l=a=d5WoZ`O0e^GAXeR;8H zft_LFk9mWgE#?PJTZG>L&tvw(xi;vH56}aTi|~m9TL_wjH^u0M=0`wVD8NCF2XwTk z)vyA5*oX1!Rw`VuH~;5Kf=kvb=GUi<&u}(<)(HHo1;0F-`3a912OE~=_a6M!bByBk2&xTF*$-y7bfQMQP<2#!mh@AwD zCvR6?g@|d#@j0nE#_L);!Y0F%*J4S}fyb}=a1izvsZ*PY%6fdGOWMJyN`dHBrE-^_ z7fJeTBtq19$HuTRx+=yddZeI8BIqk)cVo>Zf{HYqxG^HnAbZo5RYzw=cXLjj$PR6!;EH# zV+LeN3G5$65FI`pUWTy=EH-QFwPi;SjLc0c!BaCgxmy&&~7 z?4|qsH>eS(T9uOr32fK)YH^~np3=zntC{*pb%C6Ah>6X&>q}CLFp`fEHQH^GNSr*F zZ9`qsOXTT!7*9Vo1;CQD?+H85ENy=J5C+P6vn91q@7T0lx;{V7ccX>psUg` zenfP5s?&Rl_zL!t8l@&!U8ek$ER;~(!vlx#rNp+aGXq5BR`Q1QDuRrwF2%cKwOsVt zV#mPjwyjhN(9!gP9~8k3jo5sJVBAeT`4alRB(2vvt$Z*#WY}lOW2~zv44KeUvsoLa zMX_$%OfOt(b763slI>N~g|Ai@_110Xt&Ues1%nCE>IIVX;c94X0tux%QC4;xc;3TF zIy6aB%qxqEZC1XaDIBfBl3`)K%b?d6NzfRXCnA9_{$X>Ia)2L6L02|GyBL!GB!w+K zDwfHv#i2fD?@CVPYWZO0y=u0bBDk$FD&J0!q(+VxD7@K24}!(muk`69yklNC{oC}+ z9tIyt3vKcv>;e1f&KEXScwv?gztHV?z9Z!X1db%hYDT1V%uug2RH(Nu*T41cZE6VGqT91XRnXVsvX%7B!Qj+RD|7mRMjfM> zYK;u`qcD^0$!+_5P`JL!a=cd+R=PsQWJSCWfl8#%vf1jA55i^us(^*j)nq^4-TPe@)E`;1v7S@M3R)q!g-E_mRx^6(u+dQEbrB{ zMZ909ph@^er`LuD73?Nty*IqN%4%c49gPwf#%P6Ri*R90H+F5}3FhpgM)~B)>f*c= zhpD{bCRQwEi;Odk7H z{BUX+nLco7WMl#;R8fSl8fsc^yQ<*D61sqeMWgEU7<;_n%;;2uU$vxgtX!GhWG^1& zdZtHs#s%=UbNbI4Q*`;`ymBnhwQheUMVr43YeN^}*Q3RD zgc|AGaY8KzIqcFbhj49TujZ;a!%ukxCqMos@rs&C4KIA4mODnbSyhf5!fl|2Y}2Na z`(ci5fK^DjHm`tK$0>(LMM|H+~ZN6ebMogk>>e5nK!^ zf7cPkwrVObIC>ICOk^{nwrkTalQzj?Vw+DWBI;1$xtaVPXb3ZKsVWYIh_OFzTsanH zR#o@laww&e&^1=XA@;`jK4aDXkIL-3L$59h3&p)#%u6TpWUS-+w^KRU$)Tls{D7qO zoaUJ&j95Yy5$Pq&vWv1tU;j}qX&B&i+Ays<;!B(7XCv>0vqv0wiH#@5Kf5Q?+0nxW zJa2Hb>*d^p;+%3HK0^}GR4;4Ts}1IN#}xAt_WE>R8V<#Ak#Bo!qCv&6B3I$?)H<1` zSIt5{@ycx-y_f1<+adPMEUAd-Qs5C{7w>(282f(OxJyRQencF9AELdFh-cJ^$e#1r zd0xJP@fdS>Zt8(p3F;pvlwe*8`#Zn_RHAuDF?be-VEIw!fuy&(vncUb&La_>3k?!BMA&%WoJwIB1^riIJu)`F44 zcrqij0cFkR7`mn?dJ2!Dg;6cWTt<2Z?0MVG*a<<5fgq?8ofOhkl4ekAPM~dQIW$6l ziUO6wD>SF+Rph?n#@w8auBvjsLdggG$;qkE{3GOyAI4wVCXF`U3B$t@bElnus>Xe#(P*r+8t#9bL{>+a z!a-wD&nvZ@;@r$*2ge^@VU@wBhw2_mnndo4+GvW@eJC&0294A1^iCUNkLod8X%$9j zB3CTqzNa_Lxo3qTExEQQxNN8v4YO6LJ)ADzXt6W2{|h}56X@Ovt;Vam`H#Q9x)xt$ zCY)hhDQGdpwzYR#?5eU9TUPr*xw)0qJDpbyR~p`|{X<74*v|cfkQ5U#ka~tbY%W%k zK)4)rlXyy7#k9m`tl~IaAPX}lu_iEi!ssL8O<7;nZV|XE*>HWBCi6#nMO+W zO_?YgyEKNsqbEbkaWvjv>8=45HI!WJs2pM3UNdlpY#{;ggQ2=J5{q?3DkGnj*;*>6 zUz~e@f4{EpeSG7ovR|4%f1gPjE#)Q5n2#y1sjJO{gjE%r@ro*(Nt)=#c7kce1Z= zALI@)+jSBLW1AVZfhzzwgE@D?HG4d`86|WhNs`H-wMY%8ZJ2eLCDOG5c_R$WJ_#Cv zMzFQwtRi%NtjtXFRo%pMT1N;R}+1rz~v zH#!@a!eX0aV^O^L`*l3)@a{Fm!q{G2k3UTafyTQz()bK3{dT~XLyZhVv!qcAbSIMyG3u@0?iqrUZKlUOf1X8C7U+g0BP`Rlj&@hi zMf#u%84pbOZ?QJ6omr}V`3+^^@n?f4_lX7hf00iHSCla9ylDxtp-)IskoC|*^}$hU z&BPyqxnfRL+=e22>cH3CvpaKB+}=S+bx4c-N%lm!l5H^7v9sjU_n;#nJ4G%jK5nvq zU=9P1go?ZQsb@-|3Glu;O&7CWFLKuCcMLzRmoTAYu}8hfQ`Tns%jj=wWA#-%9~znrU)Icc~LAg!-AbDdU9aWRoNZ+fH1mvbv^&#jz+zau+y7$FvQ6_8eJVn2*YS?!x3iAu71^b8 zd=%#>HHuoy-UIt${dezY%xnD-uM98jwlI7$)(PAv06fX`*#$^1B%nr(T=Cg3;Gww1?3digeI4YaU~??v7tWXRA}Q^3hkWvdc!D-kY0b0{ z8+dfox7X&+=HfG8`SuPm&Vn!$cbXC}OD+sJdg3VF;KNOf42h8Tt-Ea)p(blVExec8 zpqejZDhDfHNxE8MMx3#}d+WV>4cJ=qyFIGy6VhC095eD1mh4~1=Q;sHaUONXG6t;0 zQ{>Bid%53XPbeX|vY;@D^Bhc=5MB0R))+B4-nt(j7m_oEm|9&qIz4hnRwXq#AK6b6 z&e;2Q<0+K)m_(3uMaR*%BlIu}YEc^`^qy50<>j;qs`b(Ws3gxD8YFF2TeSTsGcSl| zD24WOz~SDn_+}?<{eDxW2_d*J)nBdF?ZWKaNIF%uBT^5 zai9~kp0=kWmD@5VCnM)Ldh8jc7!E>n-7bo_VTRs~KDw_@btznNC>(VhAir6ggKSCG z=}UX~<1#HxuG&~`k?i+g68GM$Oz+0LtaR5h6u3Bf6l-dj)gf4ia-65=c3JaXANMmC z${N{Mn#Rjl$4f<~zm3hwEyL#RUV~T2Xf%QoTtLZUbG?;n4OT)(cJ_%t$Jt`9^V|e7 z3<}L+9apDroW3n933m@_*n-J&zdRZ?%45BkiI*NhhGmn4Ob^zYt=Bjuj1t3(&2Sv& z(9f*!b5YW~59QfCBA^kdGL)N9f;|Gqt={tZx+h|9S|kbgXY-cP6=KJ&`28)EEMgW) zH73kOD!+5yY%5aog{ST5*8p&zK8RatfK(SyzUTI)83i%M^}yB7kqX4lu^CZKN zrZiMqIiMIC^Ax}5kTLK*cQoh>$xwNMK`R;-lpXB!5zyJ&O?BQY$(vMuGvdWlvINZC zmIc`mnpP0Adh%+WGAiSlHE*VBznJX!{%QwboFwNqYlVTa5m$#aHY6us7c^-D6kW90 zmGYrIIFy=Vxm$@s2fz}cDRX=Ur`0H_wz_9~ zQy=w2Q^YR3X0ES6Tmuq8qyM3sHqkzN={MY;4o&QkQuxd4`3`6Hd~2cV7$~lHv_nNR_Y8LQZo!w z+t;_KEqgE*bSV>3Ld!Z|ZUuqkO~%l~^Yr1_vVJwJqe%;L;0q}HYS4+@G3T_c@$O~h`_5hB znrTH-hxe1!*)disAogxU%K>DyRo~8kyMy|8nt%SW)pX~g`av-DUFdPJyXeK4J89^i zm+P)uZAwCU?`AI;Q^DoegfZgpFebSe+8IMG_{`b#bf+4T_`=c;o{kYe{a649%J&Ff zE1Vh-|Ah9DdK~)uYiQl0w$U#>>soQkAe%RmpZ!!d`i?b=#Bh9cF8+ybSNIif#GgI$ zx3)YsdgRHB@K)w;P&#W`e>OataAV8k`Jv+xq&JUICv6(?pK&=H0-1fW%Ug>)Evc8_ zmVe^D>E0QNp0E(y*1Tw7|EjGjdE|@p(ETpf6I*;x60z2-`J%}9195Y{jU4e6I!eRe zlw${fXpCYzS4W(3=Y$EK?);Pc*XYM`SIjus``$_9GIOD^*w>Z*mSB>a1d-9QHFI^g zP2upM`vnzQ6&E0(3@qDb{d2AN(jp7A|L2|mvLYN{d=A|EpI3m}o)^0g+`eSV@9)Q- z`UeTve|MmtEj2$M@4q0y&pZBUi0yOgrqEhVVE+JfwKUuNQ!vV?6jddq643(8@Hm3j zLDo-|+5#lsqPYXW5!bls|cQdEo z;l6m2xpV2Loc?-i|I*~*1CP*MO=8B)nOiT7tsvVjXggM9;#X##uklnZ%n3&ugLZGvi7FA>5qQmNc;7s`5#*05xkS?eAo(;4-~m_h5Eme&JbE%ctjkS-!&zB?C-kn*G^~5hJcw>HM%Wf0#!tlH&*1q#Siru&H{M%QB+ZB7IWn!SGUC{4P1TIBL{fQ8m2Fd zbtfQn{SY0$+!M>79zob`(+)a?H&!{1zwOuIOr99@1bJd{1x|E+Zm`pxU7Yl`X%9Wt z=$wL9zZ_pQdtXLlC85o61#mBs(aX+XFpyw%w*!{5mn88f{HLIOr~Jwz z@gB^iEyFK29m89JZ-uo8Hv|FlogO=n`4_(mQ2(0Cg+8;(MtX^6&9oXQKO8I-F;UAk zTy$l-`ysPc1pQ)CS7r^T8($nY1-ropjM2v+2EW^w!kGU@>o5{tdzc8q7|6GgpNx-#kKNa1i$|iD zF8Lw*_(I{0E$DV2Er63K)j9jirJ3v+A_qKK101-P{(dX^vSUmQcqTUs=5%6moO9T^ z=!|8umrm@WR^{m?{piquZ2;KHQk>*$V#d3?Zm-0lBnN~Dy#RtsBu_7Gb$VH z$DKf_w7>e9cPn7k@3||&oLl#Xo1>n1KJRrl5&2_;9ruWv9=L-UWv^wDs;Q zFTIvnG<#roGT9|$j>=BH$|?y(aMZG=(Xhw*qaQ=@w_q83cTN%csiU(C&O=vN&3-Ga zO;CiRTLkYp3^wLxgg6dO5DCZ9$_F_C$5kZJC@y>P?x~Q`5}vs?27%WH&c?u;qV1zWjIc*O8@>5^;hPv-BO@bg4J^xs2s zRa2EI{e7s2zO^}#D~6YD&irjydXnLWA3I7ST4nygvtI6g&@qeE{rx*^-O+f|Vh46h zQ@t8+d_@R84yXAsB6g^TR(m5Rav;!UA<={N@~oX2S|5iQIuZlV4)rood^8;Fvo=|! z5WT{x!>Oag!13CT5=OvaKd=Bqo(1j`7h4TtQZTrwmd2gdlvAhu5qNZ@m6HWIaVon( zECA>Fw3FOB>U^R*U}za_vJD=k-D?_w0sj9j;lpb2`Da0qICL8)>N@4q3p%>v(33^v zg9%6L!+UBnK9og0hOzF8pO|z>q>T>}{UXZX(AxTN%C|Stmo)_=z$Dini-sCm!QvMy ztXxu-8W42`gYEp})#5Hx>>V31Em_{n;9rM)zXDt0h%l~_W3mu457>Gg-LF6rJ9sP8ydrz zVo`Wr{x^7%RZp~Yo~^3U1_S?5E5aQno|>dJjT3kQ#Q~?tr&ZtUNIfOVRi`mhBfl^% z?MRGYwwn5+HSy6G;SnhOP?C58+xhry|6_()sud^7j(eU8%iJ&wg}#XXcOPQ^F&4p8G++e<)I`ryxw_Uscgw7nIhFSOnPhI^;HIb9`4+qf+JrmAFbb! zy5e11^gFI`$AjTPO>B3yNfG%SFGhEF1IJoT7G1~>om>UwZB}6AQJDPAsCus2`riyh zD}i3~R?v!DRR`XDnz{3>g_%dICtmpH*OPwyTS0$Vdl`FfDQWShlP4b}hvjcpeE83= z{_OUe@Bg3f{ybR>q@fE{iRCrFeE&B~cRA+WbIX{o{OVN1>z8)dxqsMvt$bwJZ-W<8 z;xCsio}1WmV(}cto0}I8XVkqBAjAIT`@aUxWc<%TG$%p-e!p>%7yCao*O0fJc`NOd z|G$W`>{hnZ`}X3uwBevrKQ8U)alfnuDrO)4di newVertices = new ArrayList<>(); while (vertices != null) { + for (Integer vertice : vertices) { for (int n : graph.adjList[vertice]) { if (!visited[n].getAndSet(true)) { newVertices.add(n); } + if (INTERPROCESS_BATCH == newVertices.size()) { + graph.workerQueues.add(new ArrayList<>(newVertices)); + newVertices.clear(); + } } } if (!newVertices.isEmpty()) { From 3be231657a0e23f60234137bf604a2794ed2cf71 Mon Sep 17 00:00:00 2001 From: Artemiy Romanov Date: Fri, 26 Dec 2025 15:58:41 +0300 Subject: [PATCH 3/3] Add jcstress test Since the bfs implementation is higly cohesive and jcstress actor model doesn't allow multiple iterations per actor, it's impossible to test the implementation's work layer per layer. So test is made to check correctness of visiting mechanism --- build.gradle | 6 ++ .../java/org/itmo/ParallelBFSQueueTest.java | 86 +++++++++++++++++++ src/main/java/org/itmo/Graph.java | 13 ++- 3 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 src/jcstress/java/org/itmo/ParallelBFSQueueTest.java diff --git a/build.gradle b/build.gradle index 568439c..8a3c45d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,6 @@ plugins { id 'java' + id "io.github.reyerizo.gradle.jcstress" version "0.9.0" } repositories { @@ -24,3 +25,8 @@ test { } failFast = true } + +jcstress { + verbose = true + timeMillis = "2000" +} diff --git a/src/jcstress/java/org/itmo/ParallelBFSQueueTest.java b/src/jcstress/java/org/itmo/ParallelBFSQueueTest.java new file mode 100644 index 0000000..dcd260f --- /dev/null +++ b/src/jcstress/java/org/itmo/ParallelBFSQueueTest.java @@ -0,0 +1,86 @@ +package org.itmo; + +import org.openjdk.jcstress.annotations.*; +import org.openjdk.jcstress.infra.results.*; + +import java.util.Queue; +import java.util.Random; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.itmo.*; + +@JCStressTest +@Outcome(id = "true", expect = Expect.ACCEPTABLE, desc = "Each vertex is visited exactly once") +@Outcome(id = "false", expect = Expect.FORBIDDEN, desc = "Each vertex might be visited more than once") +@State +public class ParallelBFSQueueTest { + private static final int VERTICES = 20; + + private final Graph graph; + private int visitedCount = 0; + private Queue currentLevel = new ConcurrentLinkedQueue<>(); + private Queue nextLevel = new ConcurrentLinkedQueue<>(); + + public ParallelBFSQueueTest() { + this.graph = new Graph(VERTICES); + for (int i = 1; i < VERTICES; i++) { + this.graph.addEdge(0, i); + } + this.currentLevel.add(0); + } + + @Actor + public void actor1() { + Integer vertex; + while ((vertex = currentLevel.poll()) != null) { + graph.visited[vertex].getAndSet(true); + for (int newVertex : graph.getAdjList()[vertex]) { + nextLevel.add(newVertex); + } + } + } + + @Actor + public void actor2() { + Integer vertex; + while ((vertex = currentLevel.poll()) != null) { + graph.visited[vertex].getAndSet(true); + for (int newVertex : graph.getAdjList()[vertex]) { + nextLevel.add(newVertex); + } + } + } + + @Actor + public void actor3() { + Integer vertex; + while ((vertex = currentLevel.poll()) != null) { + graph.visited[vertex].getAndSet(true); + for (int newVertex : graph.getAdjList()[vertex]) { + nextLevel.add(newVertex); + } + } + } + + @Actor + public void actor4() { + Integer vertex; + while ((vertex = currentLevel.poll()) != null) { + graph.visited[vertex].getAndSet(true); + for (int newVertex : graph.getAdjList()[vertex]) { + nextLevel.add(newVertex); + } + } + } + + @Arbiter + public void arbiter(L_Result r) { + for (int i = 0; i < VERTICES; i++) { + if (this.graph.visited[i].get() == true) { + this.visitedCount++; + } + } + currentLevel = nextLevel; + r.r1 = visitedCount == 1; + } +} diff --git a/src/main/java/org/itmo/Graph.java b/src/main/java/org/itmo/Graph.java index 6d7d154..41a10e8 100644 --- a/src/main/java/org/itmo/Graph.java +++ b/src/main/java/org/itmo/Graph.java @@ -7,13 +7,13 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -class Graph { +public class Graph { private final int V; private final ArrayList[] adjList; AtomicBoolean[] visited; - private final ConcurrentLinkedQueue> globalQueue; - private final ConcurrentLinkedQueue> workerQueues; + public final ConcurrentLinkedQueue> globalQueue; + public final ConcurrentLinkedQueue> workerQueues; private final ExecutorService executor; private final int cpus; private volatile CountDownLatch latch; @@ -23,7 +23,12 @@ class Graph { private final AtomicBoolean isFinished = new AtomicBoolean(false); private final int INTERPROCESS_BATCH = 50; - Graph(int vertices) { + public ArrayList[] getAdjList() { + return this.adjList; + } + + public Graph(int vertices) { + this.V = vertices; this.visited = new AtomicBoolean[V]; adjList = new ArrayList[vertices];