From 604c805cfd5c5a36f1e66800c99efee3b6e91c05 Mon Sep 17 00:00:00 2001 From: Gregor Olenik Date: Wed, 30 Jul 2025 09:27:02 +0200 Subject: [PATCH 01/33] use repartAllToAll --- include/OGL/CommunicationPattern.hpp | 6 ++++++ src/CommunicationPattern.cpp | 27 +++++++++++++++++++++++++++ src/MatrixWrapper/Distributed.cpp | 9 +++++---- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/include/OGL/CommunicationPattern.hpp b/include/OGL/CommunicationPattern.hpp index 7fcf542e..0bb6e477 100644 --- a/include/OGL/CommunicationPattern.hpp +++ b/include/OGL/CommunicationPattern.hpp @@ -19,6 +19,12 @@ struct AllToAllPattern { std::vector recv_offsets; }; +/* @brief computes AllToAllPattern for repart comm from global allToAll pattern + * + */ +AllToAllPattern compute_repart_allToall( + const ExecutorHandler &exec_handler, const AllToAllPattern allToAll); + /* @brief This function computes the send and recv counts vectors and the send * and recv offsets vectors for scattering from an owner to all ranks, including * owner itself diff --git a/src/CommunicationPattern.cpp b/src/CommunicationPattern.cpp index 2d9b132c..0c7fe548 100644 --- a/src/CommunicationPattern.cpp +++ b/src/CommunicationPattern.cpp @@ -179,6 +179,33 @@ void communicate_values(const ExecutorHandler &exec_handler, // } } +AllToAllPattern compute_repart_allToall( + const ExecutorHandler &exec_handler, const AllToAllPattern allToAllIn) + { + auto host_comm = exec_handler.get_host_comm(); + auto repart_comm = exec_handler.get_repart_comm(); + auto ranks = repart_comm->size(); + + std::vector send_counts(ranks); + std::vector send_offsets(ranks+1); + std::vector recv_counts(ranks); + std::vector recv_offsets(ranks+1); + + label start_rank = host_comm->rank(); + for (auto i=0;i src_exec, std::shared_ptr target_exec, diff --git a/src/MatrixWrapper/Distributed.cpp b/src/MatrixWrapper/Distributed.cpp index 72eaae43..312a7346 100644 --- a/src/MatrixWrapper/Distributed.cpp +++ b/src/MatrixWrapper/Distributed.cpp @@ -384,7 +384,7 @@ void update_impl( std::map linops, label verbose) { auto comm = exec_handler.get_host_comm(); - // auto repart_comm = exec_handler.get_repart_comm(); + auto repart_comm = exec_handler.get_repart_comm(); auto ref_exec = exec_handler.get_ref_exec(); auto rank = exec_handler.get_host_rank(); auto device_exec = exec_handler.get_device_exec(); @@ -392,12 +392,13 @@ void update_impl( word fieldname = host_A->get_field_name(); // perform all-to-all updates first - auto all_to_all_update = [comm, ref_exec, device_exec, + auto all_to_all_update = [repart_comm, ref_exec, device_exec, all_to_all_update_data, host_A, - force_host_buffer]() { + force_host_buffer, exec_handler]() { for (auto [id, comm_pattern, data_ptr] : all_to_all_update_data) { + auto repartAllToAll = compute_repart_allToall(exec_handler, comm_pattern); auto [length, send_data_ptr] = host_A->get_interface_data(id); - communicate_values(ref_exec, device_exec, comm, comm_pattern, + communicate_values(ref_exec, device_exec, repart_comm, repartAllToAll, send_data_ptr, data_ptr, force_host_buffer); } }; From f9d9a9942dc60b5fe4762a33986dac117810e413 Mon Sep 17 00:00:00 2001 From: Gregor Olenik Date: Wed, 30 Jul 2025 09:35:50 +0200 Subject: [PATCH 02/33] add get_ranks_per_gpu --- include/OGL/DevicePersistent/ExecutorHandler.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/OGL/DevicePersistent/ExecutorHandler.hpp b/include/OGL/DevicePersistent/ExecutorHandler.hpp index 3c9b7da5..50ec322e 100644 --- a/include/OGL/DevicePersistent/ExecutorHandler.hpp +++ b/include/OGL/DevicePersistent/ExecutorHandler.hpp @@ -300,6 +300,8 @@ class ExecutorHandler * */ bool get_non_orig_device_comm() const { return non_orig_device_comm_; } + label get_ranks_per_gpu() const { return device_id_handler_.ranks_per_gpu; } + const std::shared_ptr get_device_exec() const { return this->get_persistent_object(); From e0041d2d149b9179fd9d911f2bedfc915232cd0d Mon Sep 17 00:00:00 2001 From: Gregor Olenik Date: Wed, 30 Jul 2025 13:57:01 +0200 Subject: [PATCH 03/33] add basic implementation of gatherv instead off alltoallv for repart update --- include/OGL/.Preconditioner.hpp.swn | Bin 0 -> 16384 bytes include/OGL/.Preconditioner.hpp.swo | Bin 0 -> 16384 bytes .../OGL/DevicePersistent/ExecutorHandler.hpp | 7 ++-- include/OGL/lduLduBase.hpp | 1 + src/CommunicationPattern.cpp | 6 +-- src/MatrixWrapper/Distributed.cpp | 36 +++++++++++++++++- 6 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 include/OGL/.Preconditioner.hpp.swn create mode 100644 include/OGL/.Preconditioner.hpp.swo diff --git a/include/OGL/.Preconditioner.hpp.swn b/include/OGL/.Preconditioner.hpp.swn new file mode 100644 index 0000000000000000000000000000000000000000..6793705a6f00ad2117ddacb5b1735306a1af1c01 GIT binary patch literal 16384 zcmeHN-)|hn9iO(L1WG7sA9&$ma!BP)v3(Z@hiKziRqZ;swXsP;04Zph+nu}HcyD(* zJ7=Fs)1pfJ2c@n0Pzk|PrAn>TAL1#9N9ao{KnNrxeh4ZdfdqYODeY%=X7_g2mjjPu*EZ;hxp{)?HbVZ$&J7L^?t1+FwR;Hv-rb#J$CcpU zUp<-3j!ztq=I6rLW1$}pSrAPz`GI!W_L*dDFZOvm?uYFl^1>0mZ=POnZwctB1|y1ZB;%YbFTGGH073|Iy%1C{~H zfMwu+lL46=BtJyxUo_!&&F2?tpZ_%1Idk8u$v-vn4RikwHTge`{EWGOz%-Dz^NEq) zYvku^^1mDT{YL(an*47@e!<8;tjWKWw`)GXYdV~_Z*JQU%YbFTGGH073|Iy%1C{~H zfMvikU>UFs{9iJ_d_um7p1q?s!ubDxzW;yetAzXscm{YH_zCbNFa~yk`+&m$1r7m! zy_JxUfwzDcfv12JI01Zeh>$-6zXYBD9sw4BTY=YZA>;+%5^xNd2U@^E;6~stUm@f@ z;5pz5@H612z-8e3fCP>JZ{AGEZ-J+P$AJalX5fRHU=O?tTmhZ{wtzc;R}K>Ld*Ii= z7+3&q01g1p-bl#Lfro)xfRDaR$gcnfJPOIaY zNklVQWF#~@%b|a?mBn(*M9R;=>||jT^k}mejJdCcQ4sZ8^b)e7cFo06)8{*Z$6Y?= zUaK{6QPZSzyMY|Ig8L&+odR)t%#*Qbrg6B#?~BE7xz*a|Uis*6$BvWAIB}daJPrI2 z3zhm}iW4bJEICeh6oh{Bn#OCA3#M8wEObOeHg*HZ(k8wsCEexL%)V%}z9*D+z?xT) zCzYcvP5d-n-K&O}bzBs|6yCDI^0F~;wGKUHNEk4|o7Xi6ldg6#{M&9CJjR|VS|*rm=QXu;A#PY0k=Pxq?Sk&X4u({87^!$mhvxjRFL zX}{W{3Jq5(eaDfpn@XV~(=0v6gZ@BH&%ByJb%f~=+PDy1kP|m@(4a?1)>QRR%}*(5 zb0-zo^fS6CPrg>}N$~JoY-Z(WbhK}(nx0i=cg5FkEPO>XhN*Fy<4hKloDN5!3~0!A zct}%ku*<|_jv}b$K66yCl;vx+_ot|j6JzoADA^P%yvN|S*{G;AW@yN|JZvs>>NR7E zX;C!v)I6(7hA3Pd<+I1jPIM(K%1WsgmZp|Y8uWfjbCY}+NVK90O|vuCIa+Q;CCEPG z#j~h#-e9TOsBs2AJr<_Cl%`oUHMM%M)d8FuZAGOZWkH2njL|5?bfL9slCkJG%l*8R zPHMN-?|FIU$r7V40?fYE>Z)LD&2TQ&T_pYC6dzmtynI*fE)@Z1$x&LVS`^0zQ(4Hf z`IxGD=(~v&i{^acYPP2AEm2d1XS5mhgKW)VVvl~qpA`1Gmu#u|Hr6q$rDBPe7PhO~ zWO3>GydFfG$&&g$WGGN$Z8WtJqq-|t;%4N!*{pNTtkY|Y@rMgf()^y zFIZWSZ8R&AwU%=qarYwkdug4)C~jA(W9bWRGMBl9{L{WPbi{S)ip7kWD8(PVlreY{CiYRS{jl%@b~s8vrDH(k8)+P6;+g|ZjMOqw2QJ#U(t zc{DBi3uMu3_9$CCjaHOIp=4rP6V>9Z8x4xWT&Hl&TdaiVcQ58H>#E;jUfc~9{TNBh zt995=a828cj%lXXw5$XZZk6t-1L_-D#eNX=80p$xnWU*Yt6p}XlvlDH&ldI! z&_iaozr|9n6(?>N`$4qbkK6h~Nte)QB3OUOXdHQ*kanA%-CB8Qb{+etDCM(jKAZ); zfD4D7-ddkMHrJVr#jIKb1e6Q?)ga`{ak3}WgYP*$mJXfo%->BBo7(FQVv!QH|Nk-e z@6Q2h|BvlzcD;e$uL3U{*%c+Xmu0{*U>UFsSOzQumI2FvWxz6E8L$jk1}p>r6$UO- iiq`|xcO2xhep@to-z&HriHP>ie{k?JT>tm+B>5MH00&|K literal 0 HcmV?d00001 diff --git a/include/OGL/.Preconditioner.hpp.swo b/include/OGL/.Preconditioner.hpp.swo new file mode 100644 index 0000000000000000000000000000000000000000..59f5bb35988ed3c6ebd5b633ff6bf04be8b770a0 GIT binary patch literal 16384 zcmeHOTa4UR89wPPEHvd(5agkfyQv}%*`1kON`f=H5^UJ8G?yi9LZvn`9{bFUvmV>A zJ-f3Ffxht42MVodLE?oZedz-Qo@jUgfp`Iml&F=siR%O6iH9I0AY8t48y|aSv)u?G zA#CYedwl-$pZ|R4Kj--W?QJ*DEFCuv)%Ot`?;zx-uPydoeeSNOzjn_yt;1HI@_VMxp0t zeiYKA-izajimICx0~G^XV_=YVW)JN+y?@`{Cabt>`a$FVcb(pvj!L>>pkkn6pkkn6 zpkkn6pkkn6pkm;Ent?3dPCkPk+#!3hBG21O=YPrLjJ)43mH$(gFU$MiFO~m8mYI1(8t^!X3j{xrle)ASWehyp$ zIsgS81`Yr_fxm1gRR>0X_-L0WIL2z>n`D z|UIwlJmw`_KCjd5XzebYd zSCbPRhCI^Dv#hk|B-FFxENS5@i!?L3E0JX#^TU(zJiG2YS>g|82&7g=iy^GF7m(ZN*%NFU5bxH zP}dyUUaK7@s$8AxQD}N})pw~)ht#c&3#|EB&vqjxNvWMi!75G6!mk>cnyPc5V6UC_ zqbTb^q~ioB-9%eJS7~6z-M-y%Hf))HHlrGj#TPI|y@``rR(s$Fo|zXUG#ezL7(+g? zCV`z(U;uwR?x=#WJYDg@e3WE<*fq0cKx^W@>}V3LrDjS4n_bj4q|6y)ks-Td%oW<6 zQnl+T%{bGLO$yAzvWqZoB-n)@`xeNoJ>j2)x^L_LUm*hr5rQMxo=XBc^Hbah2IT$+Jl*LIyWYjNraewgjwHxFvZ zyE&$8eCiWTMxVs(a~t#>q$#3}x!msuDOM9hur^|ZFQAsS&{YnHi83W5JFb%I4}#3^ zCO&qhMSn=W1-|-*P$z567-GieWC;~md?x5v?ke{#*1It3X?YtfZ8C;hcMZNXZdi@8 zua=E@Lz^l2L@775`Chx(j>*}w`DSu^yXOUc`^5g%jj)MU3V95mDy%b4KTHMLlf3)7GvT0d?|I3bz^t23o~N;h4UE&f~3c&g+pjsixRJF ziqa9a&rvr!MZ12Qv6j5{42cKrz;`V%g@g+3=c*}N?kbzvS(FnhCbC%2H*Qf;&!pZ! zB2N5O?2giEjm<4zmgh8|PIMS!2k6r#UCz%& z&GHR=w7V9Bl97;HY?qRJvCTX0kCxjqk4tW=V4l}Lr&N|jKjyem+i!UhJeL+%S4qL9 zbvYfAs%~1dU}QfVDkH_j$0n0%9d`pKO;z+Dr>Sv)u+<@r9hVx5k<-TwvP*t)ZcHb% zyL3{_iuy;VwSvy-!r~EjOS{KDP(RK?q)#A>fzLLM0Pg|b z4ctIX{t|EncpTUP+zVVozpetW0xtqz06qt>{tkias2Hdis2Hdi_%AbX(J-*D6*p&c zQ9S14(TYlP$xI)Tmm)tVA8XmOP8^BU4APoN3K4dT9Z)_LBlchZ+OfNEUhKajnqsrvIuuI~5wHgW5z&h*tf`(x z%-G3#GX~-w#4$v-#1DP+sPKPswvQaD$*AO^2M^t5SX?h2lb}XRf94Ev)5dJq<9i-a zuxBoi7~=T>83-Q1m18YiSemP5DZtGuz*?ctW&uFtX|%B(BL?DKDTkFRmp3hIBc5z( zRrRQ35Q6=0SPqSUEeiLe7y$Mvt6eyn^rrF?38NYC*@U8qK=$ zRdj~%7D|7%Ji@B}Mk8%(=uG1V{6~gV8FZUNt5wI_i#+PZ{U*DX&W6*t&lDY1 z)tr1+mCnu&V&v7S%8#r%!GOOcVX?JX6DD*{)#fp|lZs{OG*={|o-<6%ya_Y)jFGB# zi~i*z`IT6+MK)KMWKMc{lUK;EMA$6jNflP|)V|g~lFLuNDs=M}DG1T`;z*V?P9}Uq z6ADdFU|7#_*T!d}-nvqSyoVSWomY{$xFxULqxJUS(L8_2S5Z5TkZ7ifmU))@)Wp8| z9m8aA@r=1SV_K$arfV$X)=k#0H(CeGX{HAYJIhF!xvmY|mglWR%ahw;ma#Wm%(7mC^761SM literal 0 HcmV?d00001 diff --git a/include/OGL/DevicePersistent/ExecutorHandler.hpp b/include/OGL/DevicePersistent/ExecutorHandler.hpp index 50ec322e..43fd80ea 100644 --- a/include/OGL/DevicePersistent/ExecutorHandler.hpp +++ b/include/OGL/DevicePersistent/ExecutorHandler.hpp @@ -270,7 +270,7 @@ class ExecutorHandler // gko comm label group = device_id_handler_.compute_group(); MPI_Comm gko_comm; - label host_rank = 0; + label host_rank = Pstream::myProcNo(); MPI_Comm_split(MPI_COMM_WORLD, group, host_rank, &gko_comm); device_comm_ = std::make_shared( @@ -278,8 +278,9 @@ class ExecutorHandler // repart comm MPI_Comm repart_comm; - label device_id = device_id_handler_.compute_device_id(4); - MPI_Comm_split(MPI_COMM_WORLD, device_id, host_rank, &repart_comm); + label global_rank = Pstream::myProcNo(); + label device_id = global_rank / device_id_handler_.ranks_per_gpu; + MPI_Comm_split(MPI_COMM_WORLD, device_id, host_rank , &repart_comm); repart_comm_ = std::make_shared( repart_comm, gko_force_host_buffer_); diff --git a/include/OGL/lduLduBase.hpp b/include/OGL/lduLduBase.hpp index e584adbe..33c86b07 100644 --- a/include/OGL/lduLduBase.hpp +++ b/include/OGL/lduLduBase.hpp @@ -216,6 +216,7 @@ class lduLduBase : public OGL_Info, solverPerformance &solverPerf) const { bool fused = solver_controls_.lookupOrDefault("fuse", true); + exec_handler_.init_device_comm(); auto repartitioner = std::make_shared( host_matrix_wrapper_->get_local_nrows(), ranks_per_gpu_, verbose_, diff --git a/src/CommunicationPattern.cpp b/src/CommunicationPattern.cpp index 0c7fe548..7a3387ba 100644 --- a/src/CommunicationPattern.cpp +++ b/src/CommunicationPattern.cpp @@ -192,15 +192,15 @@ AllToAllPattern compute_repart_allToall( std::vector recv_offsets(ranks+1); label start_rank = host_comm->rank(); - for (auto i=0;i(end - start).count()/1000.0; + // std::cout << __FILE__ << ":" << "delta t " << delta_t << " [ms]\n"; + auto [length, send_data_ptr] = host_A->get_interface_data(id); - communicate_values(ref_exec, device_exec, repart_comm, repartAllToAll, - send_data_ptr, data_ptr, force_host_buffer); + // communicate_values(ref_exec, device_exec, repart_comm, repartAllToAll, + // send_data_ptr, data_ptr, force_host_buffer); + // if ( repart_comm->rank() == 0 ) { + // std::cout << __FILE__ << + // " Pstream::rank " << Pstream::myProcNo() << + // " repart_rank() " << repart_comm->rank() << + // " send_offsets.back() " << repartAllToAll.send_offsets.back() << + // " recv_counts: " << repartAllToAll.recv_counts << + // " recv_offsets: " << repartAllToAll.recv_offsets << + // std::endl; + // } + + MPI_Request request; + + MPI_Igatherv( + send_data_ptr, + repartAllToAll.send_offsets.back(), + MPI_DOUBLE, + data_ptr, + repartAllToAll.recv_counts.data(), + repartAllToAll.recv_offsets.data(), + MPI_DOUBLE, + 0, + repart_comm->get(), + &request + ); + + MPI_Wait(&request, MPI_STATUS_IGNORE); } }; From b4cadf543cc891de260dfd164c559696c6effe02 Mon Sep 17 00:00:00 2001 From: Gregor Olenik Date: Wed, 30 Jul 2025 17:03:34 +0200 Subject: [PATCH 04/33] use forceHostBuffer for vector updates --- include/OGL/DevicePersistent/Vector.hpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/include/OGL/DevicePersistent/Vector.hpp b/include/OGL/DevicePersistent/Vector.hpp index 4d75f21b..6e28f3fc 100644 --- a/include/OGL/DevicePersistent/Vector.hpp +++ b/include/OGL/DevicePersistent/Vector.hpp @@ -67,7 +67,7 @@ struct VectorInitFunctor { //// TODO store auto comm_pattern = compute_gather_to_owner_counts( exec_, repartitioner->get_ranks_per_gpu(), host_size); - bool host_buffer = !exec_.get_non_orig_device_comm(); + bool host_buffer = exec_.get_gko_force_host_buffer(); communicate_values(ref_exec, exec, comm, comm_pattern, host_view.get_const_data(), @@ -171,13 +171,14 @@ class PersistentVector /** Copies the content of the distributed vector back to the original source **/ - void copy_back() + MPI_Request copy_back() { auto exec = exec_.get_device_exec(); auto rank = exec_.get_host_rank(); auto ref_exec = exec_.get_ref_exec(); auto comm = exec_.get_host_comm(); - bool host_buffer = !exec_.get_non_orig_device_comm(); + auto repart_comm = exec_.get_repart_comm(); + bool host_buffer = exec_.get_gko_force_host_buffer(); auto repartitioner = dist_matrix_->get_repartitioner(); auto host_size = repartitioner->get_orig_size(); @@ -185,10 +186,25 @@ class PersistentVector auto comm_pattern = compute_scatter_from_owner_counts( exec_, repartitioner->get_ranks_per_gpu(), host_size); + auto repartAllToAll = compute_repart_allToall(exec_, comm_pattern); communicate_values(exec, ref_exec, comm, comm_pattern, get_vector()->get_local_values(), const_cast(memory_), host_buffer); + MPI_Request request; + // MPI_Iscatterv( + // get_vector()->get_local_values(), + // repartAllToAll.send_counts.data(), + // repartAllToAll.send_offsets.data(), + // MPI_DOUBLE, + // const_cast(memory_), + // repartAllToAll.recv_counts.back(), + // MPI_DOUBLE, + // 0, + // repart_comm->get(), + // &request + // ); + return request; } /** Writes the content of the distributed vector to disk From d0fe5a1fcf55122f13141f62ef25e65ed91e0a5c Mon Sep 17 00:00:00 2001 From: Gregor Olenik Date: Mon, 4 Aug 2025 08:28:48 +0200 Subject: [PATCH 05/33] wip performance tuning --- include/OGL/CommunicationPattern.hpp | 2 +- .../OGL/DevicePersistent/ExecutorHandler.hpp | 10 ++- include/OGL/DevicePersistent/Vector.hpp | 71 ++++++++++++++----- include/OGL/StoppingCriterion.hpp | 21 +++++- include/OGL/lduLduBase.hpp | 11 ++- src/CommunicationPattern.cpp | 12 ++-- src/MatrixWrapper/Distributed.cpp | 6 +- src/StoppingCriterion.cpp | 7 +- 8 files changed, 103 insertions(+), 37 deletions(-) diff --git a/include/OGL/CommunicationPattern.hpp b/include/OGL/CommunicationPattern.hpp index 0bb6e477..51f8e2db 100644 --- a/include/OGL/CommunicationPattern.hpp +++ b/include/OGL/CommunicationPattern.hpp @@ -23,7 +23,7 @@ struct AllToAllPattern { * */ AllToAllPattern compute_repart_allToall( - const ExecutorHandler &exec_handler, const AllToAllPattern allToAll); + const ExecutorHandler &exec_handler, const AllToAllPattern allToAll, label start_rank); /* @brief This function computes the send and recv counts vectors and the send * and recv offsets vectors for scattering from an owner to all ranks, including diff --git a/include/OGL/DevicePersistent/ExecutorHandler.hpp b/include/OGL/DevicePersistent/ExecutorHandler.hpp index 43fd80ea..9197c940 100644 --- a/include/OGL/DevicePersistent/ExecutorHandler.hpp +++ b/include/OGL/DevicePersistent/ExecutorHandler.hpp @@ -71,12 +71,18 @@ struct DeviceIdHandler { return device_global_id % num_devices_per_node; } + label global_owner() const + { + label rank = Pstream::myProcNo(); + return rank - (rank % ranks_per_gpu); + } + /* @brief check if rank is an owning rank */ bool is_owner() const { label rank = Pstream::myProcNo(); - label owner_rank = rank - (rank % ranks_per_gpu); + label owner_rank = rank - (rank % ranks_per_gpu); bool is_owner = owner_rank == rank; return is_owner; } @@ -303,6 +309,8 @@ class ExecutorHandler label get_ranks_per_gpu() const { return device_id_handler_.ranks_per_gpu; } + label get_owner_rank() const { return device_id_handler_.global_owner(); } + const std::shared_ptr get_device_exec() const { return this->get_persistent_object(); diff --git a/include/OGL/DevicePersistent/Vector.hpp b/include/OGL/DevicePersistent/Vector.hpp index 6e28f3fc..311868bc 100644 --- a/include/OGL/DevicePersistent/Vector.hpp +++ b/include/OGL/DevicePersistent/Vector.hpp @@ -186,25 +186,58 @@ class PersistentVector auto comm_pattern = compute_scatter_from_owner_counts( exec_, repartitioner->get_ranks_per_gpu(), host_size); - auto repartAllToAll = compute_repart_allToall(exec_, comm_pattern); - - communicate_values(exec, ref_exec, comm, comm_pattern, - get_vector()->get_local_values(), - const_cast(memory_), host_buffer); - MPI_Request request; - // MPI_Iscatterv( - // get_vector()->get_local_values(), - // repartAllToAll.send_counts.data(), - // repartAllToAll.send_offsets.data(), - // MPI_DOUBLE, - // const_cast(memory_), - // repartAllToAll.recv_counts.back(), - // MPI_DOUBLE, - // 0, - // repart_comm->get(), - // &request - // ); - return request; + + label owner_rank = exec_.get_owner_rank(); + auto repartAllToAll = compute_repart_allToall(exec_, comm_pattern, owner_rank); + + // if (owner_rank != Pstream::myProcNo()){ + // label recv_count = repartAllToAll.recv_counts[0]; + // repartAllToAll.recv_counts[Pstream::myProcNo()] = recv_count; + // repartAllToAll.recv_counts[0] = 0; + // } + + // communicate_values(exec, ref_exec, comm, comm_pattern, + // get_vector()->get_local_values(), + // const_cast(memory_), host_buffer); + // std::cout << __FILE__ + // << " owner_rank " << exec_.get_owner_rank() + // << " rank " << Pstream::myProcNo() + // << " comm_pattern.send_counts: " << comm_pattern.send_counts + // << " comm_pattern.recv_counts: " << comm_pattern.recv_counts + // << " send_counts: " << repartAllToAll.send_counts + // << " send_offsets: " << repartAllToAll.send_offsets + // << " recv_counts: " << repartAllToAll.recv_counts + // << "\n"; + + // auto start_rep = std::chrono::steady_clock::now(); + label send_size = comm_pattern.send_offsets.back(); + auto send_view = gko::array::const_view(exec, send_size, + get_vector()->get_local_values()); + auto tmp = gko::array(exec, send_size); + + tmp = send_view; + tmp.set_executor(ref_exec); + // auto end_rep = std::chrono::steady_clock::now(); + // auto delta_t_rep = std::chrono::duration_cast(end_rep - start_rep).count() /1000.0; + // std::cout << __FILE__ << " copy back: " << delta_t_rep << " [ms]\n"; + + + MPI_Request copy_back_req; + MPI_Iscatterv( + tmp.get_data(), + //get_vector()->get_local_values(), + repartAllToAll.send_counts.data(), + repartAllToAll.send_offsets.data(), + MPI_DOUBLE, + const_cast(memory_), + repartAllToAll.recv_counts[0], + MPI_DOUBLE, + 0, + repart_comm->get(), + ©_back_req + ); + MPI_Wait(©_back_req,MPI_STATUS_IGNORE); + return copy_back_req; } /** Writes the content of the distributed vector to disk diff --git a/include/OGL/StoppingCriterion.hpp b/include/OGL/StoppingCriterion.hpp index 0f70bd86..fc2cfdae 100644 --- a/include/OGL/StoppingCriterion.hpp +++ b/include/OGL/StoppingCriterion.hpp @@ -147,6 +147,8 @@ class StoppingCriterion { const label frequency_; + const word frequencyMode_; + const scalar relaxationFactor_; const bool adapt_minIter_; @@ -172,6 +174,7 @@ class StoppingCriterion { norm_eval_limit_( controlDict.lookupOrDefault("normEvalLimit", label(100))), frequency_(controlDict.lookupOrDefault("evalFrequency", label(1))), + frequencyMode_(controlDict.lookupOrDefault("evalFrequencyMode", word("relative"))), // optimizer, fixed relaxationFactor_( controlDict.lookupOrDefault("relaxationFactor", scalar(0.6))), adapt_minIter_( @@ -199,19 +202,31 @@ class StoppingCriterion { { label minIter = minIter_; label frequency = frequency_; + // in case of export_res all residuals need to be computed + std::cout << __FILE__ << "adapt minIter and frequency0 \n"; if (!export_res) { + std::cout << __FILE__ << "adapt minIter and frequency1 \n"; if (prev_solve_iters > 0 && adapt_minIter_ && prev_rel_cost > 0) { + std::cout << __FILE__ << "adapt minIter and frequency2 \n"; minIter = prev_solve_iters * relaxationFactor_; + if (frequencyMode_ == "optimizer") { auto alpha = sqrt(1.0 / (prev_solve_iters * (1.0 - relaxationFactor_)) * prev_rel_cost); frequency = min(norm_eval_limit_, max(1, label(1 / alpha))); + } + // if (frequencyMode_ == "relative") { + frequency = label(prev_solve_iters*0.075) + 1; + // } } } - word msg = "Creating stopping criterion with minIter " + - std::to_string(minIter) + " frequency " + - std::to_string(frequency); + word msg = "Creating stopping criterion with minIter " + std::to_string(minIter) + + " frequency " + std::to_string(frequency) + + " prev_solve_iters " + std::to_string(prev_solve_iters) + + + " adapt_minIter_ " + std::to_string(adapt_minIter_) + + + " prev_rel_cost " + std::to_string(prev_rel_cost) + + " prev_solve_iters*0.075 " + std::to_string(prev_solve_iters*0.075); MLOG_0(verbose, msg) diff --git a/include/OGL/lduLduBase.hpp b/include/OGL/lduLduBase.hpp index 33c86b07..c137b1e5 100644 --- a/include/OGL/lduLduBase.hpp +++ b/include/OGL/lduLduBase.hpp @@ -306,8 +306,13 @@ class lduLduBase : public OGL_Info, delta_t_solve_ = delta_t_solve; } + // auto start_rep = std::chrono::steady_clock::now(); TIME_WITH_FIELDNAME(verbose_, copy_x_back, this->fieldName(), - dist_x.copy_back();) +dist_x.copy_back();) + // auto copy_back_req = dist_x.copy_back(); + // auto end_rep = std::chrono::steady_clock::now(); + // auto delta_t_rep = std::chrono::duration_cast(end_rep - start_rep).count() /1000.0; + // std::cout << __FILE__ << " full copy back: " << delta_t_rep << " [ms]\n"; auto bandwidth_copy_back = sizeof(scalar) * psi.size() / delta_t_copy_x_back / 1000.0; @@ -335,10 +340,12 @@ class lduLduBase : public OGL_Info, std::to_string(time_per_dof) + std::string(" [ns]") + std::string("\n\tTime per iteration and DOF: ") + std::to_string(time_per_iter_and_dof) + std::string(" [ns]") + - std::string("\n\tRetrieve results bandwidth ") + + std::string("\n\tRetrieve results bandwidth "); // + std::to_string(bandwidth_copy_back) + std::string(" [GByte/s]"); MLOG_0(verbose_, msg) + // MPI_Wait(©_back_req,MPI_STATUS_IGNORE); + return solverPerf; } diff --git a/src/CommunicationPattern.cpp b/src/CommunicationPattern.cpp index 7a3387ba..8e39a052 100644 --- a/src/CommunicationPattern.cpp +++ b/src/CommunicationPattern.cpp @@ -180,18 +180,18 @@ void communicate_values(const ExecutorHandler &exec_handler, } AllToAllPattern compute_repart_allToall( - const ExecutorHandler &exec_handler, const AllToAllPattern allToAllIn) + const ExecutorHandler &exec_handler, const AllToAllPattern allToAllIn, label start_rank) { auto host_comm = exec_handler.get_host_comm(); auto repart_comm = exec_handler.get_repart_comm(); auto ranks = repart_comm->size(); - std::vector send_counts(ranks); - std::vector send_offsets(ranks+1); - std::vector recv_counts(ranks); - std::vector recv_offsets(ranks+1); + std::vector send_counts(ranks, 0); + std::vector send_offsets(ranks+1,0); + std::vector recv_counts(ranks, 0); + std::vector recv_offsets(ranks+1,0); - label start_rank = host_comm->rank(); + // label start_rank = host_comm->rank(); for (auto i=0;i(end - start).count()/1000.0; // std::cout << __FILE__ << ":" << "delta t " << delta_t << " [ms]\n"; @@ -415,7 +415,6 @@ void update_impl( // " recv_offsets: " << repartAllToAll.recv_offsets << // std::endl; // } - MPI_Request request; MPI_Igatherv( @@ -430,7 +429,6 @@ void update_impl( repart_comm->get(), &request ); - MPI_Wait(&request, MPI_STATUS_IGNORE); } }; diff --git a/src/StoppingCriterion.cpp b/src/StoppingCriterion.cpp index 38f9c13d..69afed10 100644 --- a/src/StoppingCriterion.cpp +++ b/src/StoppingCriterion.cpp @@ -44,9 +44,13 @@ StoppingCriterion::OpenFOAMDistStoppingCriterion::compute_normfactor_dist( auto Axref = gko::share( dist_vec::create(device_exec, comm, global_size, local_size)); Axref->fill(0.0); - + + auto start_axref = std::chrono::steady_clock::now(); compute_Axref_dist(global_size[0], local_size[0], device_exec, gkomatrix, x, Axref); + auto end_axref = std::chrono::steady_clock::now(); + auto delta_t_axref = std::chrono::duration_cast(end_axref-start_axref).count()/1.0; + // std::cout << __FILE__ << " delta_t_axref " << delta_t_axref << " [mu s]\n"; auto unity = gko::initialize>(1, {1.0}, device_exec); @@ -169,6 +173,7 @@ bool StoppingCriterion::OpenFOAMDistStoppingCriterion::check_impl( end_eval - start_eval) .count() / 1.0; + // std::cout << __FILE__ << "time " << *(parameters_.time) << " [mu s]\n"; return result; } From d0c11e9a06771cf50920deb051a5f25a32219355 Mon Sep 17 00:00:00 2001 From: Gregor Olenik Date: Wed, 6 Aug 2025 14:47:58 +0200 Subject: [PATCH 06/33] format files --- include/OGL/CommunicationPattern.hpp | 5 +- .../OGL/DevicePersistent/ExecutorHandler.hpp | 6 +- include/OGL/DevicePersistent/Vector.hpp | 80 +++++++++---------- include/OGL/StoppingCriterion.hpp | 40 +++++----- include/OGL/lduLduBase.hpp | 18 +++-- src/CommunicationPattern.cpp | 27 +++---- src/MatrixWrapper/Distributed.cpp | 63 +++++++-------- src/StoppingCriterion.cpp | 12 ++- 8 files changed, 127 insertions(+), 124 deletions(-) diff --git a/include/OGL/CommunicationPattern.hpp b/include/OGL/CommunicationPattern.hpp index 51f8e2db..64f1e221 100644 --- a/include/OGL/CommunicationPattern.hpp +++ b/include/OGL/CommunicationPattern.hpp @@ -22,8 +22,9 @@ struct AllToAllPattern { /* @brief computes AllToAllPattern for repart comm from global allToAll pattern * */ -AllToAllPattern compute_repart_allToall( - const ExecutorHandler &exec_handler, const AllToAllPattern allToAll, label start_rank); +AllToAllPattern compute_repart_allToall(const ExecutorHandler &exec_handler, + const AllToAllPattern allToAll, + label start_rank); /* @brief This function computes the send and recv counts vectors and the send * and recv offsets vectors for scattering from an owner to all ranks, including diff --git a/include/OGL/DevicePersistent/ExecutorHandler.hpp b/include/OGL/DevicePersistent/ExecutorHandler.hpp index 9197c940..ec91a5db 100644 --- a/include/OGL/DevicePersistent/ExecutorHandler.hpp +++ b/include/OGL/DevicePersistent/ExecutorHandler.hpp @@ -71,6 +71,8 @@ struct DeviceIdHandler { return device_global_id % num_devices_per_node; } + /* @brief returns the owner rank on the global comm world communicator + */ label global_owner() const { label rank = Pstream::myProcNo(); @@ -82,7 +84,7 @@ struct DeviceIdHandler { bool is_owner() const { label rank = Pstream::myProcNo(); - label owner_rank = rank - (rank % ranks_per_gpu); + label owner_rank = rank - (rank % ranks_per_gpu); bool is_owner = owner_rank == rank; return is_owner; } @@ -286,7 +288,7 @@ class ExecutorHandler MPI_Comm repart_comm; label global_rank = Pstream::myProcNo(); label device_id = global_rank / device_id_handler_.ranks_per_gpu; - MPI_Comm_split(MPI_COMM_WORLD, device_id, host_rank , &repart_comm); + MPI_Comm_split(MPI_COMM_WORLD, device_id, host_rank, &repart_comm); repart_comm_ = std::make_shared( repart_comm, gko_force_host_buffer_); diff --git a/include/OGL/DevicePersistent/Vector.hpp b/include/OGL/DevicePersistent/Vector.hpp index 311868bc..1b76273b 100644 --- a/include/OGL/DevicePersistent/Vector.hpp +++ b/include/OGL/DevicePersistent/Vector.hpp @@ -177,7 +177,7 @@ class PersistentVector auto rank = exec_.get_host_rank(); auto ref_exec = exec_.get_ref_exec(); auto comm = exec_.get_host_comm(); - auto repart_comm = exec_.get_repart_comm(); + auto repart_comm = exec_.get_repart_comm(); bool host_buffer = exec_.get_gko_force_host_buffer(); auto repartitioner = dist_matrix_->get_repartitioner(); @@ -187,57 +187,53 @@ class PersistentVector auto comm_pattern = compute_scatter_from_owner_counts( exec_, repartitioner->get_ranks_per_gpu(), host_size); - label owner_rank = exec_.get_owner_rank(); - auto repartAllToAll = compute_repart_allToall(exec_, comm_pattern, owner_rank); + label owner_rank = exec_.get_owner_rank(); + auto repartAllToAll = + compute_repart_allToall(exec_, comm_pattern, owner_rank); - // if (owner_rank != Pstream::myProcNo()){ - // label recv_count = repartAllToAll.recv_counts[0]; - // repartAllToAll.recv_counts[Pstream::myProcNo()] = recv_count; - // repartAllToAll.recv_counts[0] = 0; - // } + // if (owner_rank != Pstream::myProcNo()){ + // label recv_count = repartAllToAll.recv_counts[0]; + // repartAllToAll.recv_counts[Pstream::myProcNo()] = recv_count; + // repartAllToAll.recv_counts[0] = 0; + // } // communicate_values(exec, ref_exec, comm, comm_pattern, // get_vector()->get_local_values(), // const_cast(memory_), host_buffer); - // std::cout << __FILE__ - // << " owner_rank " << exec_.get_owner_rank() - // << " rank " << Pstream::myProcNo() - // << " comm_pattern.send_counts: " << comm_pattern.send_counts - // << " comm_pattern.recv_counts: " << comm_pattern.recv_counts - // << " send_counts: " << repartAllToAll.send_counts - // << " send_offsets: " << repartAllToAll.send_offsets - // << " recv_counts: " << repartAllToAll.recv_counts - // << "\n"; - - // auto start_rep = std::chrono::steady_clock::now(); + // std::cout << __FILE__ + // << " owner_rank " << exec_.get_owner_rank() + // << " rank " << Pstream::myProcNo() + // << " comm_pattern.send_counts: " << comm_pattern.send_counts + // << " comm_pattern.recv_counts: " << comm_pattern.recv_counts + // << " send_counts: " << repartAllToAll.send_counts + // << " send_offsets: " << repartAllToAll.send_offsets + // << " recv_counts: " << repartAllToAll.recv_counts + // << "\n"; + + // auto start_rep = std::chrono::steady_clock::now(); label send_size = comm_pattern.send_offsets.back(); - auto send_view = gko::array::const_view(exec, send_size, - get_vector()->get_local_values()); - auto tmp = gko::array(exec, send_size); + auto send_view = gko::array::const_view( + exec, send_size, get_vector()->get_local_values()); + auto tmp = gko::array(exec, send_size); - tmp = send_view; - tmp.set_executor(ref_exec); - // auto end_rep = std::chrono::steady_clock::now(); - // auto delta_t_rep = std::chrono::duration_cast(end_rep - start_rep).count() /1000.0; - // std::cout << __FILE__ << " copy back: " << delta_t_rep << " [ms]\n"; + tmp = send_view; + tmp.set_executor(ref_exec); + // auto end_rep = std::chrono::steady_clock::now(); + // auto delta_t_rep = + // std::chrono::duration_cast(end_rep - + // start_rep).count() /1000.0; std::cout << __FILE__ << " copy back: " + // << delta_t_rep << " [ms]\n"; MPI_Request copy_back_req; - MPI_Iscatterv( - tmp.get_data(), - //get_vector()->get_local_values(), - repartAllToAll.send_counts.data(), - repartAllToAll.send_offsets.data(), - MPI_DOUBLE, - const_cast(memory_), - repartAllToAll.recv_counts[0], - MPI_DOUBLE, - 0, - repart_comm->get(), - ©_back_req - ); - MPI_Wait(©_back_req,MPI_STATUS_IGNORE); - return copy_back_req; + MPI_Iscatterv(tmp.get_data(), + // get_vector()->get_local_values(), + repartAllToAll.send_counts.data(), + repartAllToAll.send_offsets.data(), MPI_DOUBLE, + const_cast(memory_), repartAllToAll.recv_counts[0], + MPI_DOUBLE, 0, repart_comm->get(), ©_back_req); + MPI_Wait(©_back_req, MPI_STATUS_IGNORE); + return copy_back_req; } /** Writes the content of the distributed vector to disk diff --git a/include/OGL/StoppingCriterion.hpp b/include/OGL/StoppingCriterion.hpp index fc2cfdae..b32cd791 100644 --- a/include/OGL/StoppingCriterion.hpp +++ b/include/OGL/StoppingCriterion.hpp @@ -174,7 +174,8 @@ class StoppingCriterion { norm_eval_limit_( controlDict.lookupOrDefault("normEvalLimit", label(100))), frequency_(controlDict.lookupOrDefault("evalFrequency", label(1))), - frequencyMode_(controlDict.lookupOrDefault("evalFrequencyMode", word("relative"))), // optimizer, fixed + frequencyMode_(controlDict.lookupOrDefault( + "evalFrequencyMode", word("relative"))), // optimizer, fixed relaxationFactor_( controlDict.lookupOrDefault("relaxationFactor", scalar(0.6))), adapt_minIter_( @@ -202,31 +203,32 @@ class StoppingCriterion { { label minIter = minIter_; label frequency = frequency_; - // in case of export_res all residuals need to be computed + // in case of export_res all residuals need to be computed std::cout << __FILE__ << "adapt minIter and frequency0 \n"; if (!export_res) { - std::cout << __FILE__ << "adapt minIter and frequency1 \n"; + std::cout << __FILE__ << "adapt minIter and frequency1 \n"; if (prev_solve_iters > 0 && adapt_minIter_ && prev_rel_cost > 0) { - std::cout << __FILE__ << "adapt minIter and frequency2 \n"; + std::cout << __FILE__ << "adapt minIter and frequency2 \n"; minIter = prev_solve_iters * relaxationFactor_; - if (frequencyMode_ == "optimizer") { - auto alpha = - sqrt(1.0 / (prev_solve_iters * (1.0 - relaxationFactor_)) * - prev_rel_cost); - frequency = min(norm_eval_limit_, max(1, label(1 / alpha))); - } - // if (frequencyMode_ == "relative") { - frequency = label(prev_solve_iters*0.075) + 1; - // } + if (frequencyMode_ == "optimizer") { + auto alpha = sqrt( + 1.0 / (prev_solve_iters * (1.0 - relaxationFactor_)) * + prev_rel_cost); + frequency = min(norm_eval_limit_, max(1, label(1 / alpha))); + } + // if (frequencyMode_ == "relative") { + frequency = label(prev_solve_iters * 0.075) + 1; + // } } } - word msg = "Creating stopping criterion with minIter " + std::to_string(minIter) - + " frequency " + std::to_string(frequency) - + " prev_solve_iters " + std::to_string(prev_solve_iters) + - + " adapt_minIter_ " + std::to_string(adapt_minIter_) + - + " prev_rel_cost " + std::to_string(prev_rel_cost) - + " prev_solve_iters*0.075 " + std::to_string(prev_solve_iters*0.075); + word msg = "Creating stopping criterion with minIter " + + std::to_string(minIter) + " frequency " + + std::to_string(frequency) + " prev_solve_iters " + + std::to_string(prev_solve_iters) + +" adapt_minIter_ " + + std::to_string(adapt_minIter_) + +" prev_rel_cost " + + std::to_string(prev_rel_cost) + " prev_solve_iters*0.075 " + + std::to_string(prev_solve_iters * 0.075); MLOG_0(verbose, msg) diff --git a/include/OGL/lduLduBase.hpp b/include/OGL/lduLduBase.hpp index c137b1e5..9bc5c0a8 100644 --- a/include/OGL/lduLduBase.hpp +++ b/include/OGL/lduLduBase.hpp @@ -306,13 +306,15 @@ class lduLduBase : public OGL_Info, delta_t_solve_ = delta_t_solve; } - // auto start_rep = std::chrono::steady_clock::now(); + // auto start_rep = std::chrono::steady_clock::now(); TIME_WITH_FIELDNAME(verbose_, copy_x_back, this->fieldName(), -dist_x.copy_back();) + dist_x.copy_back();) // auto copy_back_req = dist_x.copy_back(); - // auto end_rep = std::chrono::steady_clock::now(); - // auto delta_t_rep = std::chrono::duration_cast(end_rep - start_rep).count() /1000.0; - // std::cout << __FILE__ << " full copy back: " << delta_t_rep << " [ms]\n"; + // auto end_rep = std::chrono::steady_clock::now(); + // auto delta_t_rep = + // std::chrono::duration_cast(end_rep - + // start_rep).count() /1000.0; std::cout << __FILE__ << " full copy + // back: " << delta_t_rep << " [ms]\n"; auto bandwidth_copy_back = sizeof(scalar) * psi.size() / delta_t_copy_x_back / 1000.0; @@ -340,11 +342,11 @@ dist_x.copy_back();) std::to_string(time_per_dof) + std::string(" [ns]") + std::string("\n\tTime per iteration and DOF: ") + std::to_string(time_per_iter_and_dof) + std::string(" [ns]") + - std::string("\n\tRetrieve results bandwidth "); // + - std::to_string(bandwidth_copy_back) + std::string(" [GByte/s]"); + std::string("\n\tRetrieve results bandwidth "); // + + std::to_string(bandwidth_copy_back) + std::string(" [GByte/s]"); MLOG_0(verbose_, msg) - // MPI_Wait(©_back_req,MPI_STATUS_IGNORE); + // MPI_Wait(©_back_req,MPI_STATUS_IGNORE); return solverPerf; } diff --git a/src/CommunicationPattern.cpp b/src/CommunicationPattern.cpp index 8e39a052..46502464 100644 --- a/src/CommunicationPattern.cpp +++ b/src/CommunicationPattern.cpp @@ -179,32 +179,31 @@ void communicate_values(const ExecutorHandler &exec_handler, // } } -AllToAllPattern compute_repart_allToall( - const ExecutorHandler &exec_handler, const AllToAllPattern allToAllIn, label start_rank) - { +AllToAllPattern compute_repart_allToall(const ExecutorHandler &exec_handler, + const AllToAllPattern allToAllIn, + label start_rank) +{ auto host_comm = exec_handler.get_host_comm(); auto repart_comm = exec_handler.get_repart_comm(); auto ranks = repart_comm->size(); std::vector send_counts(ranks, 0); - std::vector send_offsets(ranks+1,0); + std::vector send_offsets(ranks + 1, 0); std::vector recv_counts(ranks, 0); - std::vector recv_offsets(ranks+1,0); + std::vector recv_offsets(ranks + 1, 0); // label start_rank = host_comm->rank(); - for (auto i=0;i src_exec, diff --git a/src/MatrixWrapper/Distributed.cpp b/src/MatrixWrapper/Distributed.cpp index 3f9bbafa..94448ed3 100644 --- a/src/MatrixWrapper/Distributed.cpp +++ b/src/MatrixWrapper/Distributed.cpp @@ -393,43 +393,40 @@ void update_impl( // perform all-to-all updates first auto all_to_all_update = [repart_comm, ref_exec, device_exec, - all_to_all_update_data, host_A, - force_host_buffer, exec_handler, rank]() { + all_to_all_update_data, host_A, force_host_buffer, + exec_handler, rank]() { for (auto [id, comm_pattern, data_ptr] : all_to_all_update_data) { - - // auto start = std::chrono::steady_clock::now(); - auto repartAllToAll = compute_repart_allToall(exec_handler, comm_pattern, rank); - // auto end = std::chrono::steady_clock::now(); - // auto delta_t = std::chrono::duration_cast(end - start).count()/1000.0; - // std::cout << __FILE__ << ":" << "delta t " << delta_t << " [ms]\n"; + // auto start = std::chrono::steady_clock::now(); + auto repartAllToAll = + compute_repart_allToall(exec_handler, comm_pattern, rank); + // auto end = std::chrono::steady_clock::now(); + // auto delta_t = + // std::chrono::duration_cast(end - + // start).count()/1000.0; std::cout << __FILE__ << ":" << "delta t " + // << delta_t << " [ms]\n"; auto [length, send_data_ptr] = host_A->get_interface_data(id); - // communicate_values(ref_exec, device_exec, repart_comm, repartAllToAll, + // communicate_values(ref_exec, device_exec, repart_comm, + // repartAllToAll, // send_data_ptr, data_ptr, force_host_buffer); - // if ( repart_comm->rank() == 0 ) { - // std::cout << __FILE__ << - // " Pstream::rank " << Pstream::myProcNo() << - // " repart_rank() " << repart_comm->rank() << - // " send_offsets.back() " << repartAllToAll.send_offsets.back() << - // " recv_counts: " << repartAllToAll.recv_counts << - // " recv_offsets: " << repartAllToAll.recv_offsets << - // std::endl; - // } - MPI_Request request; - - MPI_Igatherv( - send_data_ptr, - repartAllToAll.send_offsets.back(), - MPI_DOUBLE, - data_ptr, - repartAllToAll.recv_counts.data(), - repartAllToAll.recv_offsets.data(), - MPI_DOUBLE, - 0, - repart_comm->get(), - &request - ); - MPI_Wait(&request, MPI_STATUS_IGNORE); + // if ( repart_comm->rank() == 0 ) { + // std::cout << __FILE__ << + // " Pstream::rank " << Pstream::myProcNo() << + // " repart_rank() " << repart_comm->rank() << + // " send_offsets.back() " << + // repartAllToAll.send_offsets.back() << " recv_counts: " << + // repartAllToAll.recv_counts << " recv_offsets: " << + // repartAllToAll.recv_offsets << + // std::endl; + // } + MPI_Request request; + + MPI_Igatherv(send_data_ptr, repartAllToAll.send_offsets.back(), + MPI_DOUBLE, data_ptr, + repartAllToAll.recv_counts.data(), + repartAllToAll.recv_offsets.data(), MPI_DOUBLE, 0, + repart_comm->get(), &request); + MPI_Wait(&request, MPI_STATUS_IGNORE); } }; diff --git a/src/StoppingCriterion.cpp b/src/StoppingCriterion.cpp index 69afed10..76865bd2 100644 --- a/src/StoppingCriterion.cpp +++ b/src/StoppingCriterion.cpp @@ -44,13 +44,17 @@ StoppingCriterion::OpenFOAMDistStoppingCriterion::compute_normfactor_dist( auto Axref = gko::share( dist_vec::create(device_exec, comm, global_size, local_size)); Axref->fill(0.0); - + auto start_axref = std::chrono::steady_clock::now(); compute_Axref_dist(global_size[0], local_size[0], device_exec, gkomatrix, x, Axref); auto end_axref = std::chrono::steady_clock::now(); - auto delta_t_axref = std::chrono::duration_cast(end_axref-start_axref).count()/1.0; - // std::cout << __FILE__ << " delta_t_axref " << delta_t_axref << " [mu s]\n"; + auto delta_t_axref = std::chrono::duration_cast( + end_axref - start_axref) + .count() / + 1.0; + // std::cout << __FILE__ << " delta_t_axref " << delta_t_axref << " [mu + // s]\n"; auto unity = gko::initialize>(1, {1.0}, device_exec); @@ -173,7 +177,7 @@ bool StoppingCriterion::OpenFOAMDistStoppingCriterion::check_impl( end_eval - start_eval) .count() / 1.0; - // std::cout << __FILE__ << "time " << *(parameters_.time) << " [mu s]\n"; + // std::cout << __FILE__ << "time " << *(parameters_.time) << " [mu s]\n"; return result; } From aa977a11f71707b919887f09fe2aa0bcaff30644 Mon Sep 17 00:00:00 2001 From: Gregor Olenik Date: Wed, 6 Aug 2025 16:51:13 +0200 Subject: [PATCH 07/33] use optimizer as default --- .../OGL/DevicePersistent/ExecutorHandler.hpp | 2 ++ include/OGL/StoppingCriterion.hpp | 18 +++++++----------- src/MatrixWrapper/Distributed.cpp | 1 - test/unit/MatrixWrapper/Distributed.cpp | 12 ++++++++++++ 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/include/OGL/DevicePersistent/ExecutorHandler.hpp b/include/OGL/DevicePersistent/ExecutorHandler.hpp index ec91a5db..4ee8382e 100644 --- a/include/OGL/DevicePersistent/ExecutorHandler.hpp +++ b/include/OGL/DevicePersistent/ExecutorHandler.hpp @@ -311,6 +311,8 @@ class ExecutorHandler label get_ranks_per_gpu() const { return device_id_handler_.ranks_per_gpu; } + void set_ranks_per_gpu(label ranks_per_gpu) { device_id_handler_.ranks_per_gpu= ranks_per_gpu; } + label get_owner_rank() const { return device_id_handler_.global_owner(); } const std::shared_ptr get_device_exec() const diff --git a/include/OGL/StoppingCriterion.hpp b/include/OGL/StoppingCriterion.hpp index b32cd791..944acd60 100644 --- a/include/OGL/StoppingCriterion.hpp +++ b/include/OGL/StoppingCriterion.hpp @@ -201,34 +201,30 @@ class StoppingCriterion { bool export_res, label prev_solve_iters, scalar prev_rel_cost) const { + word frequencyMode = "optimizer"; label minIter = minIter_; label frequency = frequency_; // in case of export_res all residuals need to be computed - std::cout << __FILE__ << "adapt minIter and frequency0 \n"; if (!export_res) { - std::cout << __FILE__ << "adapt minIter and frequency1 \n"; if (prev_solve_iters > 0 && adapt_minIter_ && prev_rel_cost > 0) { - std::cout << __FILE__ << "adapt minIter and frequency2 \n"; minIter = prev_solve_iters * relaxationFactor_; - if (frequencyMode_ == "optimizer") { + if (frequencyMode == "optimizer") { auto alpha = sqrt( 1.0 / (prev_solve_iters * (1.0 - relaxationFactor_)) * prev_rel_cost); frequency = min(norm_eval_limit_, max(1, label(1 / alpha))); } - // if (frequencyMode_ == "relative") { - frequency = label(prev_solve_iters * 0.075) + 1; - // } + if (frequencyMode == "relative") { + frequency = label(prev_solve_iters * 0.075) + 1; + } } } word msg = "Creating stopping criterion with minIter " + std::to_string(minIter) + " frequency " + std::to_string(frequency) + " prev_solve_iters " + - std::to_string(prev_solve_iters) + +" adapt_minIter_ " + - std::to_string(adapt_minIter_) + +" prev_rel_cost " + - std::to_string(prev_rel_cost) + " prev_solve_iters*0.075 " + - std::to_string(prev_solve_iters * 0.075); + std::to_string(prev_solve_iters) + " adapt_minIter_ " + + std::to_string(adapt_minIter_) + " prev_rel_cost "; MLOG_0(verbose, msg) diff --git a/src/MatrixWrapper/Distributed.cpp b/src/MatrixWrapper/Distributed.cpp index 94448ed3..f134d145 100644 --- a/src/MatrixWrapper/Distributed.cpp +++ b/src/MatrixWrapper/Distributed.cpp @@ -527,7 +527,6 @@ std::shared_ptr create_impl( label rank = exec_handler.get_host_rank(); auto exec = exec_handler.get_ref_exec(); auto host_comm = *exec_handler.get_host_comm().get(); - exec_handler.init_device_comm(); auto device_comm = *exec_handler.get_device_comm().get(); bool owner = repartitioner->is_owner(exec_handler); diff --git a/test/unit/MatrixWrapper/Distributed.cpp b/test/unit/MatrixWrapper/Distributed.cpp index 496a6c0c..272d5347 100644 --- a/test/unit/MatrixWrapper/Distributed.cpp +++ b/test/unit/MatrixWrapper/Distributed.cpp @@ -56,6 +56,7 @@ class Environment : public testing::Environment { Foam::IOobject::MUST_READ), false); + // FIXME this needs the device_id_handler exec = std::make_shared(runTime_->thisDb(), dict, "dummy", true); @@ -172,6 +173,7 @@ TEST_P(DistMatL2D, canCreateDistributedMatrix) { /* The test mesh is 6x6 grid decomposed into 4 3x3 subdomains */ auto [ranks_per_gpu, matrix_format, fused] = GetParam(); + exec.set_ranks_per_gpu(ranks_per_gpu); auto mesh = ((Environment *)global_env)->mesh; auto hostMatrix = ((Environment *)global_env)->hostMatrix; @@ -182,6 +184,7 @@ TEST_P(DistMatL2D, canCreateDistributedMatrix) gko::dim<2> global_vec_dim{repartitioner->get_orig_partition()->get_size(), 1}; gko::dim<2> local_vec_dim{repartitioner->get_repart_dim()[0], 1}; + exec.init_device_comm(); auto distributed = create_distributed(exec, repartitioner, hostMatrix, matrix_format, fused, 0); @@ -200,6 +203,8 @@ TEST_P(DistMatL2D, hasCorrectLocalMatrix) { /* The test mesh is 6x6 grid decomposed into 4 3x3 subdomains */ auto [ranks_per_gpu, matrix_format, fused] = GetParam(); + exec.set_ranks_per_gpu(ranks_per_gpu); + exec.init_device_comm(); auto mesh = ((Environment *)global_env)->mesh; auto hostMatrix = ((Environment *)global_env)->hostMatrix; auto repartitioner = std::make_shared( @@ -254,6 +259,8 @@ TEST_P(DistMatL2D, hasCorrectNonLocalMatrix) { /* The test mesh is 6x6 grid decomposed into 4 3x3 subdomains */ auto [ranks_per_gpu, matrix_format, fused] = GetParam(); + exec.set_ranks_per_gpu(ranks_per_gpu); + exec.init_device_comm(); auto mesh = ((Environment *)global_env)->mesh; auto hostMatrix = ((Environment *)global_env)->hostMatrix; auto name = ((Environment *)global_env)->name_; @@ -292,6 +299,8 @@ TEST_P(DistMatL2D, hasCorrectNonLocalMatrix) TEST_P(DistMatL2D, canApplyCorrectly) { auto [ranks_per_gpu, format, fused] = GetParam(); + exec.set_ranks_per_gpu(ranks_per_gpu); + exec.init_device_comm(); auto mesh = ((Environment *)global_env)->mesh; auto hostMatrix = ((Environment *)global_env)->hostMatrix; auto name = ((Environment *)global_env)->name_; @@ -314,12 +323,15 @@ TEST_P(DistMatL2D, canApplyCorrectly) x->fill(0); // Act + bool active = repartitioner->get_repart_size() != 0; + if (active){ distributed->apply(b, x); auto res_x = std::vector( x->get_local_vector()->get_const_values(), x->get_local_vector()->get_const_values() + local_vec_dim[0]); ASSERT_EQ(res_x, exp_x[name][fused][ranks_per_gpu][rank]); + } } int main(int argc, char *argv[]) From 11509bc99afb401869b5542f03bc4d22042ce318 Mon Sep 17 00:00:00 2001 From: Gregor Olenik Date: Thu, 7 Aug 2025 17:44:38 +0200 Subject: [PATCH 08/33] WIP, avoid symmetric MPI_Igatherv --- include/OGL/.Preconditioner.hpp.swn | Bin 16384 -> 0 bytes include/OGL/.Preconditioner.hpp.swo | Bin 16384 -> 0 bytes .../OGL/DevicePersistent/ExecutorHandler.hpp | 5 +- include/OGL/DevicePersistent/Vector.hpp | 16 +---- include/OGL/StoppingCriterion.hpp | 4 -- include/OGL/lduLduBase.hpp | 14 +--- src/MatrixWrapper/Distributed.cpp | 63 +++++++++--------- test/unit/MatrixWrapper/Distributed.cpp | 12 ++-- 8 files changed, 46 insertions(+), 68 deletions(-) delete mode 100644 include/OGL/.Preconditioner.hpp.swn delete mode 100644 include/OGL/.Preconditioner.hpp.swo diff --git a/include/OGL/.Preconditioner.hpp.swn b/include/OGL/.Preconditioner.hpp.swn deleted file mode 100644 index 6793705a6f00ad2117ddacb5b1735306a1af1c01..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmeHN-)|hn9iO(L1WG7sA9&$ma!BP)v3(Z@hiKziRqZ;swXsP;04Zph+nu}HcyD(* zJ7=Fs)1pfJ2c@n0Pzk|PrAn>TAL1#9N9ao{KnNrxeh4ZdfdqYODeY%=X7_g2mjjPu*EZ;hxp{)?HbVZ$&J7L^?t1+FwR;Hv-rb#J$CcpU zUp<-3j!ztq=I6rLW1$}pSrAPz`GI!W_L*dDFZOvm?uYFl^1>0mZ=POnZwctB1|y1ZB;%YbFTGGH073|Iy%1C{~H zfMwu+lL46=BtJyxUo_!&&F2?tpZ_%1Idk8u$v-vn4RikwHTge`{EWGOz%-Dz^NEq) zYvku^^1mDT{YL(an*47@e!<8;tjWKWw`)GXYdV~_Z*JQU%YbFTGGH073|Iy%1C{~H zfMvikU>UFs{9iJ_d_um7p1q?s!ubDxzW;yetAzXscm{YH_zCbNFa~yk`+&m$1r7m! zy_JxUfwzDcfv12JI01Zeh>$-6zXYBD9sw4BTY=YZA>;+%5^xNd2U@^E;6~stUm@f@ z;5pz5@H612z-8e3fCP>JZ{AGEZ-J+P$AJalX5fRHU=O?tTmhZ{wtzc;R}K>Ld*Ii= z7+3&q01g1p-bl#Lfro)xfRDaR$gcnfJPOIaY zNklVQWF#~@%b|a?mBn(*M9R;=>||jT^k}mejJdCcQ4sZ8^b)e7cFo06)8{*Z$6Y?= zUaK{6QPZSzyMY|Ig8L&+odR)t%#*Qbrg6B#?~BE7xz*a|Uis*6$BvWAIB}daJPrI2 z3zhm}iW4bJEICeh6oh{Bn#OCA3#M8wEObOeHg*HZ(k8wsCEexL%)V%}z9*D+z?xT) zCzYcvP5d-n-K&O}bzBs|6yCDI^0F~;wGKUHNEk4|o7Xi6ldg6#{M&9CJjR|VS|*rm=QXu;A#PY0k=Pxq?Sk&X4u({87^!$mhvxjRFL zX}{W{3Jq5(eaDfpn@XV~(=0v6gZ@BH&%ByJb%f~=+PDy1kP|m@(4a?1)>QRR%}*(5 zb0-zo^fS6CPrg>}N$~JoY-Z(WbhK}(nx0i=cg5FkEPO>XhN*Fy<4hKloDN5!3~0!A zct}%ku*<|_jv}b$K66yCl;vx+_ot|j6JzoADA^P%yvN|S*{G;AW@yN|JZvs>>NR7E zX;C!v)I6(7hA3Pd<+I1jPIM(K%1WsgmZp|Y8uWfjbCY}+NVK90O|vuCIa+Q;CCEPG z#j~h#-e9TOsBs2AJr<_Cl%`oUHMM%M)d8FuZAGOZWkH2njL|5?bfL9slCkJG%l*8R zPHMN-?|FIU$r7V40?fYE>Z)LD&2TQ&T_pYC6dzmtynI*fE)@Z1$x&LVS`^0zQ(4Hf z`IxGD=(~v&i{^acYPP2AEm2d1XS5mhgKW)VVvl~qpA`1Gmu#u|Hr6q$rDBPe7PhO~ zWO3>GydFfG$&&g$WGGN$Z8WtJqq-|t;%4N!*{pNTtkY|Y@rMgf()^y zFIZWSZ8R&AwU%=qarYwkdug4)C~jA(W9bWRGMBl9{L{WPbi{S)ip7kWD8(PVlreY{CiYRS{jl%@b~s8vrDH(k8)+P6;+g|ZjMOqw2QJ#U(t zc{DBi3uMu3_9$CCjaHOIp=4rP6V>9Z8x4xWT&Hl&TdaiVcQ58H>#E;jUfc~9{TNBh zt995=a828cj%lXXw5$XZZk6t-1L_-D#eNX=80p$xnWU*Yt6p}XlvlDH&ldI! z&_iaozr|9n6(?>N`$4qbkK6h~Nte)QB3OUOXdHQ*kanA%-CB8Qb{+etDCM(jKAZ); zfD4D7-ddkMHrJVr#jIKb1e6Q?)ga`{ak3}WgYP*$mJXfo%->BBo7(FQVv!QH|Nk-e z@6Q2h|BvlzcD;e$uL3U{*%c+Xmu0{*U>UFsSOzQumI2FvWxz6E8L$jk1}p>r6$UO- iiq`|xcO2xhep@to-z&HriHP>ie{k?JT>tm+B>5MH00&|K diff --git a/include/OGL/.Preconditioner.hpp.swo b/include/OGL/.Preconditioner.hpp.swo deleted file mode 100644 index 59f5bb35988ed3c6ebd5b633ff6bf04be8b770a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmeHOTa4UR89wPPEHvd(5agkfyQv}%*`1kON`f=H5^UJ8G?yi9LZvn`9{bFUvmV>A zJ-f3Ffxht42MVodLE?oZedz-Qo@jUgfp`Iml&F=siR%O6iH9I0AY8t48y|aSv)u?G zA#CYedwl-$pZ|R4Kj--W?QJ*DEFCuv)%Ot`?;zx-uPydoeeSNOzjn_yt;1HI@_VMxp0t zeiYKA-izajimICx0~G^XV_=YVW)JN+y?@`{Cabt>`a$FVcb(pvj!L>>pkkn6pkkn6 zpkkn6pkkn6pkm;Ent?3dPCkPk+#!3hBG21O=YPrLjJ)43mH$(gFU$MiFO~m8mYI1(8t^!X3j{xrle)ASWehyp$ zIsgS81`Yr_fxm1gRR>0X_-L0WIL2z>n`D z|UIwlJmw`_KCjd5XzebYd zSCbPRhCI^Dv#hk|B-FFxENS5@i!?L3E0JX#^TU(zJiG2YS>g|82&7g=iy^GF7m(ZN*%NFU5bxH zP}dyUUaK7@s$8AxQD}N})pw~)ht#c&3#|EB&vqjxNvWMi!75G6!mk>cnyPc5V6UC_ zqbTb^q~ioB-9%eJS7~6z-M-y%Hf))HHlrGj#TPI|y@``rR(s$Fo|zXUG#ezL7(+g? zCV`z(U;uwR?x=#WJYDg@e3WE<*fq0cKx^W@>}V3LrDjS4n_bj4q|6y)ks-Td%oW<6 zQnl+T%{bGLO$yAzvWqZoB-n)@`xeNoJ>j2)x^L_LUm*hr5rQMxo=XBc^Hbah2IT$+Jl*LIyWYjNraewgjwHxFvZ zyE&$8eCiWTMxVs(a~t#>q$#3}x!msuDOM9hur^|ZFQAsS&{YnHi83W5JFb%I4}#3^ zCO&qhMSn=W1-|-*P$z567-GieWC;~md?x5v?ke{#*1It3X?YtfZ8C;hcMZNXZdi@8 zua=E@Lz^l2L@775`Chx(j>*}w`DSu^yXOUc`^5g%jj)MU3V95mDy%b4KTHMLlf3)7GvT0d?|I3bz^t23o~N;h4UE&f~3c&g+pjsixRJF ziqa9a&rvr!MZ12Qv6j5{42cKrz;`V%g@g+3=c*}N?kbzvS(FnhCbC%2H*Qf;&!pZ! zB2N5O?2giEjm<4zmgh8|PIMS!2k6r#UCz%& z&GHR=w7V9Bl97;HY?qRJvCTX0kCxjqk4tW=V4l}Lr&N|jKjyem+i!UhJeL+%S4qL9 zbvYfAs%~1dU}QfVDkH_j$0n0%9d`pKO;z+Dr>Sv)u+<@r9hVx5k<-TwvP*t)ZcHb% zyL3{_iuy;VwSvy-!r~EjOS{KDP(RK?q)#A>fzLLM0Pg|b z4ctIX{t|EncpTUP+zVVozpetW0xtqz06qt>{tkias2Hdis2Hdi_%AbX(J-*D6*p&c zQ9S14(TYlP$xI)Tmm)tVA8XmOP8^BU4APoN3K4dT9Z)_LBlchZ+OfNEUhKajnqsrvIuuI~5wHgW5z&h*tf`(x z%-G3#GX~-w#4$v-#1DP+sPKPswvQaD$*AO^2M^t5SX?h2lb}XRf94Ev)5dJq<9i-a zuxBoi7~=T>83-Q1m18YiSemP5DZtGuz*?ctW&uFtX|%B(BL?DKDTkFRmp3hIBc5z( zRrRQ35Q6=0SPqSUEeiLe7y$Mvt6eyn^rrF?38NYC*@U8qK=$ zRdj~%7D|7%Ji@B}Mk8%(=uG1V{6~gV8FZUNt5wI_i#+PZ{U*DX&W6*t&lDY1 z)tr1+mCnu&V&v7S%8#r%!GOOcVX?JX6DD*{)#fp|lZs{OG*={|o-<6%ya_Y)jFGB# zi~i*z`IT6+MK)KMWKMc{lUK;EMA$6jNflP|)V|g~lFLuNDs=M}DG1T`;z*V?P9}Uq z6ADdFU|7#_*T!d}-nvqSyoVSWomY{$xFxULqxJUS(L8_2S5Z5TkZ7ifmU))@)Wp8| z9m8aA@r=1SV_K$arfV$X)=k#0H(CeGX{HAYJIhF!xvmY|mglWR%ahw;ma#Wm%(7mC^761SM diff --git a/include/OGL/DevicePersistent/ExecutorHandler.hpp b/include/OGL/DevicePersistent/ExecutorHandler.hpp index 4ee8382e..df56b32f 100644 --- a/include/OGL/DevicePersistent/ExecutorHandler.hpp +++ b/include/OGL/DevicePersistent/ExecutorHandler.hpp @@ -311,7 +311,10 @@ class ExecutorHandler label get_ranks_per_gpu() const { return device_id_handler_.ranks_per_gpu; } - void set_ranks_per_gpu(label ranks_per_gpu) { device_id_handler_.ranks_per_gpu= ranks_per_gpu; } + void set_ranks_per_gpu(label ranks_per_gpu) + { + device_id_handler_.ranks_per_gpu = ranks_per_gpu; + } label get_owner_rank() const { return device_id_handler_.global_owner(); } diff --git a/include/OGL/DevicePersistent/Vector.hpp b/include/OGL/DevicePersistent/Vector.hpp index 1b76273b..2f54a4f4 100644 --- a/include/OGL/DevicePersistent/Vector.hpp +++ b/include/OGL/DevicePersistent/Vector.hpp @@ -171,7 +171,7 @@ class PersistentVector /** Copies the content of the distributed vector back to the original source **/ - MPI_Request copy_back() + void copy_back() { auto exec = exec_.get_device_exec(); auto rank = exec_.get_host_rank(); @@ -191,12 +191,6 @@ class PersistentVector auto repartAllToAll = compute_repart_allToall(exec_, comm_pattern, owner_rank); - // if (owner_rank != Pstream::myProcNo()){ - // label recv_count = repartAllToAll.recv_counts[0]; - // repartAllToAll.recv_counts[Pstream::myProcNo()] = recv_count; - // repartAllToAll.recv_counts[0] = 0; - // } - // communicate_values(exec, ref_exec, comm, comm_pattern, // get_vector()->get_local_values(), // const_cast(memory_), host_buffer); @@ -210,7 +204,6 @@ class PersistentVector // << " recv_counts: " << repartAllToAll.recv_counts // << "\n"; - // auto start_rep = std::chrono::steady_clock::now(); label send_size = comm_pattern.send_offsets.back(); auto send_view = gko::array::const_view( exec, send_size, get_vector()->get_local_values()); @@ -218,12 +211,6 @@ class PersistentVector tmp = send_view; tmp.set_executor(ref_exec); - // auto end_rep = std::chrono::steady_clock::now(); - // auto delta_t_rep = - // std::chrono::duration_cast(end_rep - - // start_rep).count() /1000.0; std::cout << __FILE__ << " copy back: " - // << delta_t_rep << " [ms]\n"; - MPI_Request copy_back_req; MPI_Iscatterv(tmp.get_data(), @@ -233,7 +220,6 @@ class PersistentVector const_cast(memory_), repartAllToAll.recv_counts[0], MPI_DOUBLE, 0, repart_comm->get(), ©_back_req); MPI_Wait(©_back_req, MPI_STATUS_IGNORE); - return copy_back_req; } /** Writes the content of the distributed vector to disk diff --git a/include/OGL/StoppingCriterion.hpp b/include/OGL/StoppingCriterion.hpp index 944acd60..af20a36d 100644 --- a/include/OGL/StoppingCriterion.hpp +++ b/include/OGL/StoppingCriterion.hpp @@ -147,8 +147,6 @@ class StoppingCriterion { const label frequency_; - const word frequencyMode_; - const scalar relaxationFactor_; const bool adapt_minIter_; @@ -174,8 +172,6 @@ class StoppingCriterion { norm_eval_limit_( controlDict.lookupOrDefault("normEvalLimit", label(100))), frequency_(controlDict.lookupOrDefault("evalFrequency", label(1))), - frequencyMode_(controlDict.lookupOrDefault( - "evalFrequencyMode", word("relative"))), // optimizer, fixed relaxationFactor_( controlDict.lookupOrDefault("relaxationFactor", scalar(0.6))), adapt_minIter_( diff --git a/include/OGL/lduLduBase.hpp b/include/OGL/lduLduBase.hpp index 9bc5c0a8..0734b4a5 100644 --- a/include/OGL/lduLduBase.hpp +++ b/include/OGL/lduLduBase.hpp @@ -306,16 +306,8 @@ class lduLduBase : public OGL_Info, delta_t_solve_ = delta_t_solve; } - // auto start_rep = std::chrono::steady_clock::now(); TIME_WITH_FIELDNAME(verbose_, copy_x_back, this->fieldName(), dist_x.copy_back();) - // auto copy_back_req = dist_x.copy_back(); - // auto end_rep = std::chrono::steady_clock::now(); - // auto delta_t_rep = - // std::chrono::duration_cast(end_rep - - // start_rep).count() /1000.0; std::cout << __FILE__ << " full copy - // back: " << delta_t_rep << " [ms]\n"; - auto bandwidth_copy_back = sizeof(scalar) * psi.size() / delta_t_copy_x_back / 1000.0; @@ -342,12 +334,10 @@ class lduLduBase : public OGL_Info, std::to_string(time_per_dof) + std::string(" [ns]") + std::string("\n\tTime per iteration and DOF: ") + std::to_string(time_per_iter_and_dof) + std::string(" [ns]") + - std::string("\n\tRetrieve results bandwidth "); // + - std::to_string(bandwidth_copy_back) + std::string(" [GByte/s]"); + std::string("\n\tRetrieve results bandwidth "); + std::to_string(bandwidth_copy_back) + std::string(" [GByte/s]"); MLOG_0(verbose_, msg) - // MPI_Wait(©_back_req,MPI_STATUS_IGNORE); - return solverPerf; } diff --git a/src/MatrixWrapper/Distributed.cpp b/src/MatrixWrapper/Distributed.cpp index f134d145..2511d7b7 100644 --- a/src/MatrixWrapper/Distributed.cpp +++ b/src/MatrixWrapper/Distributed.cpp @@ -121,13 +121,15 @@ void generate_alltoall_update_data( std::vector &update_data) { label linop_offset_store{0}; - for (size_t i = 0; i < 3; i++) { + // NOTE in case of symmetric matrix 0 (upper) is same as 1 (lower) + // thus we can start at 1 + label start = 0; + for (size_t i = start; i < 3; i++) { label interface_size = in->get_rows()[i].size(); label linop_idx = (fuse) ? 0 : in->get_id()[i]; label linop_offset = (fuse) ? linop_offset_store : 0; auto comm_pattern = compute_gather_to_owner_counts( exec_handler, ranks_per_owner, interface_size); - size_t recv_size = comm_pattern.recv_offsets.back(); // NOTE Probably dont need to store linops[linop-idx] because we can @@ -395,38 +397,40 @@ void update_impl( auto all_to_all_update = [repart_comm, ref_exec, device_exec, all_to_all_update_data, host_A, force_host_buffer, exec_handler, rank]() { + // NOTE if symmetric (get it from host_A) we can skip id=0 and wait till + // id=1 has been copied to use device copy for (auto [id, comm_pattern, data_ptr] : all_to_all_update_data) { - // auto start = std::chrono::steady_clock::now(); auto repartAllToAll = compute_repart_allToall(exec_handler, comm_pattern, rank); - // auto end = std::chrono::steady_clock::now(); - // auto delta_t = - // std::chrono::duration_cast(end - - // start).count()/1000.0; std::cout << __FILE__ << ":" << "delta t " - // << delta_t << " [ms]\n"; auto [length, send_data_ptr] = host_A->get_interface_data(id); - // communicate_values(ref_exec, device_exec, repart_comm, - // repartAllToAll, - // send_data_ptr, data_ptr, force_host_buffer); - // if ( repart_comm->rank() == 0 ) { - // std::cout << __FILE__ << - // " Pstream::rank " << Pstream::myProcNo() << - // " repart_rank() " << repart_comm->rank() << - // " send_offsets.back() " << - // repartAllToAll.send_offsets.back() << " recv_counts: " << - // repartAllToAll.recv_counts << " recv_offsets: " << - // repartAllToAll.recv_offsets << - // std::endl; - // } - MPI_Request request; - - MPI_Igatherv(send_data_ptr, repartAllToAll.send_offsets.back(), - MPI_DOUBLE, data_ptr, - repartAllToAll.recv_counts.data(), - repartAllToAll.recv_offsets.data(), MPI_DOUBLE, 0, - repart_comm->get(), &request); - MPI_Wait(&request, MPI_STATUS_IGNORE); + if (id == 0 && host_A->get_symmetric()) { + // if symmetric we can skip id ==0 since it is the same as id==1 + } else { + MPI_Request request; + MPI_Igatherv(send_data_ptr, repartAllToAll.send_offsets.back(), + MPI_DOUBLE, data_ptr, + repartAllToAll.recv_counts.data(), + repartAllToAll.recv_offsets.data(), MPI_DOUBLE, 0, + repart_comm->get(), &request); + MPI_Wait(&request, MPI_STATUS_IGNORE); + } + + // Perform symmetric inter device copy + if (id == 1 && repart_comm->rank() == 0 && + host_A->get_symmetric()) { + auto [zid, zcomm_pattern, zdata_ptr] = + all_to_all_update_data[0]; + // copy recv size data from data_ptr to zdata_ptr + label recv_buffer_size = repartAllToAll.recv_offsets.back(); + auto l_view = gko::array::view( + device_exec, recv_buffer_size, data_ptr); + + auto u_view = gko::array::view( + device_exec, recv_buffer_size, zdata_ptr); + + u_view = l_view; + } } }; @@ -442,7 +446,6 @@ void update_impl( } }; - // perform pairwise communications // this update interface data which needs communication auto pairwise_communicate = [comm, ref_exec, device_exec, diff --git a/test/unit/MatrixWrapper/Distributed.cpp b/test/unit/MatrixWrapper/Distributed.cpp index 272d5347..31b055f8 100644 --- a/test/unit/MatrixWrapper/Distributed.cpp +++ b/test/unit/MatrixWrapper/Distributed.cpp @@ -324,13 +324,13 @@ TEST_P(DistMatL2D, canApplyCorrectly) // Act bool active = repartitioner->get_repart_size() != 0; - if (active){ - distributed->apply(b, x); - auto res_x = std::vector( - x->get_local_vector()->get_const_values(), - x->get_local_vector()->get_const_values() + local_vec_dim[0]); + if (active) { + distributed->apply(b, x); + auto res_x = std::vector( + x->get_local_vector()->get_const_values(), + x->get_local_vector()->get_const_values() + local_vec_dim[0]); - ASSERT_EQ(res_x, exp_x[name][fused][ranks_per_gpu][rank]); + ASSERT_EQ(res_x, exp_x[name][fused][ranks_per_gpu][rank]); } } From 63cec6ff1963ad78395356c660e9692836866474 Mon Sep 17 00:00:00 2001 From: Gregor Olenik Date: Tue, 26 Aug 2025 08:46:00 +0200 Subject: [PATCH 09/33] wip move preconditioner to separate implementation files --- include/OGL/Preconditioner.hpp | 805 ++++++++---------- include/OGL/Preconditioner/Jacobi.hpp | 73 ++ include/OGL/Preconditioner/Multigrid.hpp | 281 ++++++ .../Preconditioner/PreconditionerWrapper.hpp | 32 + include/OGL/Preconditioner/Schwarz.hpp | 122 +++ 5 files changed, 842 insertions(+), 471 deletions(-) create mode 100644 include/OGL/Preconditioner/Jacobi.hpp create mode 100644 include/OGL/Preconditioner/Multigrid.hpp create mode 100644 include/OGL/Preconditioner/PreconditionerWrapper.hpp create mode 100644 include/OGL/Preconditioner/Schwarz.hpp diff --git a/include/OGL/Preconditioner.hpp b/include/OGL/Preconditioner.hpp index 03533486..ddbd9e5e 100644 --- a/include/OGL/Preconditioner.hpp +++ b/include/OGL/Preconditioner.hpp @@ -8,11 +8,16 @@ #include "OGL/DevicePersistent/Base.hpp" #include "OGL/MatrixWrapper/Distributed.hpp" +#include "OGL/Preconditioner/Jacobi.hpp" +#include "OGL/Preconditioner/Schwarz.hpp" +#include "OGL/Preconditioner/Multigrid.hpp" #include "fvCFD.H" #include "regIOobject.H" namespace Foam { + + class Preconditioner { using mtx = gko::matrix::Csr; using bj = gko::preconditioner::Jacobi; @@ -52,110 +57,6 @@ class Preconditioner { verbose_(verbose) {} - template - std::shared_ptr wrap_multi_level_schwarz( - std::shared_ptr gkomatrix, - std::shared_ptr device_exec, - std::shared_ptr precond, const dictionary &d, - label local_rows) const - { - using pgm = gko::multigrid::Pgm; - using fc = gko::multigrid::FixedCoarsening; - using solver = gko::solver::Cg; - - auto selCoarseRows = d.lookupOrDefault("selCoarseRows", label(5)); - auto fixedCoarsening = - d.lookupOrDefault("fixedCoarsening", false); - auto coarseWeight = d.lookupOrDefault("coarseWeight", scalar(0.01)); - auto solveNormC = - d.lookupOrDefault("reductionCoarseSolver", label(1e-6)); - auto maxIterCoarse = d.lookupOrDefault("maxIterCoarse", label(50)); - - word msg = "Generate multi level schwarz:\n\tfixedCoarsening " + - std::to_string(fixedCoarsening) + "\n\tselCoarseRows " + - std::to_string(selCoarseRows) + "\n\trelTolCoarse " + - std::to_string(solveNormC) + "\n\tmaxIterCoarse " + - std::to_string(maxIterCoarse) + "\n\tcoarseWeigth" + - std::to_string(coarseWeight); - MLOG_0(verbose_, msg) - - auto pre_factory = ras::build().with_local_solver( - bj::build().with_skip_sorting(true).with_max_block_size(1u).on( - device_exec)); - - auto coarse_solver = gko::share( - solver::build() - .with_preconditioner(pre_factory) - .with_criteria( - gko::stop::Iteration::build().with_max_iters(maxIterCoarse), - gko::stop::ResidualNorm::build() - .with_reduction_factor(solveNormC)) - .on(device_exec)); - - if (fixedCoarsening) { - auto n_rows = local_rows / selCoarseRows; - auto sel_rows = - gko::array