diff --git a/notebooks/jacobi_method.ipynb b/notebooks/jacobi_method.ipynb
index ead9eb5..3331276 100644
--- a/notebooks/jacobi_method.ipynb
+++ b/notebooks/jacobi_method.ipynb
@@ -33,6 +33,38 @@
"\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",
"id": "d4cb59d5",
@@ -207,12 +239,23 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 2,
"id": "4edad93f",
- "metadata": {},
- "outputs": [],
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "It's not correct. Keep trying! 💪\n"
+ ]
+ }
+ ],
"source": [
- "#TODO answer (c)"
+ "answer = \"x\" # replace x with a, b, c or d\n",
+ "gauss_seidel_1_check(answer)"
]
},
{
@@ -267,7 +310,7 @@
"source": [
"### Ghost (aka halo) cells\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."
]
},
{
@@ -287,17 +330,31 @@
"source": [
"
\n",
"Question: Which is the communication and computation complexity in each process? N is the length of the vector and P the number of processes. \n",
- "
"
+ "\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",
- "execution_count": null,
+ "execution_count": 4,
"id": "3a03fc4c",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "It's not correct. Keep trying! 💪\n"
+ ]
+ }
+ ],
"source": [
- "#TODO give multiple options"
+ "answer = \"x\" # replace x with a, b, c or d\n",
+ "jacobi_1_check(answer)"
]
},
{
@@ -427,7 +484,9 @@
"metadata": {},
"outputs": [],
"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"
]
},
{
@@ -599,7 +658,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "7bd7057a",
+ "id": "4fa7fad3",
"metadata": {},
"outputs": [],
"source": [
@@ -660,7 +719,7 @@
],
"metadata": {
"kernelspec": {
- "display_name": "Julia 1.9.0",
+ "display_name": "Julia 1.9.1",
"language": "julia",
"name": "julia-1.9"
},
@@ -668,7 +727,7 @@
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
- "version": "1.9.0"
+ "version": "1.9.1"
}
},
"nbformat": 4,
diff --git a/notebooks/matrix_matrix.ipynb b/notebooks/matrix_matrix.ipynb
index d8db409..f42a34b 100644
--- a/notebooks/matrix_matrix.ipynb
+++ b/notebooks/matrix_matrix.ipynb
@@ -1120,7 +1120,7 @@
],
"metadata": {
"kernelspec": {
- "display_name": "Julia 1.9.0",
+ "display_name": "Julia 1.9.1",
"language": "julia",
"name": "julia-1.9"
},
@@ -1128,7 +1128,7 @@
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
- "version": "1.9.0"
+ "version": "1.9.1"
}
},
"nbformat": 4,
diff --git a/notebooks/sol_matrix_matrix.ipynb b/notebooks/sol_matrix_matrix.ipynb
deleted file mode 100644
index 7bba96a..0000000
--- a/notebooks/sol_matrix_matrix.ipynb
+++ /dev/null
@@ -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
-}
diff --git a/notebooks/solutions.ipynb b/notebooks/solutions.ipynb
new file mode 100644
index 0000000..9477f60
--- /dev/null
+++ b/notebooks/solutions.ipynb
@@ -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
+}