mirror of
https://github.com/fverdugo/XM_40017.git
synced 2025-11-12 17:24:24 +01:00
Merge branch 'main' of github.com:fverdugo/XM_40017 into main
This commit is contained in:
commit
fbb7423b65
6
docs/.gitignore
vendored
6
docs/.gitignore
vendored
@ -1,7 +1,5 @@
|
|||||||
build/
|
build/
|
||||||
site/
|
site/
|
||||||
docs/src/notebook-output
|
docs/src/notebook-output/
|
||||||
|
docs/src/notebooks/
|
||||||
Manifest.toml
|
Manifest.toml
|
||||||
*.md
|
|
||||||
!index.md
|
|
||||||
!getting_started_with_julia.md
|
|
||||||
54
docs/make.jl
54
docs/make.jl
@ -13,7 +13,7 @@ EditURL = "https://github.com/fverdugo/XM_40017/blob/main/docs/src/notebooks/SCR
|
|||||||
<div class="admonition-body">
|
<div class="admonition-body">
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
Download this notebook and run it locally on your machine [recommended]. Click <a href="notebooks/SCRIPT_NAME.ipynb" download>here</a>.
|
Download this notebook and run it locally on your machine [recommended]. Click <a href="SCRIPT_NAME.ipynb" download>here</a>.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
You can also run this notebook in the cloud using Binder. Click <a href="https://mybinder.org/v2/gh/fverdugo/XM_40017/gh-pages?filepath=dev/notebooks/SCRIPT_NAME.ipynb">here</a>
|
You can also run this notebook in the cloud using Binder. Click <a href="https://mybinder.org/v2/gh/fverdugo/XM_40017/gh-pages?filepath=dev/notebooks/SCRIPT_NAME.ipynb">here</a>
|
||||||
@ -25,7 +25,7 @@ EditURL = "https://github.com/fverdugo/XM_40017/blob/main/docs/src/notebooks/SCR
|
|||||||
```
|
```
|
||||||
|
|
||||||
```@raw html
|
```@raw html
|
||||||
<iframe id="notebook" src="../notebook-output/SCRIPT_NAME.html" style="width:100%"></iframe>
|
<iframe id="notebook" src="../notebook-html/SCRIPT_NAME.html" style="width:100%"></iframe>
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function(){
|
document.addEventListener('DOMContentLoaded', function(){
|
||||||
var myIframe = document.getElementById("notebook");
|
var myIframe = document.getElementById("notebook");
|
||||||
@ -47,17 +47,15 @@ function convert_embedded_img_to_base64(notebook_path)
|
|||||||
base64 = m[:base64code]
|
base64 = m[:base64code]
|
||||||
doc = replace(doc, "attachment:$filename.png" => "data:image/png;base64,$base64")
|
doc = replace(doc, "attachment:$filename.png" => "data:image/png;base64,$base64")
|
||||||
end
|
end
|
||||||
|
filename = splitpath(notebook_path)[end]
|
||||||
write(notebook_path, doc);
|
write("docs/src/notebooks/$filename", doc);
|
||||||
end
|
end
|
||||||
|
|
||||||
# Write markdown file that includes notebook html
|
# Write markdown file that includes notebook html
|
||||||
function create_md_nb_file( notebook_path )
|
function create_md_nb_file( filename )
|
||||||
global md_nb_template;
|
global md_nb_template;
|
||||||
script_file = splitpath(notebook_path)[end]
|
content = replace(md_nb_template, "SCRIPT_NAME" => filename)
|
||||||
script_name = splitext(script_file)[1]
|
md_path = joinpath(@__DIR__, "src/notebooks", filename * ".md" )
|
||||||
content = replace(md_nb_template, "SCRIPT_NAME" => script_name)
|
|
||||||
md_path = joinpath(@__DIR__, "src", script_name * ".md" )
|
|
||||||
open(md_path, "w") do md_file
|
open(md_path, "w") do md_file
|
||||||
write(md_file, content)
|
write(md_file, content)
|
||||||
end
|
end
|
||||||
@ -65,7 +63,7 @@ function create_md_nb_file( notebook_path )
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Convert to html using nbconvert
|
# Convert to html using nbconvert
|
||||||
function convert_notebook_to_html(notebook_path; output_name = "index", output_dir = "./docs/src/notebook-output", theme = "light")
|
function convert_notebook_to_html(notebook_path; output_name = "index", output_dir = "./docs/src/notebook-html", theme = "light")
|
||||||
command_jup = "jupyter"
|
command_jup = "jupyter"
|
||||||
command_nbc = "nbconvert"
|
command_nbc = "nbconvert"
|
||||||
output_format = "--to=html"
|
output_format = "--to=html"
|
||||||
@ -76,39 +74,33 @@ function convert_notebook_to_html(notebook_path; output_name = "index", output_d
|
|||||||
run(`$command_jup $command_nbc $output_format $output $output_dir $theme $infile`)
|
run(`$command_jup $command_nbc $output_format $output $output_dir $theme $infile`)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Resize iframes using IframeResizer
|
# Modify html contents
|
||||||
function modify_notebook_html( html_name )
|
function modify_notebook_html( html_filepath )
|
||||||
content = open( html_name, "r" ) do html_file
|
content = open( html_filepath, "r" ) do html_file
|
||||||
read( html_file, String )
|
read( html_file, String )
|
||||||
end
|
end
|
||||||
|
# Resize iframes using IframeResizer
|
||||||
content = replace(content,
|
content = replace(content,
|
||||||
r"(<script\b[^>]*>[\s\S]*?<\/script>\K)" =>
|
r"(<script\b[^>]*>[\s\S]*?<\/script>\K)" =>
|
||||||
s"\1\n\t<script src='../assets/iframeResizer.contentWindow.min.js'></script>\n";
|
s"\1\n\t<script src='../assets/iframeResizer.contentWindow.min.js'></script>\n";
|
||||||
count = 1
|
count = 1
|
||||||
)
|
)
|
||||||
content = replace_colors(content)
|
open( html_filepath, "w" ) do html_file
|
||||||
open( html_name, "w" ) do html_file
|
|
||||||
write( html_file, content )
|
write( html_file, content )
|
||||||
end
|
end
|
||||||
return nothing
|
return nothing
|
||||||
end
|
end
|
||||||
|
|
||||||
# Replace colors to match Documenter.jl
|
|
||||||
function replace_colors(content)
|
|
||||||
#content = replace( content, "--jp-layout-color0: #111111;" => "--jp-layout-color0: #1f2424;")
|
|
||||||
#content = replace(content, "--md-grey-900: #212121;" => "--md-grey-900: #282f2f;")
|
|
||||||
return content
|
|
||||||
end
|
|
||||||
|
|
||||||
# Loop over notebooks and generate html and markdown
|
# Loop over notebooks and generate html and markdown
|
||||||
notebook_files = glob("*.ipynb", "docs/src/notebooks/")
|
notebook_files = glob("*.ipynb", "notebooks/")
|
||||||
for filepath in notebook_files
|
for filepath in notebook_files
|
||||||
convert_embedded_img_to_base64(filepath)
|
convert_embedded_img_to_base64(filepath)
|
||||||
create_md_nb_file(filepath)
|
|
||||||
filename_with_ext = splitpath(filepath)[end]
|
filename_with_ext = splitpath(filepath)[end]
|
||||||
filename = splitext(filename_with_ext)[1]
|
filename = splitext(filename_with_ext)[1]
|
||||||
convert_notebook_to_html(filepath, output_name = filename)
|
create_md_nb_file(filename)
|
||||||
modify_notebook_html("docs/src/notebook-output/$(filename).html")
|
convert_notebook_to_html("docs/src/notebooks/$filename_with_ext", output_name = filename)
|
||||||
|
modify_notebook_html("docs/src/notebook-html/$(filename).html")
|
||||||
end
|
end
|
||||||
|
|
||||||
makedocs(;
|
makedocs(;
|
||||||
@ -122,12 +114,12 @@ makedocs(;
|
|||||||
canonical="https://fverdugo.github.io/XM_40017",
|
canonical="https://fverdugo.github.io/XM_40017",
|
||||||
edit_link="main",),
|
edit_link="main",),
|
||||||
pages=["Home" => "index.md","Getting started"=>"getting_started_with_julia.md", "Notebooks"=>[
|
pages=["Home" => "index.md","Getting started"=>"getting_started_with_julia.md", "Notebooks"=>[
|
||||||
"Julia Basics" => "julia_basics.md",
|
"Julia Basics" => "notebooks/julia_basics.md",
|
||||||
"Tasks and channels" => "julia_async.md",
|
"Tasks and channels" => "notebooks/julia_async.md",
|
||||||
"Remote calls and remote channels" => "julia_distributed.md",
|
"Remote calls and remote channels" => "notebooks/julia_distributed.md",
|
||||||
"Matrix Multiplication"=>"matrix_matrix.md",
|
"Matrix Multiplication"=>"notebooks/matrix_matrix.md",
|
||||||
"Jacobi" => "jacobi_method.md",
|
"Jacobi" => "notebooks/jacobi_method.md",
|
||||||
"Solutions" => "sol_matrix_matrix.md"
|
"Solutions" => "notebooks/sol_matrix_matrix.md"
|
||||||
]],
|
]],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
# Getting started
|
# Getting started
|
||||||
|
|
||||||
|
|
||||||
@ -381,4 +380,3 @@ We have learned the basics of how to work with Julia. If you want to further dig
|
|||||||
- [Package manager](https://pkgdocs.julialang.org/v1/getting-started/)
|
- [Package manager](https://pkgdocs.julialang.org/v1/getting-started/)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,30 +0,0 @@
|
|||||||
```@meta
|
|
||||||
EditURL = "https://github.com/fverdugo/XM_40017/blob/main/docs/src/notebooks/jacobi_2D.ipynb"
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<div class="admonition is-success">
|
|
||||||
<header class="admonition-header">Tip</header>
|
|
||||||
<div class="admonition-body">
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Download this notebook and run it locally on your machine [recommended]. Click <a href="notebooks/jacobi_2D.ipynb" download>here</a>.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
You can also run this notebook in the cloud using Binder. Click <a href="https://mybinder.org/v2/gh/fverdugo/XM_40017/gh-pages?filepath=dev/notebooks/jacobi_2D.ipynb">here</a>
|
|
||||||
.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<iframe id="notebook" src="../notebook-output/jacobi_2D.html" style="width:100%"></iframe>
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function(){
|
|
||||||
var myIframe = document.getElementById("notebook");
|
|
||||||
iFrameResize({log:true}, myIframe);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
```@meta
|
|
||||||
EditURL = "https://github.com/fverdugo/XM_40017/blob/main/docs/src/notebooks/julia_async.ipynb"
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<div class="admonition is-success">
|
|
||||||
<header class="admonition-header">Tip</header>
|
|
||||||
<div class="admonition-body">
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Download this notebook and run it locally on your machine [recommended]. Click <a href="notebooks/julia_async.ipynb" download>here</a>.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
You can also run this notebook in the cloud using Binder. Click <a href="https://mybinder.org/v2/gh/fverdugo/XM_40017/gh-pages?filepath=dev/notebooks/julia_async.ipynb">here</a>
|
|
||||||
.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<iframe id="notebook" src="../notebook-output/julia_async.html" style="width:100%"></iframe>
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function(){
|
|
||||||
var myIframe = document.getElementById("notebook");
|
|
||||||
iFrameResize({log:true}, myIframe);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
```@meta
|
|
||||||
EditURL = "https://github.com/fverdugo/XM_40017/blob/main/docs/src/notebooks/julia_basics.ipynb"
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<div class="admonition is-success">
|
|
||||||
<header class="admonition-header">Tip</header>
|
|
||||||
<div class="admonition-body">
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Download this notebook and run it locally on your machine [recommended]. Click <a href="notebooks/julia_basics.ipynb" download>here</a>.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
You can also run this notebook in the cloud using Binder. Click <a href="https://mybinder.org/v2/gh/fverdugo/XM_40017/gh-pages?filepath=dev/notebooks/julia_basics.ipynb">here</a>
|
|
||||||
.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<iframe id="notebook" src="../notebook-output/julia_basics.html" style="width:100%"></iframe>
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function(){
|
|
||||||
var myIframe = document.getElementById("notebook");
|
|
||||||
iFrameResize({log:true}, myIframe);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
```@meta
|
|
||||||
EditURL = "https://github.com/fverdugo/XM_40017/blob/main/docs/src/notebooks/julia_distributed.ipynb"
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<div class="admonition is-success">
|
|
||||||
<header class="admonition-header">Tip</header>
|
|
||||||
<div class="admonition-body">
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Download this notebook and run it locally on your machine [recommended]. Click <a href="notebooks/julia_distributed.ipynb" download>here</a>.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
You can also run this notebook in the cloud using Binder. Click <a href="https://mybinder.org/v2/gh/fverdugo/XM_40017/gh-pages?filepath=dev/notebooks/julia_distributed.ipynb">here</a>
|
|
||||||
.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<iframe id="notebook" src="../notebook-output/julia_distributed.html" style="width:100%"></iframe>
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function(){
|
|
||||||
var myIframe = document.getElementById("notebook");
|
|
||||||
iFrameResize({log:true}, myIframe);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
```@meta
|
|
||||||
EditURL = "https://github.com/fverdugo/XM_40017/blob/main/docs/src/notebooks/julia_distributed_test.ipynb"
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<div class="admonition is-success">
|
|
||||||
<header class="admonition-header">Tip</header>
|
|
||||||
<div class="admonition-body">
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Download this notebook and run it locally on your machine [recommended]. Click <a href="notebooks/julia_distributed_test.ipynb" download>here</a>.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
You can also run this notebook in the cloud using Binder. Click <a href="https://mybinder.org/v2/gh/fverdugo/XM_40017/gh-pages?filepath=dev/notebooks/julia_distributed_test.ipynb">here</a>
|
|
||||||
.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<iframe id="notebook" src="../notebook-output/julia_distributed_test.html" style="width:100%"></iframe>
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function(){
|
|
||||||
var myIframe = document.getElementById("notebook");
|
|
||||||
iFrameResize({log:true}, myIframe);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
```@meta
|
|
||||||
EditURL = "https://github.com/fverdugo/XM_40017/blob/main/docs/src/notebooks/julia_intro.ipynb"
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<div class="admonition is-success">
|
|
||||||
<header class="admonition-header">Tip</header>
|
|
||||||
<div class="admonition-body">
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Download this notebook and run it locally on your machine [recommended]. Click <a href="notebooks/julia_intro.ipynb" download>here</a>.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
You can also run this notebook in the cloud using Binder. Click <a href="https://mybinder.org/v2/gh/fverdugo/XM_40017/gh-pages?filepath=dev/notebooks/julia_intro.ipynb">here</a>
|
|
||||||
.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<iframe id="notebook" src="../notebook-output/julia_intro.html" style="width:100%"></iframe>
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function(){
|
|
||||||
var myIframe = document.getElementById("notebook");
|
|
||||||
iFrameResize({log:true}, myIframe);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
```@meta
|
|
||||||
EditURL = "https://github.com/fverdugo/XM_40017/blob/main/docs/src/notebooks/julia_jacobi.ipynb"
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<div class="admonition is-success">
|
|
||||||
<header class="admonition-header">Tip</header>
|
|
||||||
<div class="admonition-body">
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Download this notebook and run it locally on your machine [recommended]. Click <a href="notebooks/julia_jacobi.ipynb" download>here</a>.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
You can also run this notebook in the cloud using Binder. Click <a href="https://mybinder.org/v2/gh/fverdugo/XM_40017/gh-pages?filepath=dev/notebooks/julia_jacobi.ipynb">here</a>
|
|
||||||
.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<iframe id="notebook" src="../notebook-output/julia_jacobi.html" style="width:100%"></iframe>
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function(){
|
|
||||||
var myIframe = document.getElementById("notebook");
|
|
||||||
iFrameResize({log:true}, myIframe);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
```@meta
|
|
||||||
EditURL = "https://github.com/fverdugo/XM_40017/blob/main/docs/src/notebooks/julia_tutorial.ipynb"
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<div class="admonition is-success">
|
|
||||||
<header class="admonition-header">Tip</header>
|
|
||||||
<div class="admonition-body">
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Download this notebook and run it locally on your machine [recommended]. Click <a href="notebooks/julia_tutorial.ipynb" download>here</a>.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
You can also run this notebook in the cloud using Binder. Click <a href="https://mybinder.org/v2/gh/fverdugo/XM_40017/gh-pages?filepath=dev/notebooks/julia_tutorial.ipynb">here</a>
|
|
||||||
.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<iframe id="notebook" src="../notebook-output/julia_tutorial.html" style="width:100%"></iframe>
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function(){
|
|
||||||
var myIframe = document.getElementById("notebook");
|
|
||||||
iFrameResize({log:true}, myIframe);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
```@meta
|
|
||||||
EditURL = "https://github.com/fverdugo/XM_40017/blob/main/docs/src/notebooks/matrix_matrix.ipynb"
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<div class="admonition is-success">
|
|
||||||
<header class="admonition-header">Tip</header>
|
|
||||||
<div class="admonition-body">
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Download this notebook and run it locally on your machine [recommended]. Click <a href="notebooks/matrix_matrix.ipynb" download>here</a>.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
You can also run this notebook in the cloud using Binder. Click <a href="https://mybinder.org/v2/gh/fverdugo/XM_40017/gh-pages?filepath=dev/notebooks/matrix_matrix.ipynb">here</a>
|
|
||||||
.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<iframe id="notebook" src="../notebook-output/matrix_matrix.html" style="width:100%"></iframe>
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function(){
|
|
||||||
var myIframe = document.getElementById("notebook");
|
|
||||||
iFrameResize({log:true}, myIframe);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
```@meta
|
|
||||||
EditURL = "https://github.com/fverdugo/XM_40017/blob/main/docs/src/notebooks/notebook-hello.ipynb"
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<div class="admonition is-success">
|
|
||||||
<header class="admonition-header">Tip</header>
|
|
||||||
<div class="admonition-body">
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Download this notebook and run it locally on your machine [recommended]. Click <a href="notebooks/notebook-hello.ipynb" download>here</a>.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
You can also run this notebook in the cloud using Binder. Click <a href="https://mybinder.org/v2/gh/fverdugo/XM_40017/gh-pages?filepath=dev/notebooks/notebook-hello.ipynb">here</a>
|
|
||||||
.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<iframe id="notebook" src="../notebook-output/notebook-hello.html" style="width:100%"></iframe>
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function(){
|
|
||||||
var myIframe = document.getElementById("notebook");
|
|
||||||
iFrameResize({log:true}, myIframe);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,30 +0,0 @@
|
|||||||
```@meta
|
|
||||||
EditURL = "https://github.com/fverdugo/XM_40017/blob/main/docs/src/notebooks/sol_matrix_matrix.ipynb"
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<div class="admonition is-success">
|
|
||||||
<header class="admonition-header">Tip</header>
|
|
||||||
<div class="admonition-body">
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Download this notebook and run it locally on your machine [recommended]. Click <a href="notebooks/sol_matrix_matrix.ipynb" download>here</a>.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
You can also run this notebook in the cloud using Binder. Click <a href="https://mybinder.org/v2/gh/fverdugo/XM_40017/gh-pages?filepath=dev/notebooks/sol_matrix_matrix.ipynb">here</a>
|
|
||||||
.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
```@raw html
|
|
||||||
<iframe id="notebook" src="../notebook-output/sol_matrix_matrix.html" style="width:100%"></iframe>
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function(){
|
|
||||||
var myIframe = document.getElementById("notebook");
|
|
||||||
iFrameResize({log:true}, myIframe);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
@ -33,6 +33,38 @@
|
|||||||
"\n"
|
"\n"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 5,
|
||||||
|
"id": "1dc78750",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"jacobi_2_check (generic function with 1 method)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 5,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"using Printf\n",
|
||||||
|
"\n",
|
||||||
|
"function answer_checker(answer,solution)\n",
|
||||||
|
" if answer == solution\n",
|
||||||
|
" \"🥳 Well done! \"\n",
|
||||||
|
" else\n",
|
||||||
|
" \"It's not correct. Keep trying! 💪\"\n",
|
||||||
|
" end |> println\n",
|
||||||
|
"end\n",
|
||||||
|
"gauss_seidel_1_check(answer) = answer_checker(answer,\"c\")\n",
|
||||||
|
"jacobi_1_check(answer) = answer_checker(answer, \"d\")\n",
|
||||||
|
"jacobi_2_check(answer) = answer_checker(answer, \"b\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"id": "d4cb59d5",
|
"id": "d4cb59d5",
|
||||||
@ -244,12 +276,23 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": null,
|
"execution_count": 2,
|
||||||
"id": "4edad93f",
|
"id": "4edad93f",
|
||||||
"metadata": {},
|
"metadata": {
|
||||||
"outputs": [],
|
"scrolled": true
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"It's not correct. Keep trying! 💪\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
"source": [
|
"source": [
|
||||||
"#TODO answer (c)"
|
"answer = \"x\" # replace x with a, b, c or d\n",
|
||||||
|
"gauss_seidel_1_check(answer)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -304,7 +347,7 @@
|
|||||||
"source": [
|
"source": [
|
||||||
"### Ghost (aka halo) cells\n",
|
"### Ghost (aka halo) cells\n",
|
||||||
"\n",
|
"\n",
|
||||||
"A usual way of handling this type of data dependencies 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 jacoby update locally in the processes."
|
"A usual way of handling this type of data dependencies 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."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -324,17 +367,31 @@
|
|||||||
"source": [
|
"source": [
|
||||||
"<div class=\"alert alert-block alert-success\">\n",
|
"<div class=\"alert alert-block alert-success\">\n",
|
||||||
"<b>Question:</b> Which is the communication and computation complexity in each process? N is the length of the vector and P the number of processes. \n",
|
"<b>Question:</b> Which is the communication and computation complexity in each process? N is the length of the vector and P the number of processes. \n",
|
||||||
"</div>"
|
"</div>\n",
|
||||||
|
"\n",
|
||||||
|
" a) Communication: O(P), computation: O(N/P)\n",
|
||||||
|
" b) Communication: O(1), computation: O(N)\n",
|
||||||
|
" c) Communication: O(P), computation: O(N)\n",
|
||||||
|
" d) Communication: O(1), computation: O(N/P)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": null,
|
"execution_count": 4,
|
||||||
"id": "3a03fc4c",
|
"id": "3a03fc4c",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"It's not correct. Keep trying! 💪\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
"source": [
|
"source": [
|
||||||
"#TODO give multiple options"
|
"answer = \"x\" # replace x with a, b, c or d\n",
|
||||||
|
"jacobi_1_check(answer)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -464,7 +521,9 @@
|
|||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"# TODO (b) 2 mesajes. Add another question if you find it useful"
|
"answer = \"x\" # replace x with a, b, c or d\n",
|
||||||
|
"jacobi_2_check(answer)\n",
|
||||||
|
"# TODO: think of more questions"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -805,7 +864,7 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": null,
|
"execution_count": null,
|
||||||
"id": "7bd7057a",
|
"id": "4fa7fad3",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
@ -886,7 +945,7 @@
|
|||||||
],
|
],
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"kernelspec": {
|
"kernelspec": {
|
||||||
"display_name": "Julia 1.9.0",
|
"display_name": "Julia 1.9.1",
|
||||||
"language": "julia",
|
"language": "julia",
|
||||||
"name": "julia-1.9"
|
"name": "julia-1.9"
|
||||||
},
|
},
|
||||||
@ -894,7 +953,7 @@
|
|||||||
"file_extension": ".jl",
|
"file_extension": ".jl",
|
||||||
"mimetype": "application/julia",
|
"mimetype": "application/julia",
|
||||||
"name": "julia",
|
"name": "julia",
|
||||||
"version": "1.9.0"
|
"version": "1.9.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nbformat": 4,
|
"nbformat": 4,
|
||||||
|
|||||||
@ -1120,7 +1120,7 @@
|
|||||||
],
|
],
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"kernelspec": {
|
"kernelspec": {
|
||||||
"display_name": "Julia 1.9.0",
|
"display_name": "Julia 1.9.1",
|
||||||
"language": "julia",
|
"language": "julia",
|
||||||
"name": "julia-1.9"
|
"name": "julia-1.9"
|
||||||
},
|
},
|
||||||
@ -1128,7 +1128,7 @@
|
|||||||
"file_extension": ".jl",
|
"file_extension": ".jl",
|
||||||
"mimetype": "application/julia",
|
"mimetype": "application/julia",
|
||||||
"name": "julia",
|
"name": "julia",
|
||||||
"version": "1.9.0"
|
"version": "1.9.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nbformat": 4,
|
"nbformat": 4,
|
||||||
|
|||||||
401
notebooks/mpi_tutorial.ipynb
Normal file
401
notebooks/mpi_tutorial.ipynb
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "8d800917",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Tutorial: Using MPI in Julia\n",
|
||||||
|
"Message Passing Interface (MPI) is a standardized and portable library specification for communication between parallel processes in distributed memory systems. Julia offers a convenient way to work with MPI for creating efficient parallel and distributed applications. In this tutorial, you will learn how to use MPI from Julia to perform parallel computing tasks.\n",
|
||||||
|
"\n",
|
||||||
|
"## MPI launches separate Julia instances\n",
|
||||||
|
"When you run an MPI-enabled Julia script, MPI takes care of spawning multiple instances of the Julia executable, each acting as a separate process. These workers can communicate with each other using MPI communication functions. This enables parallel processing and distributed computation. Here's a summary of how it works:\n",
|
||||||
|
"\n",
|
||||||
|
"-- TODO: insert picture here --\n",
|
||||||
|
"\n",
|
||||||
|
"- **MPI Spawns Processes**: The `mpiexec` command launches multiple instances of the Julia executable, creating separate worker processes. In this example, 4 Julia workers are spawned.\n",
|
||||||
|
"\n",
|
||||||
|
"- **Worker Communication**: These workers can communicate with each other using MPI communication functions, allowing them to exchange data and coordinate actions.\n",
|
||||||
|
"\n",
|
||||||
|
"- **Parallel Tasks**: The workers execute parallel tasks simultaneously, working on different parts of the computation to potentially speed up the process.\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
" \n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"## Installing MPI.jl and MPIClusterManagers Packages\n",
|
||||||
|
"To use MPI in Julia, you'll need the MPI.jl package, and if you intend to run MPI programs in a Jupyter Notebook, you'll also need the MPIClusterManagers package. These packages provide the necessary bindings to the MPI library and cluster management capabilities. To install the packages, open a terminal and run the following commands:"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "3cb5f151",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"using Pkg\n",
|
||||||
|
"Pkg.add(\"MPI\")\n",
|
||||||
|
"Pkg.add(\"MPIClusterManagers\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "ed45a4b2",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"<div class=\"alert alert-block alert-info\">\n",
|
||||||
|
" <b>Tip:</b>\n",
|
||||||
|
"The package <code>MPI.jl</code> is the Julia interface to MPI. Note that it is not a MPI library by itself. It is just a thin wrapper between MPI and Julia. To use this interface, you need an actual MPI library installed in your system such as OpenMPI or MPICH. Julia downloads and installs a MPI library for you, but it is also possible to use a MPI library already available in your system. This is useful, e.g., when running on HPC clusters. See the documentation of <code>MPI.jl</code> for further details.\n",
|
||||||
|
"</div>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "7a36916e",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Writing a HelloWorld MPI Program in Julia\n",
|
||||||
|
"Let's start by creating a simple MPI program that prints a message along with the rank of each worker. \n",
|
||||||
|
"\n",
|
||||||
|
"Create a new Julia script, for example, `mpi_hello_world.jl`:\n",
|
||||||
|
"\n",
|
||||||
|
"```julia\n",
|
||||||
|
"using MPI\n",
|
||||||
|
"\n",
|
||||||
|
"# Initialize MPI\n",
|
||||||
|
"MPI.Init()\n",
|
||||||
|
"\n",
|
||||||
|
"# Get the default communicator (MPI_COMM_WORLD) for all processes\n",
|
||||||
|
"comm = MPI.COMM_WORLD\n",
|
||||||
|
"\n",
|
||||||
|
"# Get the number of processes in this communicator\n",
|
||||||
|
"nranks = MPI.Comm_size(comm)\n",
|
||||||
|
"\n",
|
||||||
|
"# Get the rank of the current process within the communicator\n",
|
||||||
|
"rank = MPI.Comm_rank(comm)\n",
|
||||||
|
"\n",
|
||||||
|
"# Print a message with the rank of the current process\n",
|
||||||
|
"println(\"Hello, I am process $rank of $nranks processes!\")\n",
|
||||||
|
"\n",
|
||||||
|
"# Finalize MPI\n",
|
||||||
|
"MPI.Finalize()\n",
|
||||||
|
"```"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "6caa8d74",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"### MPI Communicators\n",
|
||||||
|
"In MPI, a **communicator** is a context in which a group of processes can communicate with each other. `MPI_COMM_WORLD` is one of the MPI standard communicators, it represents all processes in the MPI program. Custom communicators can also be created to group processes based on specific requirements or logical divisions. \n",
|
||||||
|
"\n",
|
||||||
|
"The **rank** of a processor is a unique identifier assigned to each process within a communicator. It allows processes to distinguish and address each other in communication operations. "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "19f41e38",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Running the HelloWorld MPI Program\n",
|
||||||
|
"\n",
|
||||||
|
"To run MPI applications in parallel, you need a launcher like `mpiexec`. MPI codes written in Julia are not an exception to this rule. From the system terminal, you can run\n",
|
||||||
|
"```\n",
|
||||||
|
"$ mpiexec -np 4 mpi_hello_world.jl\n",
|
||||||
|
"```\n",
|
||||||
|
"In this command, `-np 4` specifies the desired number of processes. \n",
|
||||||
|
"But it will probably not work since the version of `mpiexec` needs to match with the MPI version we are using from Julia. You can find the path to the `mpiexec` binary you need to use with these commands\n",
|
||||||
|
"\n",
|
||||||
|
"```julia\n",
|
||||||
|
"julia> using MPI\n",
|
||||||
|
"julia> MPI.mpiexec_path\n",
|
||||||
|
"```\n",
|
||||||
|
"\n",
|
||||||
|
"and then try again\n",
|
||||||
|
"```\n",
|
||||||
|
"$ /path/to/my/mpiexec -np 4 julia mpi_hello_world.jl\n",
|
||||||
|
"```\n",
|
||||||
|
"with your particular path.\n",
|
||||||
|
"\n",
|
||||||
|
"However, this is not very convenient. Don't worry if you could not make it work! A more elegant way to run MPI code is from the Julia REPL directly, by using these commands:\n",
|
||||||
|
"```julia\n",
|
||||||
|
"julia> using MPI\n",
|
||||||
|
"julia> mpiexec(cmd->run(`$cmd -np 4 julia mpi_hello_world.jl`))\n",
|
||||||
|
"```\n",
|
||||||
|
"\n",
|
||||||
|
"Now, you should see output from 4 ranks.\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "0592e58c",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Running MPI Programs in Jupyter Notebook with MPIClusterManagers\n",
|
||||||
|
"If you want to run your MPI code from a Jupyter Notebook, you can do so using the `MPIClusterManagers` package.\n",
|
||||||
|
"\n",
|
||||||
|
"1. Load the packages and start an MPI cluster with the desired number of workers:"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "cf66dd39",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"using MPIClusterManagers\n",
|
||||||
|
"# Distributed package is needed for addprocs()\n",
|
||||||
|
"using Distributed\n",
|
||||||
|
"\n",
|
||||||
|
"manager = MPIWorkerManager(4)\n",
|
||||||
|
"addprocs(manager)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "d40fe3ee",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"2. Run your MPI code inside a `@mpi_do` block to execute it on the cluster workers:"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "0a51d1f2",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"@mpi_do manager begin\n",
|
||||||
|
" using MPI\n",
|
||||||
|
" comm = MPI.COMM_WORLD\n",
|
||||||
|
" rank = MPI.Comm_rank(comm)\n",
|
||||||
|
" println(\"Hello from process $rank\")\n",
|
||||||
|
"end\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "38ed88c1",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"MPI is automatically initialized and finalized within the `@mpi_do` block.\n",
|
||||||
|
"\n",
|
||||||
|
"3. Remove processes when done:"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "e0b53cc1",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"rmprocs(manager)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "5466a650",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Point-to-Point Communication with MPI\n",
|
||||||
|
"MPI provides point-to-point communication using blocking send and receiving functions `MPI.send`, `MPI.recv`; or their non-blocking versions `MPI.Isend`, and `MPI.Irecv!`. These functions allow individual processes to send and receive data between each other.\n",
|
||||||
|
"\n",
|
||||||
|
"### Blocking communication\n",
|
||||||
|
"\n",
|
||||||
|
"Let's demonstrate how to send and receive with an example:\n",
|
||||||
|
"\n",
|
||||||
|
"```julia\n",
|
||||||
|
"using MPI\n",
|
||||||
|
"\n",
|
||||||
|
"MPI.Init()\n",
|
||||||
|
"\n",
|
||||||
|
"comm = MPI.COMM_WORLD\n",
|
||||||
|
"rank = MPI.Comm_rank(comm)\n",
|
||||||
|
"\n",
|
||||||
|
"# Send and receive messages using blocking MPI.send and MPI.recv\n",
|
||||||
|
"if rank == 0\n",
|
||||||
|
" data = \"Hello from process $rank !\"\n",
|
||||||
|
" MPI.send(data, comm, dest=1)\n",
|
||||||
|
"elseif rank == 1\n",
|
||||||
|
" received_data = MPI.recv(comm, source=0)\n",
|
||||||
|
" println(\"Process $rank received: $received_data\")\n",
|
||||||
|
"end\n",
|
||||||
|
"\n",
|
||||||
|
"MPI.Finalize()\n",
|
||||||
|
"```"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "d4dfe654",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"In this example, process 0 sends a message using `MPI.send`, and process 1 receives it using `MPI.recv`.\n",
|
||||||
|
"\n",
|
||||||
|
"### Non-blocking communication\n",
|
||||||
|
"\n",
|
||||||
|
"To demonstrate asynchronous communication, let's modify the example using `MPI.Isend` and `MPI.Irecv!`:\n",
|
||||||
|
"\n",
|
||||||
|
"```julia\n",
|
||||||
|
"using MPI\n",
|
||||||
|
"\n",
|
||||||
|
"MPI.Init()\n",
|
||||||
|
"\n",
|
||||||
|
"comm = MPI.COMM_WORLD\n",
|
||||||
|
"rank = MPI.Comm_rank(comm)\n",
|
||||||
|
"\n",
|
||||||
|
"# Asynchronous communication using MPI.Isend and MPI.Irecv!\n",
|
||||||
|
"if rank == 0\n",
|
||||||
|
" data = \"Hello from process $rank !\"\n",
|
||||||
|
" request = MPI.Isend(data, comm, dest=1)\n",
|
||||||
|
" # Other computation can happen here\n",
|
||||||
|
" MPI.Wait(request)\n",
|
||||||
|
"elseif rank == 1\n",
|
||||||
|
" received_data = Array{UInt8}(undef, 50) # Preallocate buffer\n",
|
||||||
|
" request = MPI.Irecv!(received_data, comm, source=0)\n",
|
||||||
|
" # Other computation can happen here\n",
|
||||||
|
" MPI.Wait(request)\n",
|
||||||
|
" println(\"Process $rank received: $(String(received_data))\")\n",
|
||||||
|
"end\n",
|
||||||
|
"\n",
|
||||||
|
"MPI.Finalize()\n",
|
||||||
|
"```"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "024db538",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"In this example, process 0 uses `MPI.Isend` to send the message asynchronously. This function returns immediately, allowing the sender process to continue its execution. However, the actual sending of data is done asynchronously in the background. Similar to `MPI.Isend`, `MPI.Irecv!` returns immediately, allowing the receiver process to continue executing. \n",
|
||||||
|
"\n",
|
||||||
|
"<div class=\"alert alert-block alert-warning\">\n",
|
||||||
|
"<b>Important:</b> In asynchronous communication, always use <code>MPI.Wait()</code> to ensure the communication is finished before accessing the send or receive buffer.\n",
|
||||||
|
"</div>\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"## Collective Communication with MPI\n",
|
||||||
|
"MPI provides collective communication functions for communication involving multiple processes. Let's explore some of these functions:\n",
|
||||||
|
"\n",
|
||||||
|
"- MPI.Gather: Gathers data from all processes to a single process.\n",
|
||||||
|
"- MPI.Scatter: Distributes data from one process to all processes.\n",
|
||||||
|
"- MPI.Bcast: Broadcasts data from one process to all processes.\n",
|
||||||
|
"- MPI.Barrier: Synchronizes all processes.\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"Let's illustrate the use of `MPI.Gather` and `MPI.Scatter` with an example:\n",
|
||||||
|
"\n",
|
||||||
|
"```julia\n",
|
||||||
|
"# TODO: check if this runs correctly\n",
|
||||||
|
"using MPI\n",
|
||||||
|
"using Random\n",
|
||||||
|
"\n",
|
||||||
|
"MPI.Init()\n",
|
||||||
|
"\n",
|
||||||
|
"comm = MPI.COMM_WORLD\n",
|
||||||
|
"rank = MPI.Comm_rank(comm)\n",
|
||||||
|
"size = MPI.Comm_size(comm)\n",
|
||||||
|
"\n",
|
||||||
|
"# Root processor generates random data\n",
|
||||||
|
"data = rand(rank == 0 ? size * 2 : 0)\n",
|
||||||
|
"\n",
|
||||||
|
"# Scatter data to all processes\n",
|
||||||
|
"local_data = Vector{Float64}(undef, 2)\n",
|
||||||
|
"MPI.Scatter!(data, local_data, comm, root=0)\n",
|
||||||
|
"\n",
|
||||||
|
"# Compute local average\n",
|
||||||
|
"local_average = sum(local_data) / length(local_data)\n",
|
||||||
|
"\n",
|
||||||
|
"# Gather local averages at the root processor\n",
|
||||||
|
"gathered_averages = Vector{Float64}(undef, size)\n",
|
||||||
|
"MPI.Gather!(local_average, gathered_averages, comm, root=0)\n",
|
||||||
|
"\n",
|
||||||
|
"if rank == 0\n",
|
||||||
|
" # Compute global average of sub-averages\n",
|
||||||
|
" global_average = sum(gathered_averages) / size\n",
|
||||||
|
" println(\"Global average: $global_average\")\n",
|
||||||
|
"end\n",
|
||||||
|
"\n",
|
||||||
|
"MPI.Finalize()\n",
|
||||||
|
"```"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "e65cb53f",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"using MPI\n",
|
||||||
|
"using Random\n",
|
||||||
|
"\n",
|
||||||
|
"# TODO: check if this runs correctly\n",
|
||||||
|
"\n",
|
||||||
|
"MPI.Init()\n",
|
||||||
|
"\n",
|
||||||
|
"comm = MPI.COMM_WORLD\n",
|
||||||
|
"rank = MPI.Comm_rank(comm)\n",
|
||||||
|
"size = MPI.Comm_size(comm)\n",
|
||||||
|
"\n",
|
||||||
|
"# Root processor generates random data\n",
|
||||||
|
"data = rand(rank == 0 ? size * 2 : 0)\n",
|
||||||
|
"\n",
|
||||||
|
"# Scatter data to all processes\n",
|
||||||
|
"local_data = Vector{Float64}(undef, 2)\n",
|
||||||
|
"MPI.Scatter!(data, local_data, comm, root=0)\n",
|
||||||
|
"\n",
|
||||||
|
"# Compute local average\n",
|
||||||
|
"local_average = sum(local_data) / length(local_data)\n",
|
||||||
|
"\n",
|
||||||
|
"# Gather local averages at the root processor\n",
|
||||||
|
"gathered_averages = Vector{Float64}(undef, size)\n",
|
||||||
|
"MPI.Gather!(local_average, gathered_averages, comm, root=0)\n",
|
||||||
|
"\n",
|
||||||
|
"if rank == 0\n",
|
||||||
|
" # Compute global average of sub-averages\n",
|
||||||
|
" global_average = sum(gathered_averages) / size\n",
|
||||||
|
" println(\"Global average: $global_average\")\n",
|
||||||
|
"end\n",
|
||||||
|
"\n",
|
||||||
|
"MPI.Finalize()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "dfd5da9e",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"In this example, the root processor generates random data and then scatters it to all processes using MPI.Scatter. Each process calculates the average of its local data, and then the local averages are gathered using MPI.Gather. The root processor computes the global average of all sub-averages and prints it."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "fcf34823",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Julia 1.9.1",
|
||||||
|
"language": "julia",
|
||||||
|
"name": "julia-1.9"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"file_extension": ".jl",
|
||||||
|
"mimetype": "application/julia",
|
||||||
|
"name": "julia",
|
||||||
|
"version": "1.9.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
||||||
@ -1,60 +0,0 @@
|
|||||||
{
|
|
||||||
"cells": [
|
|
||||||
{
|
|
||||||
"cell_type": "markdown",
|
|
||||||
"id": "d6d12733",
|
|
||||||
"metadata": {},
|
|
||||||
"source": [
|
|
||||||
"# Solution to Matrix Multiplication Exercises\n",
|
|
||||||
"\n",
|
|
||||||
"## Implementation of Algorithm 3"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": null,
|
|
||||||
"id": "be73e87a",
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [],
|
|
||||||
"source": [
|
|
||||||
"function matmul_dist_3!(C,A,B)\n",
|
|
||||||
" m = size(C,1)\n",
|
|
||||||
" n = size(C,2)\n",
|
|
||||||
" l = size(A,2)\n",
|
|
||||||
" @assert size(A,1) == m\n",
|
|
||||||
" @assert size(B,2) == n\n",
|
|
||||||
" @assert size(B,1) == l\n",
|
|
||||||
" @assert mod(m,nworkers()) == 0\n",
|
|
||||||
" # Implement here\n",
|
|
||||||
" nrows_w = div(m,nworkers())\n",
|
|
||||||
" @sync for (i,w) in enumerate(workers())\n",
|
|
||||||
" rows_w = (1:nrows_w) .+ (i-1)*nrows_w\n",
|
|
||||||
" Aw = A[rows_w,:]\n",
|
|
||||||
" ftr = @spawnat w begin\n",
|
|
||||||
" Cw = similar(Aw,nrows_w,n)\n",
|
|
||||||
" matmul_seq!(Cw,Aw,B)\n",
|
|
||||||
" Cw\n",
|
|
||||||
" end\n",
|
|
||||||
" @async C[rows_w,:] = fetch(ftr)\n",
|
|
||||||
" end\n",
|
|
||||||
" C\n",
|
|
||||||
"end"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"metadata": {
|
|
||||||
"kernelspec": {
|
|
||||||
"display_name": "Julia 1.9.1",
|
|
||||||
"language": "julia",
|
|
||||||
"name": "julia-1.9"
|
|
||||||
},
|
|
||||||
"language_info": {
|
|
||||||
"file_extension": ".jl",
|
|
||||||
"mimetype": "application/julia",
|
|
||||||
"name": "julia",
|
|
||||||
"version": "1.9.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nbformat": 4,
|
|
||||||
"nbformat_minor": 5
|
|
||||||
}
|
|
||||||
129
notebooks/solutions.ipynb
Normal file
129
notebooks/solutions.ipynb
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "d6d12733",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Solutions to Notebook Exercises\n",
|
||||||
|
"\n",
|
||||||
|
"## Matrix Multiplication : Implementation of Algorithm 3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "be73e87a",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"function matmul_dist_3!(C,A,B)\n",
|
||||||
|
" m = size(C,1)\n",
|
||||||
|
" n = size(C,2)\n",
|
||||||
|
" l = size(A,2)\n",
|
||||||
|
" @assert size(A,1) == m\n",
|
||||||
|
" @assert size(B,2) == n\n",
|
||||||
|
" @assert size(B,1) == l\n",
|
||||||
|
" @assert mod(m,nworkers()) == 0\n",
|
||||||
|
" # Implement here\n",
|
||||||
|
" nrows_w = div(m,nworkers())\n",
|
||||||
|
" @sync for (i,w) in enumerate(workers())\n",
|
||||||
|
" rows_w = (1:nrows_w) .+ (i-1)*nrows_w\n",
|
||||||
|
" Aw = A[rows_w,:]\n",
|
||||||
|
" ftr = @spawnat w begin\n",
|
||||||
|
" Cw = similar(Aw,nrows_w,n)\n",
|
||||||
|
" matmul_seq!(Cw,Aw,B)\n",
|
||||||
|
" Cw\n",
|
||||||
|
" end\n",
|
||||||
|
" @async C[rows_w,:] = fetch(ftr)\n",
|
||||||
|
" end\n",
|
||||||
|
" C\n",
|
||||||
|
"end"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "2d9f4813",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Jacobi Method : Exercise 1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "cf3b1e72",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"@everywhere workers() begin\n",
|
||||||
|
" using MPI\n",
|
||||||
|
" MPI.Initialized() || MPI.Init()\n",
|
||||||
|
" comm = MPI.Comm_dup(MPI.COMM_WORLD)\n",
|
||||||
|
" nw = MPI.Comm_size(comm)\n",
|
||||||
|
" iw = MPI.Comm_rank(comm)+1\n",
|
||||||
|
" function jacobi_mpi(n,niters)\n",
|
||||||
|
" if mod(n,nw) != 0\n",
|
||||||
|
" println(\"n must be a multiple of nw\")\n",
|
||||||
|
" MPI.Abort(comm,1)\n",
|
||||||
|
" end\n",
|
||||||
|
" n_own = div(n,nw)\n",
|
||||||
|
" u = zeros(n_own+2)\n",
|
||||||
|
" u[1] = -1\n",
|
||||||
|
" u[end] = 1\n",
|
||||||
|
" u_new = copy(u)\n",
|
||||||
|
" for t in 1:niters\n",
|
||||||
|
" reqs_snd = MPI.Request[]\n",
|
||||||
|
" reqs_rcv = MPI.Request[]\n",
|
||||||
|
" if iw != 1\n",
|
||||||
|
" neig_rank = (iw-1)-1\n",
|
||||||
|
" req = MPI.Isend(view(u,2:2),comm,dest=neig_rank,tag=0)\n",
|
||||||
|
" push!(reqs_snd,req)\n",
|
||||||
|
" req = MPI.Irecv!(view(u,1:1),comm,source=neig_rank,tag=0)\n",
|
||||||
|
" push!(reqs_rcv,req)\n",
|
||||||
|
" end\n",
|
||||||
|
" if iw != nw\n",
|
||||||
|
" neig_rank = (iw+1)-1\n",
|
||||||
|
" s = n_own-1\n",
|
||||||
|
" r = n_own\n",
|
||||||
|
" req = MPI.Isend(view(u,s:s),comm,dest=neig_rank,tag=0)\n",
|
||||||
|
" push!(reqs_snd,req)\n",
|
||||||
|
" req = MPI.Irecv!(view(u,r:r),comm,source=neig_rank,tag=0)\n",
|
||||||
|
" push!(reqs_rcv,req)\n",
|
||||||
|
" end\n",
|
||||||
|
" for i in 3:n_own\n",
|
||||||
|
" u_new[i] = 0.5*(u[i-1]+u[i+1])\n",
|
||||||
|
" end\n",
|
||||||
|
" MPI.Waitall(reqs_rcv)\n",
|
||||||
|
" for i in (2,n_own+1)\n",
|
||||||
|
" u_new[i] = 0.5*(u[i-1]+u[i+1])\n",
|
||||||
|
" end\n",
|
||||||
|
" MPI.Waitall(reqs_snd)\n",
|
||||||
|
" u, u_new = u_new, u\n",
|
||||||
|
" end\n",
|
||||||
|
" u\n",
|
||||||
|
" end\n",
|
||||||
|
" niters = 100\n",
|
||||||
|
" load = 4\n",
|
||||||
|
" n = load*nw\n",
|
||||||
|
" jacobi_mpi(n,niters)\n",
|
||||||
|
"end"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Julia 1.9.1",
|
||||||
|
"language": "julia",
|
||||||
|
"name": "julia-1.9"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"file_extension": ".jl",
|
||||||
|
"mimetype": "application/julia",
|
||||||
|
"name": "julia",
|
||||||
|
"version": "1.9.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user