mirror of
https://github.com/fverdugo/XM_40017.git
synced 2025-11-09 00:24:25 +01:00
build based on cd63aed
This commit is contained in:
parent
37e14fedd6
commit
f23cd2ee39
@ -1 +1 @@
|
||||
{"documenter":{"julia_version":"1.10.5","generation_timestamp":"2024-09-09T15:08:46","documenter_version":"1.7.0"}}
|
||||
{"documenter":{"julia_version":"1.10.5","generation_timestamp":"2024-09-11T08:58:10","documenter_version":"1.7.0"}}
|
||||
@ -14,4 +14,4 @@
|
||||
var myIframe = document.getElementById("notebook");
|
||||
iFrameResize({log:true}, myIframe);
|
||||
});
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
@ -14,4 +14,4 @@
|
||||
var myIframe = document.getElementById("notebook");
|
||||
iFrameResize({log:true}, myIframe);
|
||||
});
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
@ -15,4 +15,4 @@ DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
|
||||
MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195"</code></pre><p>Copy the contents of previous code block into a file called <code>Project.toml</code> and place it in an empty folder named <code>newproject</code>. It is important that the file is named <code>Project.toml</code>. You can create a new folder from the REPL with</p><pre><code class="language-julia hljs">julia> mkdir("newproject")</code></pre><p>To install all the packages registered in this file you need to activate the folder containing your <code>Project.toml</code> file</p><pre><code class="language-julia hljs">(@v1.10) pkg> activate newproject</code></pre><p>and then <em>instantiating</em> it</p><pre><code class="language-julia hljs">(newproject) pkg> instantiate</code></pre><p>The instantiate command will download and install all listed packages and their dependencies in just one click.</p><h3 id="Getting-help-in-package-mode"><a class="docs-heading-anchor" href="#Getting-help-in-package-mode">Getting help in package mode</a><a id="Getting-help-in-package-mode-1"></a><a class="docs-heading-anchor-permalink" href="#Getting-help-in-package-mode" title="Permalink"></a></h3><p>You can get help about a particular package operator by writing <code>help</code> in front of it</p><pre><code class="language-julia hljs">(@v1.10) pkg> help activate</code></pre><p>You can get an overview of all package commands by typing <code>help</code> alone</p><pre><code class="language-julia hljs">(@v1.10) pkg> help</code></pre><h3 id="Package-operations-in-Julia-code"><a class="docs-heading-anchor" href="#Package-operations-in-Julia-code">Package operations in Julia code</a><a id="Package-operations-in-Julia-code-1"></a><a class="docs-heading-anchor-permalink" href="#Package-operations-in-Julia-code" title="Permalink"></a></h3><p>In some situations it is required to use package commands in Julia code, e.g., to automatize installation and deployment of Julia applications. This can be done using the <code>Pkg</code> package. For instance</p><pre><code class="language-julia hljs">julia> using Pkg
|
||||
julia> Pkg.status()</code></pre><p>is equivalent to calling <code>status</code> in package mode.</p><pre><code class="language-julia hljs">(@v1.10) pkg> status</code></pre><h3 id="Creating-you-own-package"><a class="docs-heading-anchor" href="#Creating-you-own-package">Creating you own package</a><a id="Creating-you-own-package-1"></a><a class="docs-heading-anchor-permalink" href="#Creating-you-own-package" title="Permalink"></a></h3><p>In many situations, it is useful to create your own package, for instance, when working with a large code base, when you want to reduce compilation latency using <a href="https://github.com/timholy/Revise.jl"><code>Revise.jl</code></a>, or if you want to eventually <a href="https://github.com/JuliaRegistries/Registrator.jl">register your package</a> and share it with others.</p><p>The simplest way of generating a package (called <code>MyPackage</code>) is as follows. Open Julia, go to package mode, and type</p><pre><code class="language-julia hljs">(@v1.10) pkg> generate MyPackage</code></pre><p>This will crate a minimal package consisting of a new folder <code>MyPackage</code> with two files:</p><ul><li><code>MyPackage/Project.toml</code>: Project file defining the direct dependencies of your package.</li><li><code>MyPackage/src/MyPackage.jl</code>: Main source file of your package. You can split your code in several files if needed, and include them in the package main file using function <code>include</code>.</li></ul><div class="admonition is-success"><header class="admonition-header">Tip</header><div class="admonition-body"><p>This approach only generates a very minimal package. To create a more sophisticated package skeleton (including unit testing, code coverage, readme file, licence, etc.) use <a href="https://github.com/JuliaCI/PkgTemplates.jl"><code>PkgTemplates.jl</code></a> or <a href="https://github.com/abelsiqueira/BestieTemplate.jl"><code>BestieTemplate.jl</code></a>. The later one is developed in Amsterdam at the <a href="https://www.esciencecenter.nl/">Netherlands eScience Center</a>.</p></div></div><p>You can add dependencies to the package by activating the <code>MyPackage</code> folder in package mode and adding new dependencies as always:</p><pre><code class="language-julia hljs">(@v1.10) pkg> activate MyPackage
|
||||
(MyPackage) pkg> add MPI</code></pre><p>This will add MPI to your package dependencies.</p><h3 id="Using-your-own-package"><a class="docs-heading-anchor" href="#Using-your-own-package">Using your own package</a><a id="Using-your-own-package-1"></a><a class="docs-heading-anchor-permalink" href="#Using-your-own-package" title="Permalink"></a></h3><p>To use your package you first need to add it to a package environment of your choice. This is done by changing to package mode and typing <code>develop</code> followed by the path to the folder containing the package. For instance:</p><pre><code class="language-julia hljs">(@v1.10) pkg> develop MyPackage</code></pre><div class="admonition is-info"><header class="admonition-header">Note</header><div class="admonition-body"><p>You do not need to "develop" your package if you activated the package folder <code>MyPackage</code>.</p></div></div><p>Now, we can go back to standard Julia mode and use it as any other package:</p><pre><code class="language-julia hljs">using MyPackage
|
||||
MyPackage.greet()</code></pre><p>Here, we just called the example function defined in <code>MyPackage/src/MyPackage.jl</code>.</p><h2 id="Conclusion"><a class="docs-heading-anchor" href="#Conclusion">Conclusion</a><a id="Conclusion-1"></a><a class="docs-heading-anchor-permalink" href="#Conclusion" title="Permalink"></a></h2><p>We have learned the basics of how to work with Julia, including how to run serial and parallel code, and how to manage, create, and use Julia packages. This knowledge will allow you to follow the course effectively! If you want to further dig into the topics we have covered here, you can take a look at the following links:</p><ul><li><a href="https://docs.julialang.org/en/v1/manual/getting-started/">Julia Manual</a></li><li><a href="https://pkgdocs.julialang.org/v1/getting-started/">Package manager</a></li></ul></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../">« Home</a><a class="docs-footer-nextpage" href="../julia_basics/">Julia Basics »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
MyPackage.greet()</code></pre><p>Here, we just called the example function defined in <code>MyPackage/src/MyPackage.jl</code>.</p><h2 id="Conclusion"><a class="docs-heading-anchor" href="#Conclusion">Conclusion</a><a id="Conclusion-1"></a><a class="docs-heading-anchor-permalink" href="#Conclusion" title="Permalink"></a></h2><p>We have learned the basics of how to work with Julia, including how to run serial and parallel code, and how to manage, create, and use Julia packages. This knowledge will allow you to follow the course effectively! If you want to further dig into the topics we have covered here, you can take a look at the following links:</p><ul><li><a href="https://docs.julialang.org/en/v1/manual/getting-started/">Julia Manual</a></li><li><a href="https://pkgdocs.julialang.org/v1/getting-started/">Package manager</a></li></ul></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../">« Home</a><a class="docs-footer-nextpage" href="../julia_basics/">Julia Basics »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -14,4 +14,4 @@
|
||||
var myIframe = document.getElementById("notebook");
|
||||
iFrameResize({log:true}, myIframe);
|
||||
});
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
@ -65,7 +65,38 @@
|
||||
"jacobi_3_check(answer) = answer_checker(answer, \"c\")\n",
|
||||
"lh_check(answer) = answer_checker(answer, \"c\")\n",
|
||||
"sndrcv_check(answer) = answer_checker(answer,\"b\")\n",
|
||||
"function sndrcv_fix_answer()\n",
|
||||
"function partition_1d_answer(bool)\n",
|
||||
" bool || return\n",
|
||||
" msg = \"\"\"\n",
|
||||
"- We update N^2/P items per iteration\n",
|
||||
"- We need data from 2 neighbors (2 messages per iteration)\n",
|
||||
"- We communicate N items per message\n",
|
||||
"- Communication/computation ratio is 2N/(N^2/P) = 2P/N =O(P/N)\n",
|
||||
" \"\"\"\n",
|
||||
" println(msg)\n",
|
||||
"end\n",
|
||||
"function partition_2d_answer(bool)\n",
|
||||
" bool || return\n",
|
||||
" msg = \"\"\"\n",
|
||||
"- We update N^2/P items per iteration\n",
|
||||
"- We need data from 4 neighbors (4 messages per iteration)\n",
|
||||
"- We communicate N/sqrt(P) items per message\n",
|
||||
"- Communication/computation ratio is (4N/sqrt(P)/(N^2/P)= 4sqrt(P)/N =O(sqrt(P)/N)\n",
|
||||
" \"\"\"\n",
|
||||
" println(msg)\n",
|
||||
"end\n",
|
||||
"function partition_cyclic_answer(bool)\n",
|
||||
" bool || return\n",
|
||||
" msg = \"\"\"\n",
|
||||
"- We update N^2/P items\n",
|
||||
"- We need data from 4 neighbors (4 messages per iteration)\n",
|
||||
"- We communicate N^2/P items per message (the full data owned by the neighbor)\n",
|
||||
"- Communication/computation ratio is O(1)\n",
|
||||
" \"\"\"\n",
|
||||
"println(msg)\n",
|
||||
"end\n",
|
||||
"function sndrcv_fix_answer(bool)\n",
|
||||
" bool || return\n",
|
||||
" msg = \"\"\"\n",
|
||||
" One needs to carefully order the sends and the receives to avoid cyclic dependencies\n",
|
||||
" that might result in deadlocks. The actual implementation is left as an exercise. \n",
|
||||
@ -73,7 +104,8 @@
|
||||
" println(msg)\n",
|
||||
"end\n",
|
||||
"jacobitest_check(answer) = answer_checker(answer,\"a\")\n",
|
||||
"function jacobitest_why()\n",
|
||||
"function jacobitest_why(bool)\n",
|
||||
" bool || return\n",
|
||||
" msg = \"\"\"\n",
|
||||
" The test will pass. The parallel implementation does exactly the same operations\n",
|
||||
" in exactly the same order than the sequential one. Thus, the result should be\n",
|
||||
@ -83,7 +115,8 @@
|
||||
" println(msg)\n",
|
||||
"end\n",
|
||||
"gauss_seidel_2_check(answer) = answer_checker(answer,\"d\")\n",
|
||||
"function gauss_seidel_2_why()\n",
|
||||
"function gauss_seidel_2_why(bool)\n",
|
||||
" bool || return\n",
|
||||
" msg = \"\"\"\n",
|
||||
" All \"red\" cells can be updated in parallel as they only depend on the values of \"black\" cells.\n",
|
||||
" In order workds, we can update the \"red\" cells in any order whithout changing the result. They only\n",
|
||||
@ -127,7 +160,7 @@
|
||||
"$u^{t+1}_i = \\dfrac{u^t_{i-1}+u^t_{i+1}}{2}$\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"This iterative is yet simple but shares fundamental challenges with many other algorithms used in scientific computing. This is why we are studying it here.\n"
|
||||
"This algorithm is yet simple but shares fundamental challenges with many other algorithms used in scientific computing. This is why we are studying it here.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -137,7 +170,12 @@
|
||||
"source": [
|
||||
"### Serial implementation\n",
|
||||
"\n",
|
||||
"The following code implements the iterative scheme above for boundary conditions -1 and 1 on a grid with $n$ interior points."
|
||||
"The following code implements the iterative scheme above for boundary conditions -1 and 1 on a grid with $n$ interior points.\n",
|
||||
"\n",
|
||||
"<div class=\"alert alert-block alert-info\">\n",
|
||||
"<b>Note:</b> `u, u_new = u_new, u` is equivalent to `tmp = u; u = u_new; u_new = tmp`. I.e. we swap the arrays `u` and `u_new` are referring to. \n",
|
||||
"</div>\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -203,7 +241,7 @@
|
||||
"id": "22fda724",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"In our version of the Jacobi method, we return after a given number of iterations. Other stopping criteria are possible. For instance, iterate until the maximum difference between u and u_new is below a tolerance:"
|
||||
"In our version of the Jacobi method, we return after a given number of iterations. Other stopping criteria are possible. For instance, iterate until the maximum difference between u and u_new (in absolute value) is below a tolerance."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -252,7 +290,7 @@
|
||||
"id": "6e085701",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"However, we are not going to parallelize this more complex in this notebook (left as an exercise)."
|
||||
"However, we are not going to parallelize this more complex in this notebook (left as an exercise). The simpler one is already challenging enough to start with."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -298,7 +336,7 @@
|
||||
"\n",
|
||||
"Remember that a sufficiently large grain size is needed to achieve performance in a distributed algorithm. For Jacobi, one could update each entry of vector `u_new` in a different process, but this would not be efficient. Instead, we use a parallelization strategy with a larger grain size that is analogous to the algorithm 3 we studied for the matrix-matrix multiplication:\n",
|
||||
"\n",
|
||||
"- Each worker updates a consecutive section of the array `u_new` \n",
|
||||
"- Data partition: each worker updates a consecutive section of the array `u_new` \n",
|
||||
"\n",
|
||||
"The following figure displays the data distribution over 3 processes."
|
||||
]
|
||||
@ -335,7 +373,7 @@
|
||||
"id": "ba4113af",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Note that an entry in the interior of the locally stored vector can be updated using local data only. For this one, communication is not needed."
|
||||
"Note that an entry in the interior of the locally stored vector can be updated using local data only. For updating this one, communication is not needed."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -405,6 +443,10 @@
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Communication overhead\n",
|
||||
"\n",
|
||||
"Now that we understand which are the data dependencies, we can do the theoretical performance analysis.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"- We update $N/P$ entries in each process at each iteration, where $N$ is the total length of the vector and $P$ the number of processes\n",
|
||||
"- Thus, computation complexity is $O(N/P)$\n",
|
||||
"- We need to get remote entries from 2 neighbors (2 messages per iteration)\n",
|
||||
@ -420,7 +462,7 @@
|
||||
"source": [
|
||||
"### Ghost (aka halo) cells\n",
|
||||
"\n",
|
||||
"A usual way of implementing the Jacobi method and related algorithms is using so-called ghost cells. Ghost cells represent the missing data dependencies in the data owned by each process. After importing the appropriate values from the neighbor processes one can perform the usual sequential Jacobi update locally in the processes."
|
||||
"This parallel strategy is efficient according to the theoretical analysis. But how to implement it? A usual way of implementing the Jacobi method and related algorithms is using so-called ghost cells. Ghost cells represent the missing data dependencies in the data owned by each process. After importing the appropriate values from the neighbor processes one can perform the usual sequential Jacobi update locally in the processes. Cells with gray edges are ghost (or boundary) cells in the following figure. Note that we added one ghost cell at the front and end of the local array."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -464,6 +506,14 @@
|
||||
"</div>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "0a40846c",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"We are going to implement this algorithm with MPI later in this notebook."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "75f735a2",
|
||||
@ -474,7 +524,7 @@
|
||||
"\n",
|
||||
"The Jacobi method studied so far was for a one dimensional Laplace equation. In real-world applications however, one solve equations in multiple dimensions. Typically 2D and 3D. The 2D and 3D cases are conceptually equivalent, but we will discuss the 2D case here for simplicity.\n",
|
||||
"\n",
|
||||
"Now the goal is to find the interior points of a 2D grid given the values at the boundary.\n",
|
||||
"Now, the goal is to find the interior points of a 2D grid given the values at the boundary.\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
@ -618,10 +668,17 @@
|
||||
"\n",
|
||||
"In 2d one has more flexibility in order to distribute the data over the processes. We consider these three alternatives:\n",
|
||||
"\n",
|
||||
"- 1D block partition (each worker handles a subset of consecutive rows and all columns)\n",
|
||||
"- 1D block row partition (each worker handles a subset of consecutive rows and all columns)\n",
|
||||
"- 2D block partition (each worker handles a subset of consecutive rows and columns)\n",
|
||||
"- 2D cyclic partition (each workers handles a subset of alternating rows ans columns)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"<div class=\"alert alert-block alert-info\">\n",
|
||||
"<b>Note:</b> Other options are 1D block column partition and 1D cyclic (row or column) partition. They are not analyzed in this notebook since they are closely related to the other strategies. In Julia, in fact, it is often preferable to work with 1D block column partitions than with 1D block row partitions since matrices are stored in column major order.\n",
|
||||
"</div>\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"The three partition types are depicted in the following figure for 4 processes."
|
||||
]
|
||||
},
|
||||
@ -675,13 +732,23 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "4f1e0942",
|
||||
"id": "1bc21623",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"- We update $N^2/P$ items per iteration\n",
|
||||
"- We need data from 2 neighbors (2 messages per iteration)\n",
|
||||
"- We communicate $N$ items per message\n",
|
||||
"- Communication/computation ratio is $2N/(N^2/P) = 2P/N =O(P/N)$"
|
||||
"<div class=\"alert alert-block alert-success\">\n",
|
||||
"<b>Question:</b> Compute the complexity of the communication over computation ratio for this data partition.\n",
|
||||
"</div>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "d01f8ce8",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"uncover = false # Change to true to see the answer\n",
|
||||
"partition_1d_answer(uncover)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -709,13 +776,23 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "abb6520c",
|
||||
"id": "09bd28ca",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"- We update $N^2/P$ items per iteration\n",
|
||||
"- We need data from 4 neighbors (4 messages per iteration)\n",
|
||||
"- We communicate $N/\\sqrt{P}$ items per message\n",
|
||||
"- Communication/computation ratio is $ (4N/\\sqrt{P})/(N^2/P)= 4\\sqrt{P}/N =O(\\sqrt{P}/N)$"
|
||||
"<div class=\"alert alert-block alert-success\">\n",
|
||||
"<b>Question:</b> Compute the complexity of the communication over computation ratio for this data partition.\n",
|
||||
"</div>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "e94a1ea6",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"uncover = false\n",
|
||||
"partition_2d_answer(uncover)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -743,13 +820,23 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "9cd32923",
|
||||
"id": "b373e9ce",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"- We update $N^2/P$ items\n",
|
||||
"- We need data from 4 neighbors (4 messages per iteration)\n",
|
||||
"- We communicate $N^2/P$ items per message (the full data owned by the neighbor)\n",
|
||||
"- Communication/computation ratio is $O(1)$"
|
||||
"<div class=\"alert alert-block alert-success\">\n",
|
||||
"<b>Question:</b> Compute the complexity of the communication over computation ratio for this data partition.\n",
|
||||
"</div>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "10fab825",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"uncover = false\n",
|
||||
"partition_cyclic_answer(uncover)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -897,7 +984,7 @@
|
||||
"source": [
|
||||
"### Backwards Gauss-Seidel\n",
|
||||
"\n",
|
||||
"In addition, the the result of the Gauss-Seidel method depends on the order of the steps in the loop over `i`. This is another symptom that tells you that this loop is hard to parallelize. For instance, if you do the iterations over `i` by reversing the loop order, you get another method called *backward* Gauss-Seidel."
|
||||
"In addition, the the result of the Gauss-Seidel method depends on the order of the steps in the loop over `i`. This is another symptom that tells you that this loop is hard (or impossible) to parallelize. For instance, if you do the iterations over `i` by reversing the loop order, you get another method called *backward* Gauss-Seidel."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -925,7 +1012,7 @@
|
||||
"id": "63c4ce1f",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Both Jacobi and *forward* and *backward* Gauss-Seidel converge to the same result, but they lead to slightly different values during the iterations. Check it with the following cells. First, run it with one `niters=1` and then with `niters=100`."
|
||||
"Both Jacobi and *forward* and *backward* Gauss-Seidel converge to the same result, but they lead to slightly different values during the iterations. Check it with the following cells. First, run the methods with `niters=1` and then with `niters=100`."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -967,7 +1054,7 @@
|
||||
"source": [
|
||||
"### Red-black Gauss-Seidel\n",
|
||||
"\n",
|
||||
"There is another version called *red-black* Gauss-Seidel. This uses a very clever order for the steps in the loop over `i`. It does this loop in two phases. First, one updates the entries with even index, and then the entries with odd index."
|
||||
"There is yet another version called *red-black* Gauss-Seidel. This uses a very clever order for the steps in the loop over `i`. It does this loop in two phases. First, one updates the entries with even index, and then the entries with odd index."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -1083,7 +1170,18 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"gauss_seidel_2_why()"
|
||||
"uncover = false\n",
|
||||
"gauss_seidel_2_why(uncover)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "41e90d60",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Changing an algorithm to make it parallel\n",
|
||||
"\n",
|
||||
"Note that the original method (the forward Gauss-Seidel) cannot be parallelized, we needed to modify the method slightly with the red-black ordering in order to create a method that can be parallelized. However the method we parallelized is not equivalent to the original one. This happens in practice in many other applications. An algorithm might be impossible to parallelize and one needs to modify it to exploit parallelism. However, one needs to be careful when modifying the algorithm to not destroy the algorithmic properties of the original one. In this case, we succeeded. The red-black Gauss-Seidel converges as fast (if not faster) than the original forward Gauss-Seidel. However, this is not true in general. There is often a trade-off between the algorithmic properties and how parallelizable is the algorithm."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -1093,7 +1191,7 @@
|
||||
"source": [
|
||||
"## MPI implementation\n",
|
||||
"\n",
|
||||
"We consider the implementation of the Jacobi method using MPI. We will consider the 1D version for simplicity.\n",
|
||||
"In the last part of this notebook, we consider the implementation of the Jacobi method using MPI. We will consider the 1D version for simplicity.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"<div class=\"alert alert-block alert-info\">\n",
|
||||
@ -1154,7 +1252,7 @@
|
||||
"source": [
|
||||
"### Initialization\n",
|
||||
"\n",
|
||||
"Let us start with function `init`. This is its implementation:"
|
||||
"Let us start with function `init`."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -1191,7 +1289,7 @@
|
||||
"id": "1b9e75d8",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"This function crates and initializes the vector `u` and the auxiliary vector `u_new` and fills in the boundary values. Note that we are not creating the full arrays like in the sequential case. We are only creating the parts to be managed by the current rank. To this end, we start by computing the number of entries to be updated in this rank, i.e., variable `load`. We have assumed that `n` is a multiple of the number of ranks for simplicity. If this is not the case, we stop the computation with `MPI.Abort`. Note that we are allocating two extra elements in `u` (and `u_new`) for the ghost cells or boundary conditions. The following figure displays the arrays created for `n==9` and `nranks==3` (thus `load == 3`). Note that the first and last elements of the arrays are displayed with gray edges denoting that they are the extra elements allocated for ghost cells or boundary conditions."
|
||||
"This function crates and initializes the vector `u` and the auxiliary vector `u_new` and fills in the boundary values. Note that we are not creating the full arrays like in the sequential case. We are only creating the parts to be managed by the current rank. To this end, we start by computing the number of entries to be updated in this rank, i.e., variable `load`. We have assumed that `n` is a multiple of the number of ranks for simplicity. If this is not the case, we stop the computation with `MPI.Abort`. Note that we are allocating two extra elements in `u` (and `u_new`) for the ghost cells and boundary conditions. The following figure displays the arrays created for `n==9` and `nranks==3` (thus `load == 3`). Note that the first and last elements of the arrays are displayed with gray edges denoting that they are the extra elements allocated for ghost cells or boundary conditions."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -1353,7 +1451,8 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"sndrcv_fix_answer()"
|
||||
"uncover = false\n",
|
||||
"sndrcv_fix_answer(uncover)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -1363,7 +1462,7 @@
|
||||
"source": [
|
||||
"### Local computation\n",
|
||||
"\n",
|
||||
"Once the ghost values have the right values, we can perform the Jacobi update locally at each process. This is done in function `local_update!`. Note that here we only update the data *owned* by the current MPI rank, i.e. we do not modify the ghost values. There is no need to modify the ghost values since they will updated by another rank, i.e. the rank that own the value. In the code this is reflected in the loop over `i`. We do not visit the first nor the last entry in `u_new`."
|
||||
"Once the ghost cells have the right values, we can perform the Jacobi update locally at each process. This is done in function `local_update!`. Note that here we only update the data *owned* by the current MPI rank, i.e. we do not modify the ghost values. There is no need to modify the ghost values since they will updated by another rank. In the code, this is reflected in the loop over `i`. We do not visit the first nor the last entry in `u_new`."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -1390,7 +1489,7 @@
|
||||
"source": [
|
||||
"### Running the code\n",
|
||||
"\n",
|
||||
"Not let us put all pieces together and run the code. If not done yet, install MPI."
|
||||
"Let us put all pieces together and run the code. If not done yet, install MPI."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -1408,7 +1507,7 @@
|
||||
"id": "c966375a",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The following cells includes all previous code snippets into a final one. Note that we are eventually calling function `jacobi_mpi` and showing the result vector `u`. Run the following code for 1 MPI rank, then for 2 and 3 MPI ranks. Look into the values of `u`. Does it make sense?"
|
||||
"The following cells includes all previous code snippets into a final one. We are eventually calling function `jacobi_mpi` and showing the result vector `u`. Run the following code for 1 MPI rank, then for 2 and 3 MPI ranks. Look into the values of `u`. Does it make sense?"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -1442,7 +1541,7 @@
|
||||
"source": [
|
||||
"### Checking the result\n",
|
||||
"\n",
|
||||
"Checking the result visually is not enough in general. To check the parallel implementation we want to compare the result against the sequential implementation. The way we do the computations (either in parallel or sequential) should not affect the result. However, how can we compare the sequential and the parallel result? The parallel version gives a distributed vector. We cannot compare this one directly with the result of the sequential function. A possible solution is to gather all the pieces of the parallel result in a single rank and compare there against the parallel implementation.\n",
|
||||
"Checking the result visually is not enough in general. To check the parallel implementation we want to compare it against the sequential implementation. However, how can we compare the sequential and the parallel result? The parallel version gives a distributed vector. We cannot compare this one directly with the result of the sequential function. A possible solution is to gather all the pieces of the parallel result in a single rank and compare there against the parallel implementation.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"The following function gather the distributed vector in rank 0."
|
||||
@ -1592,58 +1691,6 @@
|
||||
"run(`$(mpiexec()) -np 3 julia --project=. -e $code`);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "73cd4d73",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Note that we have used function `isapprox` to compare the results. This function checks if two values are the same within machine precision. Using `==` is generally discouraged when working with floating point numbers as they can be affected by rounding-off errors."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "d73c838c",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<div class=\"alert alert-block alert-success\">\n",
|
||||
"<b>Question:</b> What happens if we use `u_root == u_seq` to compare the parallel and the sequential result?\n",
|
||||
"</div>\n",
|
||||
"\n",
|
||||
" a) The test will still pass.\n",
|
||||
" b) The test will fail due to rounding-off errors.\n",
|
||||
" c) The test might pass or fail depending on `n`.\n",
|
||||
" d) The test might pass or fail depending on the number of MPI ranks."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "cd2427f1",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"answer = \"x\" # replace x with a, b, c or d\n",
|
||||
"jacobitest_check(answer)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "790e7064",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Run cell below for an explanation of the correct answer."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "72ed2aa1",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"jacobitest_why()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "c9aa2901",
|
||||
@ -1651,7 +1698,7 @@
|
||||
"source": [
|
||||
"## Latency hiding\n",
|
||||
"\n",
|
||||
"Can our implementation above be improved? Note that we only need communications to update the values at the boundary of the portion owned by each process. The other values (the one in green in the figure below) can be updated without communications. This provides the opportunity of overlapping the computation of the interior values (green cells in the figure) with the communication of the ghost values. This technique is called latency hiding, since we are hiding communication latency by overlapping it with computation that we need to do anyway. The actual implementation is left as an exercise (see Exercise 1)."
|
||||
"We have now a correct parallel implementation. But. can our implementation above be improved? Note that we only need communications to update the values at the boundary of the portion owned by each process. The other values (the one in green in the figure below) can be updated without communications. This provides the opportunity of overlapping the computation of the interior values (green cells in the figure) with the communication of the ghost values. This technique is called latency hiding, since we are hiding communication latency by overlapping it with computation that we need to do anyway. The actual implementation is left as an exercise (see Exercise 1)."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@ -14,4 +14,4 @@
|
||||
var myIframe = document.getElementById("notebook");
|
||||
iFrameResize({log:true}, myIframe);
|
||||
});
|
||||
</script></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../mpi_collectives/">« MPI (collectives)</a><a class="docs-footer-nextpage" href="../solutions_for_all_notebooks/">Solutions »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
</script></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../mpi_collectives/">« MPI (collectives)</a><a class="docs-footer-nextpage" href="../solutions_for_all_notebooks/">Solutions »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
@ -7586,7 +7586,38 @@ a.anchor-link {
|
||||
<span class="n">jacobi_3_check</span><span class="p">(</span><span class="n">answer</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">answer_checker</span><span class="p">(</span><span class="n">answer</span><span class="p">,</span><span class="w"> </span><span class="s">"c"</span><span class="p">)</span>
|
||||
<span class="n">lh_check</span><span class="p">(</span><span class="n">answer</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">answer_checker</span><span class="p">(</span><span class="n">answer</span><span class="p">,</span><span class="w"> </span><span class="s">"c"</span><span class="p">)</span>
|
||||
<span class="n">sndrcv_check</span><span class="p">(</span><span class="n">answer</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">answer_checker</span><span class="p">(</span><span class="n">answer</span><span class="p">,</span><span class="s">"b"</span><span class="p">)</span>
|
||||
<span class="k">function</span><span class="w"> </span><span class="n">sndrcv_fix_answer</span><span class="p">()</span>
|
||||
<span class="k">function</span><span class="w"> </span><span class="n">partition_1d_answer</span><span class="p">(</span><span class="n">bool</span><span class="p">)</span>
|
||||
<span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="k">return</span>
|
||||
<span class="w"> </span><span class="n">msg</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"""</span>
|
||||
<span class="s">- We update N^2/P items per iteration</span>
|
||||
<span class="s">- We need data from 2 neighbors (2 messages per iteration)</span>
|
||||
<span class="s">- We communicate N items per message</span>
|
||||
<span class="s">- Communication/computation ratio is 2N/(N^2/P) = 2P/N =O(P/N)</span>
|
||||
<span class="s"> """</span>
|
||||
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">function</span><span class="w"> </span><span class="n">partition_2d_answer</span><span class="p">(</span><span class="n">bool</span><span class="p">)</span>
|
||||
<span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="k">return</span>
|
||||
<span class="w"> </span><span class="n">msg</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"""</span>
|
||||
<span class="s">- We update N^2/P items per iteration</span>
|
||||
<span class="s">- We need data from 4 neighbors (4 messages per iteration)</span>
|
||||
<span class="s">- We communicate N/sqrt(P) items per message</span>
|
||||
<span class="s">- Communication/computation ratio is (4N/sqrt(P)/(N^2/P)= 4sqrt(P)/N =O(sqrt(P)/N)</span>
|
||||
<span class="s"> """</span>
|
||||
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">function</span><span class="w"> </span><span class="n">partition_cyclic_answer</span><span class="p">(</span><span class="n">bool</span><span class="p">)</span>
|
||||
<span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="k">return</span>
|
||||
<span class="w"> </span><span class="n">msg</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"""</span>
|
||||
<span class="s">- We update N^2/P items</span>
|
||||
<span class="s">- We need data from 4 neighbors (4 messages per iteration)</span>
|
||||
<span class="s">- We communicate N^2/P items per message (the full data owned by the neighbor)</span>
|
||||
<span class="s">- Communication/computation ratio is O(1)</span>
|
||||
<span class="s"> """</span>
|
||||
<span class="n">println</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">function</span><span class="w"> </span><span class="n">sndrcv_fix_answer</span><span class="p">(</span><span class="n">bool</span><span class="p">)</span>
|
||||
<span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="k">return</span>
|
||||
<span class="w"> </span><span class="n">msg</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"""</span>
|
||||
<span class="s"> One needs to carefully order the sends and the receives to avoid cyclic dependencies</span>
|
||||
<span class="s"> that might result in deadlocks. The actual implementation is left as an exercise. </span>
|
||||
@ -7594,7 +7625,8 @@ a.anchor-link {
|
||||
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
|
||||
<span class="k">end</span>
|
||||
<span class="n">jacobitest_check</span><span class="p">(</span><span class="n">answer</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">answer_checker</span><span class="p">(</span><span class="n">answer</span><span class="p">,</span><span class="s">"a"</span><span class="p">)</span>
|
||||
<span class="k">function</span><span class="w"> </span><span class="n">jacobitest_why</span><span class="p">()</span>
|
||||
<span class="k">function</span><span class="w"> </span><span class="n">jacobitest_why</span><span class="p">(</span><span class="n">bool</span><span class="p">)</span>
|
||||
<span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="k">return</span>
|
||||
<span class="w"> </span><span class="n">msg</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"""</span>
|
||||
<span class="s"> The test will pass. The parallel implementation does exactly the same operations</span>
|
||||
<span class="s"> in exactly the same order than the sequential one. Thus, the result should be</span>
|
||||
@ -7604,7 +7636,8 @@ a.anchor-link {
|
||||
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
|
||||
<span class="k">end</span>
|
||||
<span class="n">gauss_seidel_2_check</span><span class="p">(</span><span class="n">answer</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">answer_checker</span><span class="p">(</span><span class="n">answer</span><span class="p">,</span><span class="s">"d"</span><span class="p">)</span>
|
||||
<span class="k">function</span><span class="w"> </span><span class="n">gauss_seidel_2_why</span><span class="p">()</span>
|
||||
<span class="k">function</span><span class="w"> </span><span class="n">gauss_seidel_2_why</span><span class="p">(</span><span class="n">bool</span><span class="p">)</span>
|
||||
<span class="w"> </span><span class="n">bool</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="k">return</span>
|
||||
<span class="w"> </span><span class="n">msg</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"""</span>
|
||||
<span class="s"> All "red" cells can be updated in parallel as they only depend on the values of "black" cells.</span>
|
||||
<span class="s"> In order workds, we can update the "red" cells in any order whithout changing the result. They only</span>
|
||||
@ -7652,7 +7685,7 @@ a.anchor-link {
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<p>When solving a <a href="https://en.wikipedia.org/wiki/Laplace%27s_equation">Laplace equation</a> in 1D, the Jacobi method leads to the following iterative scheme: The entry $i$ of vector $u$ at iteration $t+1$ is computed as:</p>
|
||||
<p>$u^{t+1}_i = \dfrac{u^t_{i-1}+u^t_{i+1}}{2}$</p>
|
||||
<p>This iterative is yet simple but shares fundamental challenges with many other algorithms used in scientific computing. This is why we are studying it here.</p>
|
||||
<p>This algorithm is yet simple but shares fundamental challenges with many other algorithms used in scientific computing. This is why we are studying it here.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -7664,6 +7697,9 @@ a.anchor-link {
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h3 id="Serial-implementation">Serial implementation<a class="anchor-link" href="#Serial-implementation">¶</a></h3><p>The following code implements the iterative scheme above for boundary conditions -1 and 1 on a grid with $n$ interior points.</p>
|
||||
<div class="alert alert-block alert-info">
|
||||
<b>Note:</b> `u, u_new = u_new, u` is equivalent to `tmp = u; u = u_new; u_new = tmp`. I.e. we swap the arrays `u` and `u_new` are referring to.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -7750,7 +7786,7 @@ a.anchor-link {
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<p>In our version of the Jacobi method, we return after a given number of iterations. Other stopping criteria are possible. For instance, iterate until the maximum difference between u and u_new is below a tolerance:</p>
|
||||
<p>In our version of the Jacobi method, we return after a given number of iterations. Other stopping criteria are possible. For instance, iterate until the maximum difference between u and u_new (in absolute value) is below a tolerance.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -7810,7 +7846,7 @@ a.anchor-link {
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<p>However, we are not going to parallelize this more complex in this notebook (left as an exercise).</p>
|
||||
<p>However, we are not going to parallelize this more complex in this notebook (left as an exercise). The simpler one is already challenging enough to start with.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -7856,7 +7892,7 @@ a.anchor-link {
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h3 id="Parallelization-strategy">Parallelization strategy<a class="anchor-link" href="#Parallelization-strategy">¶</a></h3><p>Remember that a sufficiently large grain size is needed to achieve performance in a distributed algorithm. For Jacobi, one could update each entry of vector <code>u_new</code> in a different process, but this would not be efficient. Instead, we use a parallelization strategy with a larger grain size that is analogous to the algorithm 3 we studied for the matrix-matrix multiplication:</p>
|
||||
<ul>
|
||||
<li>Each worker updates a consecutive section of the array <code>u_new</code></li>
|
||||
<li>Data partition: each worker updates a consecutive section of the array <code>u_new</code></li>
|
||||
</ul>
|
||||
<p>The following figure displays the data distribution over 3 processes.</p>
|
||||
</div>
|
||||
@ -7894,7 +7930,7 @@ a.anchor-link {
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<p>Note that an entry in the interior of the locally stored vector can be updated using local data only. For this one, communication is not needed.</p>
|
||||
<p>Note that an entry in the interior of the locally stored vector can be updated using local data only. For updating this one, communication is not needed.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -7966,7 +8002,8 @@ a.anchor-link {
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h3 id="Communication-overhead">Communication overhead<a class="anchor-link" href="#Communication-overhead">¶</a></h3><ul>
|
||||
<h3 id="Communication-overhead">Communication overhead<a class="anchor-link" href="#Communication-overhead">¶</a></h3><p>Now that we understand which are the data dependencies, we can do the theoretical performance analysis.</p>
|
||||
<ul>
|
||||
<li>We update $N/P$ entries in each process at each iteration, where $N$ is the total length of the vector and $P$ the number of processes</li>
|
||||
<li>Thus, computation complexity is $O(N/P)$</li>
|
||||
<li>We need to get remote entries from 2 neighbors (2 messages per iteration)</li>
|
||||
@ -7984,7 +8021,7 @@ a.anchor-link {
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h3 id="Ghost-(aka-halo)-cells">Ghost (aka halo) cells<a class="anchor-link" href="#Ghost-(aka-halo)-cells">¶</a></h3><p>A usual way of implementing the Jacobi method and related algorithms is using so-called ghost cells. Ghost cells represent the missing data dependencies in the data owned by each process. After importing the appropriate values from the neighbor processes one can perform the usual sequential Jacobi update locally in the processes.</p>
|
||||
<h3 id="Ghost-(aka-halo)-cells">Ghost (aka halo) cells<a class="anchor-link" href="#Ghost-(aka-halo)-cells">¶</a></h3><p>This parallel strategy is efficient according to the theoretical analysis. But how to implement it? A usual way of implementing the Jacobi method and related algorithms is using so-called ghost cells. Ghost cells represent the missing data dependencies in the data owned by each process. After importing the appropriate values from the neighbor processes one can perform the usual sequential Jacobi update locally in the processes. Cells with gray edges are ghost (or boundary) cells in the following figure. Note that we added one ghost cell at the front and end of the local array.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -8030,6 +8067,17 @@ a.anchor-link {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=0a40846c">
|
||||
<div class="jp-Cell-inputWrapper" tabindex="0">
|
||||
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<p>We are going to implement this algorithm with MPI later in this notebook.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=75f735a2">
|
||||
<div class="jp-Cell-inputWrapper" tabindex="0">
|
||||
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
||||
@ -8037,7 +8085,7 @@ a.anchor-link {
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h2 id="Extension-to-2D">Extension to 2D<a class="anchor-link" href="#Extension-to-2D">¶</a></h2><p>The Jacobi method studied so far was for a one dimensional Laplace equation. In real-world applications however, one solve equations in multiple dimensions. Typically 2D and 3D. The 2D and 3D cases are conceptually equivalent, but we will discuss the 2D case here for simplicity.</p>
|
||||
<p>Now the goal is to find the interior points of a 2D grid given the values at the boundary.</p>
|
||||
<p>Now, the goal is to find the interior points of a 2D grid given the values at the boundary.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -8199,10 +8247,13 @@ a.anchor-link {
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h3 id="Parallelization-strategies">Parallelization strategies<a class="anchor-link" href="#Parallelization-strategies">¶</a></h3><p>In 2d one has more flexibility in order to distribute the data over the processes. We consider these three alternatives:</p>
|
||||
<ul>
|
||||
<li>1D block partition (each worker handles a subset of consecutive rows and all columns)</li>
|
||||
<li>1D block row partition (each worker handles a subset of consecutive rows and all columns)</li>
|
||||
<li>2D block partition (each worker handles a subset of consecutive rows and columns)</li>
|
||||
<li>2D cyclic partition (each workers handles a subset of alternating rows ans columns)</li>
|
||||
</ul>
|
||||
<div class="alert alert-block alert-info">
|
||||
<b>Note:</b> Other options are 1D block column partition and 1D cyclic (row or column) partition. They are not analyzed in this notebook since they are closely related to the other strategies. In Julia, in fact, it is often preferable to work with 1D block column partitions than with 1D block row partitions since matrices are stored in column major order.
|
||||
</div>
|
||||
<p>The three partition types are depicted in the following figure for 4 processes.</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -8256,18 +8307,30 @@ a.anchor-link {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=4f1e0942">
|
||||
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=1bc21623">
|
||||
<div class="jp-Cell-inputWrapper" tabindex="0">
|
||||
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<ul>
|
||||
<li>We update $N^2/P$ items per iteration</li>
|
||||
<li>We need data from 2 neighbors (2 messages per iteration)</li>
|
||||
<li>We communicate $N$ items per message</li>
|
||||
<li>Communication/computation ratio is $2N/(N^2/P) = 2P/N =O(P/N)$</li>
|
||||
</ul>
|
||||
<div class="alert alert-block alert-success">
|
||||
<b>Question:</b> Compute the complexity of the communication over computation ratio for this data partition.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=d01f8ce8">
|
||||
<div class="jp-Cell-inputWrapper" tabindex="0">
|
||||
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea">
|
||||
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
|
||||
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
|
||||
<div class="cm-editor cm-s-jupyter">
|
||||
<div class="highlight hl-julia"><pre><span></span><span class="n">uncover</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">false</span><span class="w"> </span><span class="c"># Change to true to see the answer</span>
|
||||
<span class="n">partition_1d_answer</span><span class="p">(</span><span class="n">uncover</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -8296,18 +8359,30 @@ a.anchor-link {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=abb6520c">
|
||||
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=09bd28ca">
|
||||
<div class="jp-Cell-inputWrapper" tabindex="0">
|
||||
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<ul>
|
||||
<li>We update $N^2/P$ items per iteration</li>
|
||||
<li>We need data from 4 neighbors (4 messages per iteration)</li>
|
||||
<li>We communicate $N/\sqrt{P}$ items per message</li>
|
||||
<li>Communication/computation ratio is $ (4N/\sqrt{P})/(N^2/P)= 4\sqrt{P}/N =O(\sqrt{P}/N)$</li>
|
||||
</ul>
|
||||
<div class="alert alert-block alert-success">
|
||||
<b>Question:</b> Compute the complexity of the communication over computation ratio for this data partition.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=e94a1ea6">
|
||||
<div class="jp-Cell-inputWrapper" tabindex="0">
|
||||
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea">
|
||||
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
|
||||
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
|
||||
<div class="cm-editor cm-s-jupyter">
|
||||
<div class="highlight hl-julia"><pre><span></span><span class="n">uncover</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">false</span>
|
||||
<span class="n">partition_2d_answer</span><span class="p">(</span><span class="n">uncover</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -8336,18 +8411,30 @@ a.anchor-link {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=9cd32923">
|
||||
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=b373e9ce">
|
||||
<div class="jp-Cell-inputWrapper" tabindex="0">
|
||||
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<ul>
|
||||
<li>We update $N^2/P$ items</li>
|
||||
<li>We need data from 4 neighbors (4 messages per iteration)</li>
|
||||
<li>We communicate $N^2/P$ items per message (the full data owned by the neighbor)</li>
|
||||
<li>Communication/computation ratio is $O(1)$</li>
|
||||
</ul>
|
||||
<div class="alert alert-block alert-success">
|
||||
<b>Question:</b> Compute the complexity of the communication over computation ratio for this data partition.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=10fab825">
|
||||
<div class="jp-Cell-inputWrapper" tabindex="0">
|
||||
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea">
|
||||
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
|
||||
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
|
||||
<div class="cm-editor cm-s-jupyter">
|
||||
<div class="highlight hl-julia"><pre><span></span><span class="n">uncover</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">false</span>
|
||||
<span class="n">partition_cyclic_answer</span><span class="p">(</span><span class="n">uncover</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -8545,7 +8632,7 @@ d) The inner, but not the outer</code></pre>
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h3 id="Backwards-Gauss-Seidel">Backwards Gauss-Seidel<a class="anchor-link" href="#Backwards-Gauss-Seidel">¶</a></h3><p>In addition, the the result of the Gauss-Seidel method depends on the order of the steps in the loop over <code>i</code>. This is another symptom that tells you that this loop is hard to parallelize. For instance, if you do the iterations over <code>i</code> by reversing the loop order, you get another method called <em>backward</em> Gauss-Seidel.</p>
|
||||
<h3 id="Backwards-Gauss-Seidel">Backwards Gauss-Seidel<a class="anchor-link" href="#Backwards-Gauss-Seidel">¶</a></h3><p>In addition, the the result of the Gauss-Seidel method depends on the order of the steps in the loop over <code>i</code>. This is another symptom that tells you that this loop is hard (or impossible) to parallelize. For instance, if you do the iterations over <code>i</code> by reversing the loop order, you get another method called <em>backward</em> Gauss-Seidel.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -8580,7 +8667,7 @@ d) The inner, but not the outer</code></pre>
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<p>Both Jacobi and <em>forward</em> and <em>backward</em> Gauss-Seidel converge to the same result, but they lead to slightly different values during the iterations. Check it with the following cells. First, run it with one <code>niters=1</code> and then with <code>niters=100</code>.</p>
|
||||
<p>Both Jacobi and <em>forward</em> and <em>backward</em> Gauss-Seidel converge to the same result, but they lead to slightly different values during the iterations. Check it with the following cells. First, run the methods with <code>niters=1</code> and then with <code>niters=100</code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -8635,7 +8722,7 @@ d) The inner, but not the outer</code></pre>
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h3 id="Red-black-Gauss-Seidel">Red-black Gauss-Seidel<a class="anchor-link" href="#Red-black-Gauss-Seidel">¶</a></h3><p>There is another version called <em>red-black</em> Gauss-Seidel. This uses a very clever order for the steps in the loop over <code>i</code>. It does this loop in two phases. First, one updates the entries with even index, and then the entries with odd index.</p>
|
||||
<h3 id="Red-black-Gauss-Seidel">Red-black Gauss-Seidel<a class="anchor-link" href="#Red-black-Gauss-Seidel">¶</a></h3><p>There is yet another version called <em>red-black</em> Gauss-Seidel. This uses a very clever order for the steps in the loop over <code>i</code>. It does this loop in two phases. First, one updates the entries with even index, and then the entries with odd index.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -8769,20 +8856,32 @@ d) Loop over i only</code></pre>
|
||||
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
|
||||
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
|
||||
<div class="cm-editor cm-s-jupyter">
|
||||
<div class="highlight hl-julia"><pre><span></span><span class="n">gauss_seidel_2_why</span><span class="p">()</span>
|
||||
<div class="highlight hl-julia"><pre><span></span><span class="n">uncover</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">false</span>
|
||||
<span class="n">gauss_seidel_2_why</span><span class="p">(</span><span class="n">uncover</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=41e90d60">
|
||||
<div class="jp-Cell-inputWrapper" tabindex="0">
|
||||
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h3 id="Changing-an-algorithm-to-make-it-parallel">Changing an algorithm to make it parallel<a class="anchor-link" href="#Changing-an-algorithm-to-make-it-parallel">¶</a></h3><p>Note that the original method (the forward Gauss-Seidel) cannot be parallelized, we needed to modify the method slightly with the red-black ordering in order to create a method that can be parallelized. However the method we parallelized is not equivalent to the original one. This happens in practice in many other applications. An algorithm might be impossible to parallelize and one needs to modify it to exploit parallelism. However, one needs to be careful when modifying the algorithm to not destroy the algorithmic properties of the original one. In this case, we succeeded. The red-black Gauss-Seidel converges as fast (if not faster) than the original forward Gauss-Seidel. However, this is not true in general. There is often a trade-off between the algorithmic properties and how parallelizable is the algorithm.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=8ed4129c">
|
||||
<div class="jp-Cell-inputWrapper" tabindex="0">
|
||||
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h2 id="MPI-implementation">MPI implementation<a class="anchor-link" href="#MPI-implementation">¶</a></h2><p>We consider the implementation of the Jacobi method using MPI. We will consider the 1D version for simplicity.</p>
|
||||
<h2 id="MPI-implementation">MPI implementation<a class="anchor-link" href="#MPI-implementation">¶</a></h2><p>In the last part of this notebook, we consider the implementation of the Jacobi method using MPI. We will consider the 1D version for simplicity.</p>
|
||||
<div class="alert alert-block alert-info">
|
||||
<b>Note:</b> The programming model of MPI is generally better suited for data-parallel algorithms like this one than the task-based model provided by Distributed.jl. In any case, one can also implement it using Distributed.jl, but it requires some extra effort to setup the remote channels right for the communication between neighbor processes.
|
||||
</div>
|
||||
@ -8844,7 +8943,7 @@ d) Loop over i only</code></pre>
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h3 id="Initialization">Initialization<a class="anchor-link" href="#Initialization">¶</a></h3><p>Let us start with function <code>init</code>. This is its implementation:</p>
|
||||
<h3 id="Initialization">Initialization<a class="anchor-link" href="#Initialization">¶</a></h3><p>Let us start with function <code>init</code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -8888,7 +8987,7 @@ d) Loop over i only</code></pre>
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<p>This function crates and initializes the vector <code>u</code> and the auxiliary vector <code>u_new</code> and fills in the boundary values. Note that we are not creating the full arrays like in the sequential case. We are only creating the parts to be managed by the current rank. To this end, we start by computing the number of entries to be updated in this rank, i.e., variable <code>load</code>. We have assumed that <code>n</code> is a multiple of the number of ranks for simplicity. If this is not the case, we stop the computation with <code>MPI.Abort</code>. Note that we are allocating two extra elements in <code>u</code> (and <code>u_new</code>) for the ghost cells or boundary conditions. The following figure displays the arrays created for <code>n==9</code> and <code>nranks==3</code> (thus <code>load == 3</code>). Note that the first and last elements of the arrays are displayed with gray edges denoting that they are the extra elements allocated for ghost cells or boundary conditions.</p>
|
||||
<p>This function crates and initializes the vector <code>u</code> and the auxiliary vector <code>u_new</code> and fills in the boundary values. Note that we are not creating the full arrays like in the sequential case. We are only creating the parts to be managed by the current rank. To this end, we start by computing the number of entries to be updated in this rank, i.e., variable <code>load</code>. We have assumed that <code>n</code> is a multiple of the number of ranks for simplicity. If this is not the case, we stop the computation with <code>MPI.Abort</code>. Note that we are allocating two extra elements in <code>u</code> (and <code>u_new</code>) for the ghost cells and boundary conditions. The following figure displays the arrays created for <code>n==9</code> and <code>nranks==3</code> (thus <code>load == 3</code>). Note that the first and last elements of the arrays are displayed with gray edges denoting that they are the extra elements allocated for ghost cells or boundary conditions.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -9065,7 +9164,8 @@ d) This implementation does not work when distributing over just a single MPI ra
|
||||
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
|
||||
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
|
||||
<div class="cm-editor cm-s-jupyter">
|
||||
<div class="highlight hl-julia"><pre><span></span><span class="n">sndrcv_fix_answer</span><span class="p">()</span>
|
||||
<div class="highlight hl-julia"><pre><span></span><span class="n">uncover</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">false</span>
|
||||
<span class="n">sndrcv_fix_answer</span><span class="p">(</span><span class="n">uncover</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
@ -9078,7 +9178,7 @@ d) This implementation does not work when distributing over just a single MPI ra
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h3 id="Local-computation">Local computation<a class="anchor-link" href="#Local-computation">¶</a></h3><p>Once the ghost values have the right values, we can perform the Jacobi update locally at each process. This is done in function <code>local_update!</code>. Note that here we only update the data <em>owned</em> by the current MPI rank, i.e. we do not modify the ghost values. There is no need to modify the ghost values since they will updated by another rank, i.e. the rank that own the value. In the code this is reflected in the loop over <code>i</code>. We do not visit the first nor the last entry in <code>u_new</code>.</p>
|
||||
<h3 id="Local-computation">Local computation<a class="anchor-link" href="#Local-computation">¶</a></h3><p>Once the ghost cells have the right values, we can perform the Jacobi update locally at each process. This is done in function <code>local_update!</code>. Note that here we only update the data <em>owned</em> by the current MPI rank, i.e. we do not modify the ghost values. There is no need to modify the ghost values since they will updated by another rank. In the code, this is reflected in the loop over <code>i</code>. We do not visit the first nor the last entry in <code>u_new</code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -9110,7 +9210,7 @@ d) This implementation does not work when distributing over just a single MPI ra
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h3 id="Running-the-code">Running the code<a class="anchor-link" href="#Running-the-code">¶</a></h3><p>Not let us put all pieces together and run the code. If not done yet, install MPI.</p>
|
||||
<h3 id="Running-the-code">Running the code<a class="anchor-link" href="#Running-the-code">¶</a></h3><p>Let us put all pieces together and run the code. If not done yet, install MPI.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -9135,7 +9235,7 @@ d) This implementation does not work when distributing over just a single MPI ra
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<p>The following cells includes all previous code snippets into a final one. Note that we are eventually calling function <code>jacobi_mpi</code> and showing the result vector <code>u</code>. Run the following code for 1 MPI rank, then for 2 and 3 MPI ranks. Look into the values of <code>u</code>. Does it make sense?</p>
|
||||
<p>The following cells includes all previous code snippets into a final one. We are eventually calling function <code>jacobi_mpi</code> and showing the result vector <code>u</code>. Run the following code for 1 MPI rank, then for 2 and 3 MPI ranks. Look into the values of <code>u</code>. Does it make sense?</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -9174,7 +9274,7 @@ d) This implementation does not work when distributing over just a single MPI ra
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h3 id="Checking-the-result">Checking the result<a class="anchor-link" href="#Checking-the-result">¶</a></h3><p>Checking the result visually is not enough in general. To check the parallel implementation we want to compare the result against the sequential implementation. The way we do the computations (either in parallel or sequential) should not affect the result. However, how can we compare the sequential and the parallel result? The parallel version gives a distributed vector. We cannot compare this one directly with the result of the sequential function. A possible solution is to gather all the pieces of the parallel result in a single rank and compare there against the parallel implementation.</p>
|
||||
<h3 id="Checking-the-result">Checking the result<a class="anchor-link" href="#Checking-the-result">¶</a></h3><p>Checking the result visually is not enough in general. To check the parallel implementation we want to compare it against the sequential implementation. However, how can we compare the sequential and the parallel result? The parallel version gives a distributed vector. We cannot compare this one directly with the result of the sequential function. A possible solution is to gather all the pieces of the parallel result in a single rank and compare there against the parallel implementation.</p>
|
||||
<p>The following function gather the distributed vector in rank 0.</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -9346,81 +9446,13 @@ d) This implementation does not work when distributing over just a single MPI ra
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=73cd4d73">
|
||||
<div class="jp-Cell-inputWrapper" tabindex="0">
|
||||
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<p>Note that we have used function <code>isapprox</code> to compare the results. This function checks if two values are the same within machine precision. Using <code>==</code> is generally discouraged when working with floating point numbers as they can be affected by rounding-off errors.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=d73c838c">
|
||||
<div class="jp-Cell-inputWrapper" tabindex="0">
|
||||
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<div class="alert alert-block alert-success">
|
||||
<b>Question:</b> What happens if we use `u_root == u_seq` to compare the parallel and the sequential result?
|
||||
</div>
|
||||
<pre><code>a) The test will still pass.
|
||||
b) The test will fail due to rounding-off errors.
|
||||
c) The test might pass or fail depending on `n`.
|
||||
d) The test might pass or fail depending on the number of MPI ranks.</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=cd2427f1">
|
||||
<div class="jp-Cell-inputWrapper" tabindex="0">
|
||||
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea">
|
||||
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
|
||||
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
|
||||
<div class="cm-editor cm-s-jupyter">
|
||||
<div class="highlight hl-julia"><pre><span></span><span class="n">answer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"x"</span><span class="w"> </span><span class="c"># replace x with a, b, c or d</span>
|
||||
<span class="n">jacobitest_check</span><span class="p">(</span><span class="n">answer</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=790e7064">
|
||||
<div class="jp-Cell-inputWrapper" tabindex="0">
|
||||
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<p>Run cell below for an explanation of the correct answer.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs" id="cell-id=72ed2aa1">
|
||||
<div class="jp-Cell-inputWrapper" tabindex="0">
|
||||
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea">
|
||||
<div class="jp-InputPrompt jp-InputArea-prompt">In [ ]:</div>
|
||||
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
|
||||
<div class="cm-editor cm-s-jupyter">
|
||||
<div class="highlight hl-julia"><pre><span></span><span class="n">jacobitest_why</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=c9aa2901">
|
||||
<div class="jp-Cell-inputWrapper" tabindex="0">
|
||||
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h2 id="Latency-hiding">Latency hiding<a class="anchor-link" href="#Latency-hiding">¶</a></h2><p>Can our implementation above be improved? Note that we only need communications to update the values at the boundary of the portion owned by each process. The other values (the one in green in the figure below) can be updated without communications. This provides the opportunity of overlapping the computation of the interior values (green cells in the figure) with the communication of the ghost values. This technique is called latency hiding, since we are hiding communication latency by overlapping it with computation that we need to do anyway. The actual implementation is left as an exercise (see Exercise 1).</p>
|
||||
<h2 id="Latency-hiding">Latency hiding<a class="anchor-link" href="#Latency-hiding">¶</a></h2><p>We have now a correct parallel implementation. But. can our implementation above be improved? Note that we only need communications to update the values at the boundary of the portion owned by each process. The other values (the one in green in the figure below) can be updated without communications. This provides the opportunity of overlapping the computation of the interior values (green cells in the figure) with the communication of the ghost values. This technique is called latency hiding, since we are hiding communication latency by overlapping it with computation that we need to do anyway. The actual implementation is left as an exercise (see Exercise 1).</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -14,4 +14,4 @@
|
||||
var myIframe = document.getElementById("notebook");
|
||||
iFrameResize({log:true}, myIframe);
|
||||
});
|
||||
</script></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../julia_basics/">« Julia Basics</a><a class="docs-footer-nextpage" href="../julia_distributed/">Distributed computing in Julia »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
</script></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../julia_basics/">« Julia Basics</a><a class="docs-footer-nextpage" href="../julia_distributed/">Distributed computing in Julia »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
@ -14,4 +14,4 @@
|
||||
var myIframe = document.getElementById("notebook");
|
||||
iFrameResize({log:true}, myIframe);
|
||||
});
|
||||
</script></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../getting_started_with_julia/">« Getting started</a><a class="docs-footer-nextpage" href="../julia_async/">Asynchronous programming in Julia »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
</script></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../getting_started_with_julia/">« Getting started</a><a class="docs-footer-nextpage" href="../julia_async/">Asynchronous programming in Julia »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
@ -14,4 +14,4 @@
|
||||
var myIframe = document.getElementById("notebook");
|
||||
iFrameResize({log:true}, myIframe);
|
||||
});
|
||||
</script></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../julia_async/">« Asynchronous programming in Julia</a><a class="docs-footer-nextpage" href="../matrix_matrix/">Matrix-matrix multiplication »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
</script></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../julia_async/">« Asynchronous programming in Julia</a><a class="docs-footer-nextpage" href="../matrix_matrix/">Matrix-matrix multiplication »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
@ -14,4 +14,4 @@
|
||||
var myIframe = document.getElementById("notebook");
|
||||
iFrameResize({log:true}, myIframe);
|
||||
});
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
@ -14,4 +14,4 @@
|
||||
var myIframe = document.getElementById("notebook");
|
||||
iFrameResize({log:true}, myIframe);
|
||||
});
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
@ -75,6 +75,7 @@
|
||||
"- MPI is not a Julia implementation of the MPI standard\n",
|
||||
"- It is just a wrapper to the C interface of MPI.\n",
|
||||
"- You need a C MPI installation in your system (MPI.jl downloads one for you when needed).\n",
|
||||
"- On a cluster (e.g. DAS-5), you want you use the MPI installation already available in the system.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"### Why MPI.jl?\n",
|
||||
@ -211,7 +212,7 @@
|
||||
"MPI.Finalize()\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"In some process `rand(1:10)` might be 2 and the program will stop without reaching `MPI.Finalize()` leading to an incorrect program."
|
||||
"This is incorrect. In some process `rand(1:10)` might be 2 and the program will stop without reaching `MPI.Finalize()` leading to an incorrect program."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -367,7 +368,7 @@
|
||||
"id": "f1a502a3",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Note that this note notebook is running on a single process. So using MPI will only make sense later when we add more processes."
|
||||
"Note that this note notebook is running on a single process. So using MPI will only make actual sense later when we add more processes."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -626,13 +627,13 @@
|
||||
"source": [
|
||||
"## Point-to-point communication\n",
|
||||
"\n",
|
||||
"Now we are up and running, and ready to start learning MPI communication primitives. In this notebook we will cover so-called point-to-point communication directives. In a later notebook we will also learn about collective primitives.\n",
|
||||
"Now we are up and running, and ready to start learning MPI communication primitives. In this notebook we will cover so-called point-to-point communication. In a later notebook we will also learn about collective primitives.\n",
|
||||
"\n",
|
||||
"MPI provides point-to-point communication directives for arbitrary communication between processes. Point-to-point communications are two-sided: there is a sender and a receiver. Here, we will discuss different types of directives:\n",
|
||||
"\n",
|
||||
"- `MPI_Send`, and `MPI_Recv` (*blocking directives*)\n",
|
||||
"- `MPI_Isend`, and `MPI_Irecv` (*non-blocking directives*)\n",
|
||||
"- `MPI_Bsend`, `MPI_Ssend`, and `MPI_Rsend` (*advanced communication modes*)"
|
||||
"- `MPI_Send`, and `MPI_Recv`: *complete (blocking) directives*\n",
|
||||
"- `MPI_Isend`, and `MPI_Irecv`: *incomplete (non-blocking) directives*\n",
|
||||
"- `MPI_Bsend`, `MPI_Ssend`, and `MPI_Rsend`: *advanced communication modes*"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -640,7 +641,7 @@
|
||||
"id": "0e515109",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"In all cases, these functions are used to send a message from a ranks and receive it in another rank. See next picture."
|
||||
"In all cases, these functions are used to send a message from a rank and receive it in another rank. See next picture."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -979,7 +980,7 @@
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"`MPI_Send` is also often called a blocking send, but this is very misleading. `MPI_Send` might or not wait for a matching `MPI_Recv`. Assuming that `MPI_Send` will block waiting for a matching receive is erroneous. I.e., we cannot assume that `MPI_Send` has synchronization side effects with the receiver process. However, assuming that `MPI_Send` will not block is also erroneous. Look into the following example (which in fact is an incorrect MPI program). In contrast, `MPI_Send` guarantees that the send buffer can be reused when function returns (complete operation)."
|
||||
"`MPI_Send` is *informally* called a blocking send, but this is not accurate. `MPI_Send` might or not wait for a matching `MPI_Recv`. Assuming that `MPI_Send` will block waiting for a matching receive is erroneous. I.e., we cannot assume that `MPI_Send` has synchronization side effects with the receiver process. However, assuming that `MPI_Send` will not block is also erroneous. Look into the following example (which in fact is an incorrect MPI program). `MPI_Send` only guarantees that the send buffer can be reused when function returns (complete operation)."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -1042,7 +1043,7 @@
|
||||
"1. One might want to minimize synchronization time. This is often achieved by copying the outgoing message in an internal buffer and returning from the `MPI_Send` as soon as possible, without waiting for a matching `MPI_Recv`.\n",
|
||||
"2. One might want to avoid data copies (e.g. for large messages). In this case, one needs to wait for a matching receive and return from the `MPI_Send` when the data has been sent.\n",
|
||||
"\n",
|
||||
"Thus, there is a trade-off between memory copied (buffering) and synchronization (wait) time. One cannot minimize both at the same time."
|
||||
"Thus, there is a trade-off between memory copied (buffering) and synchronization (wait) time. One cannot minimize both at the same time unfortunately."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -1497,7 +1498,7 @@
|
||||
"function matmul_mpi_3!(C,A,B)\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"Assume that the input matrices `A` and `B` are given only on rank 0, the other ranks get dummy matrices with zero rows and zero columns to save memory. You need to communicate the required parts to other ranks. For simplicity you can assume that `A` and `B` are square matrices and that the number of rows is a multiple of the number of processes (on rank 0). The result `C` should be overwritten only on rank 0. You can use the following cell to implement and check your result. Copy the code below to a file called `ex1.jl`. Modify the file (e.g. with vscode). Run it from the Julia REPL using the `run` function as explained in the [Getting Started tutorial](https://www.francescverdugo.com/XM_40017/dev/getting_started_with_julia/#Running-MPI-code)."
|
||||
"Assume that the input matrices `A` and `B` are given only on rank 0, the other ranks get dummy empty matrices to save memory. You need to communicate the required parts to other ranks. For simplicity you can assume that `A` and `B` are square matrices and that the number of rows is a multiple of the number of processes (on rank 0). The result `C` should be overwritten only on rank 0. You can use the following cell to implement and check your result. Copy the code below to a file called `ex1.jl`. Modify the file (e.g. with vscode). Run it from the Julia REPL using the `run` function as explained in the [Getting Started tutorial](https://www.francescverdugo.com/XM_40017/dev/getting_started_with_julia/#Running-MPI-code). Don't try to implement complex MPI code in a Jupyter notebook."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@ -14,4 +14,4 @@
|
||||
var myIframe = document.getElementById("notebook");
|
||||
iFrameResize({log:true}, myIframe);
|
||||
});
|
||||
</script></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../matrix_matrix/">« Matrix-matrix multiplication</a><a class="docs-footer-nextpage" href="../mpi_collectives/">MPI (collectives) »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
</script></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../matrix_matrix/">« Matrix-matrix multiplication</a><a class="docs-footer-nextpage" href="../mpi_collectives/">MPI (collectives) »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
@ -7593,6 +7593,7 @@ a.anchor-link {
|
||||
<li>MPI is not a Julia implementation of the MPI standard</li>
|
||||
<li>It is just a wrapper to the C interface of MPI.</li>
|
||||
<li>You need a C MPI installation in your system (MPI.jl downloads one for you when needed).</li>
|
||||
<li>On a cluster (e.g. DAS-5), you want you use the MPI installation already available in the system.</li>
|
||||
</ul>
|
||||
<h3 id="Why-MPI.jl?">Why MPI.jl?<a class="anchor-link" href="#Why-MPI.jl?">¶</a></h3><p>MPI.jl provides a convenient Julia API to access MPI. For instance, this is how you get the id (rank) of the current process.</p>
|
||||
<div class="highlight"><pre><span></span><span class="n">comm</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MPI</span><span class="o">.</span><span class="n">COMM_WORLD</span>
|
||||
@ -7727,7 +7728,7 @@ a.anchor-link {
|
||||
<span class="nd">@assert</span><span class="w"> </span><span class="n">rand</span><span class="p">(</span><span class="mi">1</span><span class="o">:</span><span class="mi">10</span><span class="p">)</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">2</span>
|
||||
<span class="n">MPI</span><span class="o">.</span><span class="n">Finalize</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
<p>In some process <code>rand(1:10)</code> might be 2 and the program will stop without reaching <code>MPI.Finalize()</code> leading to an incorrect program.</p>
|
||||
<p>This is incorrect. In some process <code>rand(1:10)</code> might be 2 and the program will stop without reaching <code>MPI.Finalize()</code> leading to an incorrect program.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -7925,7 +7926,7 @@ a.anchor-link {
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<p>Note that this note notebook is running on a single process. So using MPI will only make sense later when we add more processes.</p>
|
||||
<p>Note that this note notebook is running on a single process. So using MPI will only make actual sense later when we add more processes.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -8231,12 +8232,12 @@ a.anchor-link {
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h2 id="Point-to-point-communication">Point-to-point communication<a class="anchor-link" href="#Point-to-point-communication">¶</a></h2><p>Now we are up and running, and ready to start learning MPI communication primitives. In this notebook we will cover so-called point-to-point communication directives. In a later notebook we will also learn about collective primitives.</p>
|
||||
<h2 id="Point-to-point-communication">Point-to-point communication<a class="anchor-link" href="#Point-to-point-communication">¶</a></h2><p>Now we are up and running, and ready to start learning MPI communication primitives. In this notebook we will cover so-called point-to-point communication. In a later notebook we will also learn about collective primitives.</p>
|
||||
<p>MPI provides point-to-point communication directives for arbitrary communication between processes. Point-to-point communications are two-sided: there is a sender and a receiver. Here, we will discuss different types of directives:</p>
|
||||
<ul>
|
||||
<li><code>MPI_Send</code>, and <code>MPI_Recv</code> (<em>blocking directives</em>)</li>
|
||||
<li><code>MPI_Isend</code>, and <code>MPI_Irecv</code> (<em>non-blocking directives</em>)</li>
|
||||
<li><code>MPI_Bsend</code>, <code>MPI_Ssend</code>, and <code>MPI_Rsend</code> (<em>advanced communication modes</em>)</li>
|
||||
<li><code>MPI_Send</code>, and <code>MPI_Recv</code>: <em>complete (blocking) directives</em></li>
|
||||
<li><code>MPI_Isend</code>, and <code>MPI_Irecv</code>: <em>incomplete (non-blocking) directives</em></li>
|
||||
<li><code>MPI_Bsend</code>, <code>MPI_Ssend</code>, and <code>MPI_Rsend</code>: <em>advanced communication modes</em></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@ -8248,7 +8249,7 @@ a.anchor-link {
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<p>In all cases, these functions are used to send a message from a ranks and receive it in another rank. See next picture.</p>
|
||||
<p>In all cases, these functions are used to send a message from a rank and receive it in another rank. See next picture.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -8610,7 +8611,7 @@ a.anchor-link {
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h2 id="Blocking-operations">Blocking operations<a class="anchor-link" href="#Blocking-operations">¶</a></h2><p><code>MPI_Recv</code> and <code>MPI_Probe</code> are <em>blocking</em> operations. This means that they will wait for a matching send.</p>
|
||||
<p><code>MPI_Send</code> is also often called a blocking send, but this is very misleading. <code>MPI_Send</code> might or not wait for a matching <code>MPI_Recv</code>. Assuming that <code>MPI_Send</code> will block waiting for a matching receive is erroneous. I.e., we cannot assume that <code>MPI_Send</code> has synchronization side effects with the receiver process. However, assuming that <code>MPI_Send</code> will not block is also erroneous. Look into the following example (which in fact is an incorrect MPI program). In contrast, <code>MPI_Send</code> guarantees that the send buffer can be reused when function returns (complete operation).</p>
|
||||
<p><code>MPI_Send</code> is <em>informally</em> called a blocking send, but this is not accurate. <code>MPI_Send</code> might or not wait for a matching <code>MPI_Recv</code>. Assuming that <code>MPI_Send</code> will block waiting for a matching receive is erroneous. I.e., we cannot assume that <code>MPI_Send</code> has synchronization side effects with the receiver process. However, assuming that <code>MPI_Send</code> will not block is also erroneous. Look into the following example (which in fact is an incorrect MPI program). <code>MPI_Send</code> only guarantees that the send buffer can be reused when function returns (complete operation).</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -8682,7 +8683,7 @@ a.anchor-link {
|
||||
<li>One might want to minimize synchronization time. This is often achieved by copying the outgoing message in an internal buffer and returning from the <code>MPI_Send</code> as soon as possible, without waiting for a matching <code>MPI_Recv</code>.</li>
|
||||
<li>One might want to avoid data copies (e.g. for large messages). In this case, one needs to wait for a matching receive and return from the <code>MPI_Send</code> when the data has been sent.</li>
|
||||
</ol>
|
||||
<p>Thus, there is a trade-off between memory copied (buffering) and synchronization (wait) time. One cannot minimize both at the same time.</p>
|
||||
<p>Thus, there is a trade-off between memory copied (buffering) and synchronization (wait) time. One cannot minimize both at the same time unfortunately.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -9171,7 +9172,7 @@ a.anchor-link {
|
||||
<h3 id="Exercise-1">Exercise 1<a class="anchor-link" href="#Exercise-1">¶</a></h3><p>Implement the parallel matrix-matrix multiplication (Algorithm 3) in previous notebook using MPI instead of <code>Distributed</code>. Use this function signature:</p>
|
||||
<div class="highlight"><pre><span></span><span class="k">function</span><span class="w"> </span><span class="n">matmul_mpi_3!</span><span class="p">(</span><span class="n">C</span><span class="p">,</span><span class="n">A</span><span class="p">,</span><span class="n">B</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
<p>Assume that the input matrices <code>A</code> and <code>B</code> are given only on rank 0, the other ranks get dummy matrices with zero rows and zero columns to save memory. You need to communicate the required parts to other ranks. For simplicity you can assume that <code>A</code> and <code>B</code> are square matrices and that the number of rows is a multiple of the number of processes (on rank 0). The result <code>C</code> should be overwritten only on rank 0. You can use the following cell to implement and check your result. Copy the code below to a file called <code>ex1.jl</code>. Modify the file (e.g. with vscode). Run it from the Julia REPL using the <code>run</code> function as explained in the <a href="https://www.francescverdugo.com/XM_40017/dev/getting_started_with_julia/#Running-MPI-code">Getting Started tutorial</a>.</p>
|
||||
<p>Assume that the input matrices <code>A</code> and <code>B</code> are given only on rank 0, the other ranks get dummy empty matrices to save memory. You need to communicate the required parts to other ranks. For simplicity you can assume that <code>A</code> and <code>B</code> are square matrices and that the number of rows is a multiple of the number of processes (on rank 0). The result <code>C</code> should be overwritten only on rank 0. You can use the following cell to implement and check your result. Copy the code below to a file called <code>ex1.jl</code>. Modify the file (e.g. with vscode). Run it from the Julia REPL using the <code>run</code> function as explained in the <a href="https://www.francescverdugo.com/XM_40017/dev/getting_started_with_julia/#Running-MPI-code">Getting Started tutorial</a>. Don't try to implement complex MPI code in a Jupyter notebook.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -14,4 +14,4 @@
|
||||
var myIframe = document.getElementById("notebook");
|
||||
iFrameResize({log:true}, myIframe);
|
||||
});
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
@ -14,4 +14,4 @@
|
||||
var myIframe = document.getElementById("notebook");
|
||||
iFrameResize({log:true}, myIframe);
|
||||
});
|
||||
</script></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../julia_distributed/">« Distributed computing in Julia</a><a class="docs-footer-nextpage" href="../julia_mpi/">MPI (point-to-point) »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
</script></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../julia_distributed/">« Distributed computing in Julia</a><a class="docs-footer-nextpage" href="../julia_mpi/">MPI (point-to-point) »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
@ -97,7 +97,7 @@
|
||||
"source": [
|
||||
"## MPI_Barrier\n",
|
||||
"\n",
|
||||
"This function is used to synchronizes a group of processes. All processes block until all have reached the barrier. It is often invoked at the end of for loops to make sure all processes have finished the current loop iteration to move to the next one. We will see an example later in another notebook when studying the traveling sales person problem (TSP).\n",
|
||||
"This function is used to synchronizes a group of processes. All processes block until all have reached the barrier. It is often invoked at the end of for loops to make sure all processes have finished the current loop iteration to move to the next one. We will see a practical example later in another notebook when studying the traveling sales person problem (TSP).\n",
|
||||
"\n",
|
||||
"In Julia:\n",
|
||||
"```julia\n",
|
||||
@ -117,7 +117,7 @@
|
||||
"source": [
|
||||
"### Example\n",
|
||||
"\n",
|
||||
"In this example the ranks sleep for a random amount of time and then they call barrier. It is guaranteed that the message \"Done!\" will be printed after all processes printed \"I woke up\" since we used a barrier. Try also to comment out the call to `MPI.Barrier`. You will see that the message can be printed in any order in this case."
|
||||
"In this example the ranks sleep for a random amount of time and then they call barrier. It is guaranteed that the message \"Done!\" will be printed after all processes printed \"I woke up\" since we used a barrier. Try also to comment out the call to `MPI.Barrier`. You will see that the message can be printed in any order."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -147,7 +147,7 @@
|
||||
"source": [
|
||||
"## MPI_Reduce\n",
|
||||
"\n",
|
||||
"This function combines values provided by different processors according to a given reduction operation. The result is received in a single process (called the root process).\n",
|
||||
"This function combines values provided by different processors according to a given reduction operation. The result is received in a single process (called the root process). The root process can be any process and it is rank 0 by default in Julia.\n",
|
||||
"\n",
|
||||
"In Julia:\n",
|
||||
"```julia\n",
|
||||
@ -301,7 +301,12 @@
|
||||
"source": [
|
||||
"## MPI_Gather\n",
|
||||
"\n",
|
||||
"Each rank sends a message to the root rank (the root rank also sends a message to itself). The root rank receives all these values in a buffer (e.g. a vector). This function assumes that the amount of data sent from each rank is the same. The root process can be any process and it is rank 0 by default in Julia.\n",
|
||||
"Each rank sends a message to the root rank (the root rank also sends a message to itself). The root rank receives all these values in a buffer (e.g. a vector).\n",
|
||||
"\n",
|
||||
"<div class=\"alert alert-block alert-info\">\n",
|
||||
"<b>Note:</b> This function assumes that the amount of data sent from each rank is the same. See `MPI_Gatherv` below for more general cases.\n",
|
||||
"</div>\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"In Julia:\n",
|
||||
"```julia\n",
|
||||
@ -487,7 +492,7 @@
|
||||
"source": [
|
||||
"### Example\n",
|
||||
"\n",
|
||||
"Each process sends a random amount of integers to rank 0."
|
||||
"Each process sends a random amount of integers to rank 0. The root process will not know the amount of data to be gathered from each rank in advance. We need an auxiliary gather to inform about the message size."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -898,6 +903,24 @@
|
||||
"After learning this material and the previous MPI notebook, you have a solid basis to start implementing sophisticated parallel algorithms using MPI."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "843b40cd",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Exercises"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "5c2045d9",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Exercise 1\n",
|
||||
"\n",
|
||||
"Implement the parallel matrix-matrix multiplication (Algorithm 3) using MPI collectives instead of point-to-point communication. I.e., this is the same exercise as in previous notebook, but using different functions for communication."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "5e8f6e6a",
|
||||
|
||||
@ -14,4 +14,4 @@
|
||||
var myIframe = document.getElementById("notebook");
|
||||
iFrameResize({log:true}, myIframe);
|
||||
});
|
||||
</script></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../julia_mpi/">« MPI (point-to-point)</a><a class="docs-footer-nextpage" href="../jacobi_method/">Jacobi method »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
</script></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../julia_mpi/">« MPI (point-to-point)</a><a class="docs-footer-nextpage" href="../jacobi_method/">Jacobi method »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
@ -7614,7 +7614,7 @@ a.anchor-link {
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h2 id="MPI_Barrier">MPI_Barrier<a class="anchor-link" href="#MPI_Barrier">¶</a></h2><p>This function is used to synchronizes a group of processes. All processes block until all have reached the barrier. It is often invoked at the end of for loops to make sure all processes have finished the current loop iteration to move to the next one. We will see an example later in another notebook when studying the traveling sales person problem (TSP).</p>
|
||||
<h2 id="MPI_Barrier">MPI_Barrier<a class="anchor-link" href="#MPI_Barrier">¶</a></h2><p>This function is used to synchronizes a group of processes. All processes block until all have reached the barrier. It is often invoked at the end of for loops to make sure all processes have finished the current loop iteration to move to the next one. We will see a practical example later in another notebook when studying the traveling sales person problem (TSP).</p>
|
||||
<p>In Julia:</p>
|
||||
<div class="highlight"><pre><span></span><span class="n">MPI</span><span class="o">.</span><span class="n">Barrier</span><span class="p">(</span><span class="n">comm</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
@ -7631,7 +7631,7 @@ a.anchor-link {
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h3 id="Example">Example<a class="anchor-link" href="#Example">¶</a></h3><p>In this example the ranks sleep for a random amount of time and then they call barrier. It is guaranteed that the message "Done!" will be printed after all processes printed "I woke up" since we used a barrier. Try also to comment out the call to <code>MPI.Barrier</code>. You will see that the message can be printed in any order in this case.</p>
|
||||
<h3 id="Example">Example<a class="anchor-link" href="#Example">¶</a></h3><p>In this example the ranks sleep for a random amount of time and then they call barrier. It is guaranteed that the message "Done!" will be printed after all processes printed "I woke up" since we used a barrier. Try also to comment out the call to <code>MPI.Barrier</code>. You will see that the message can be printed in any order.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -7666,7 +7666,7 @@ a.anchor-link {
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h2 id="MPI_Reduce">MPI_Reduce<a class="anchor-link" href="#MPI_Reduce">¶</a></h2><p>This function combines values provided by different processors according to a given reduction operation. The result is received in a single process (called the root process).</p>
|
||||
<h2 id="MPI_Reduce">MPI_Reduce<a class="anchor-link" href="#MPI_Reduce">¶</a></h2><p>This function combines values provided by different processors according to a given reduction operation. The result is received in a single process (called the root process). The root process can be any process and it is rank 0 by default in Julia.</p>
|
||||
<p>In Julia:</p>
|
||||
<div class="highlight"><pre><span></span><span class="n">MPI</span><span class="o">.</span><span class="n">Reduce!</span><span class="p">(</span><span class="n">sendbuf</span><span class="p">,</span><span class="w"> </span><span class="n">recvbuf</span><span class="p">,</span><span class="w"> </span><span class="n">op</span><span class="p">,</span><span class="w"> </span><span class="n">comm</span><span class="p">;</span><span class="w"> </span><span class="n">root</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
@ -7832,7 +7832,10 @@ a.anchor-link {
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h2 id="MPI_Gather">MPI_Gather<a class="anchor-link" href="#MPI_Gather">¶</a></h2><p>Each rank sends a message to the root rank (the root rank also sends a message to itself). The root rank receives all these values in a buffer (e.g. a vector). This function assumes that the amount of data sent from each rank is the same. The root process can be any process and it is rank 0 by default in Julia.</p>
|
||||
<h2 id="MPI_Gather">MPI_Gather<a class="anchor-link" href="#MPI_Gather">¶</a></h2><p>Each rank sends a message to the root rank (the root rank also sends a message to itself). The root rank receives all these values in a buffer (e.g. a vector).</p>
|
||||
<div class="alert alert-block alert-info">
|
||||
<b>Note:</b> This function assumes that the amount of data sent from each rank is the same. See `MPI_Gatherv` below for more general cases.
|
||||
</div>
|
||||
<p>In Julia:</p>
|
||||
<div class="highlight"><pre><span></span><span class="n">MPI</span><span class="o">.</span><span class="n">Gather!</span><span class="p">(</span><span class="n">sendbuf</span><span class="p">,</span><span class="w"> </span><span class="n">recvbuf</span><span class="p">,</span><span class="w"> </span><span class="n">comm</span><span class="p">;</span><span class="w"> </span><span class="n">root</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
@ -8033,7 +8036,7 @@ a.anchor-link {
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h3 id="Example">Example<a class="anchor-link" href="#Example">¶</a></h3><p>Each process sends a random amount of integers to rank 0.</p>
|
||||
<h3 id="Example">Example<a class="anchor-link" href="#Example">¶</a></h3><p>Each process sends a random amount of integers to rank 0. The root process will not know the amount of data to be gathered from each rank in advance. We need an auxiliary gather to inform about the message size.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -8451,6 +8454,28 @@ a.anchor-link {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=843b40cd">
|
||||
<div class="jp-Cell-inputWrapper" tabindex="0">
|
||||
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h2 id="Exercises">Exercises<a class="anchor-link" href="#Exercises">¶</a></h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=5c2045d9">
|
||||
<div class="jp-Cell-inputWrapper" tabindex="0">
|
||||
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
||||
</div>
|
||||
<div class="jp-InputArea jp-Cell-inputArea"><div class="jp-InputPrompt jp-InputArea-prompt">
|
||||
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput" data-mime-type="text/markdown">
|
||||
<h3 id="Exercise-1">Exercise 1<a class="anchor-link" href="#Exercise-1">¶</a></h3><p>Implement the parallel matrix-matrix multiplication (Algorithm 3) using MPI collectives instead of point-to-point communication. I.e., this is the same exercise as in previous notebook, but using different functions for communication.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="jp-Cell jp-MarkdownCell jp-Notebook-cell" id="cell-id=5e8f6e6a">
|
||||
<div class="jp-Cell-inputWrapper" tabindex="0">
|
||||
<div class="jp-Collapser jp-InputCollapser jp-Cell-inputCollapser">
|
||||
|
||||
@ -14,4 +14,4 @@
|
||||
var myIframe = document.getElementById("notebook");
|
||||
iFrameResize({log:true}, myIframe);
|
||||
});
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
@ -14,4 +14,4 @@
|
||||
var myIframe = document.getElementById("notebook");
|
||||
iFrameResize({log:true}, myIframe);
|
||||
});
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
@ -14,4 +14,4 @@
|
||||
var myIframe = document.getElementById("notebook");
|
||||
iFrameResize({log:true}, myIframe);
|
||||
});
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
@ -14,4 +14,4 @@
|
||||
var myIframe = document.getElementById("notebook");
|
||||
iFrameResize({log:true}, myIframe);
|
||||
});
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
@ -172,4 +172,4 @@ end</code></pre><h2 id="Jacobi-method"><a class="docs-heading-anchor" href="#Jac
|
||||
end
|
||||
end
|
||||
return u_all
|
||||
end</code></pre></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../jacobi_method/">« Jacobi method</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
end</code></pre></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../jacobi_method/">« Jacobi method</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
@ -14,4 +14,4 @@
|
||||
var myIframe = document.getElementById("notebook");
|
||||
iFrameResize({log:true}, myIframe);
|
||||
});
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 9 September 2024 15:08">Monday 9 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
</script></article><nav class="docs-footer"><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Wednesday 11 September 2024 08:58">Wednesday 11 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user