diff --git a/dev/getting_started_with_julia/index.html b/dev/getting_started_with_julia/index.html index a597c89..5b4ba45 100644 --- a/dev/getting_started_with_julia/index.html +++ b/dev/getting_started_with_julia/index.html @@ -14,4 +14,4 @@ julia> DataFrame(a=[1,2],b=[3,4])

You should get an error or a BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195"

Copy the contents of previous code block into a file called Project.toml and place it in an empty folder named newproject. It is important that the file is named Project.toml. You can create a new folder from the REPL with

julia> mkdir("newproject")

To install all the packages registered in this file you need to activate the folder containing your Project.toml file

(@v1.8) pkg> activate newproject

and then instantiating it

(newproject) pkg> instantiate

The instantiate command will download and install all listed packages and their dependencies in just one click.

Getting help in package mode

You can get help about a particular package operator by writing help in front of it

(@v1.8) pkg> help activate

You can get an overview of all package commands by typing help alone

(@v1.8) pkg> help

Package operations in Julia code

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 Pkg package. For instance

julia> using Pkg
-julia> Pkg.status()

is equivalent to calling status in package mode.

(@v1.8) pkg> status

Conclusion

We have learned the basics of how to work with Julia. If you want to further dig into the topics we have covered here, you can take a look at the following links:

+julia> Pkg.status()

is equivalent to calling status in package mode.

(@v1.8) pkg> status

Conclusion

We have learned the basics of how to work with Julia. If you want to further dig into the topics we have covered here, you can take a look at the following links:

diff --git a/dev/index.html b/dev/index.html index 71d1cbc..e129732 100644 --- a/dev/index.html +++ b/dev/index.html @@ -2,4 +2,4 @@ Home · XM_40017

Programming Large-Scale Parallel Systems (XM_40017)

Welcome to the interactive lecture notes of the Programming Large-Scale Parallel Systems course at VU Amsterdam!

What

This page contains part of the course material of the Programming Large-Scale Parallel Systems course at VU Amsterdam. We provide several lecture notes in jupyter notebook format, which will help you to learn how to design, analyze, and program parallel algorithms on multi-node computing systems. Further information about the course is found in the study guide (click here) and our Canvas page (for registered students).

Note

This page contains only a part of the course material. The rest is available on Canvas. In particular, the lecture notes in this public webpage do not fully cover all topics in the final exam.

How to use this page

You have two main ways of running the notebooks:

  • Download the notebooks and run them locally on your computer (recommended)
  • Run the notebooks on the cloud via mybinder.org (high startup time).

You also have the static version of the notebooks displayed in this webpage for quick reference. At each notebook page you will find a green box with links to download the notebook or to open in on mybinder.

How to run the notebooks locally

To run a notebook locally follow these steps:

  • Install Julia (if not done already). More information in Getting started.
  • Download the notebook.
  • Launch Julia. More information in Getting started.
  • Execute these commands in the Julia command line:
julia> using Pkg
 julia> Pkg.add("IJulia")
 julia> using IJulia
-julia> notebook()
  • These commands will open a jupyter in your web browser. Navigate in jupyter to the notebook file you have downloaded and open it.

Authors

This material is created by Francesc Verdugo with the help of Gelieza Kötterheinrich. Part of the notebooks are based on the course slides by Henri Bal.

License

All material on this page that is original to this course may be used under a CC BY 4.0 license.

Acknowledgment

This page was created with the support of the Faculty of Science of Vrije Universiteit Amsterdam in the framework of the project "Interactive lecture notes and exercises for the Programming Large-Scale Parallel Systems course" funded by the "Innovation budget BETA 2023 Studievoorschotmiddelen (SVM) towards Activated Blended Learning".

+julia> notebook()

Authors

This material is created by Francesc Verdugo with the help of Gelieza Kötterheinrich. Part of the notebooks are based on the course slides by Henri Bal.

License

All material on this page that is original to this course may be used under a CC BY 4.0 license.

Acknowledgment

This page was created with the support of the Faculty of Science of Vrije Universiteit Amsterdam in the framework of the project "Interactive lecture notes and exercises for the Programming Large-Scale Parallel Systems course" funded by the "Innovation budget BETA 2023 Studievoorschotmiddelen (SVM) towards Activated Blended Learning".

diff --git a/dev/notebook-html/solutions.html b/dev/notebook-html/solutions.html index 50b0a36..0425027 100644 --- a/dev/notebook-html/solutions.html +++ b/dev/notebook-html/solutions.html @@ -7782,19 +7782,81 @@ a.anchor-link {
-

TSP Exercise: Measure search overhead

+

Exercise: Measure search overhead

Modify the code of the serial and parallel algorithms so that the functions return the number of nodes in the search tree that they visit. You can then compare how many more nodes are visited by the parallel algorithm compared with the serial algorithm (known as search overhead). You can then use the third cell to gather some statistics about the search overhead using your altered version of the functions.

-
+
+
+
+ + +
+
+
+
+
+ +
-
+
+ + +
+
-
+
+ + +
+
+
+ + +
diff --git a/dev/notebooks/LEQ/index.html b/dev/notebooks/LEQ/index.html index adfbdc8..49817ef 100644 --- a/dev/notebooks/LEQ/index.html +++ b/dev/notebooks/LEQ/index.html @@ -18,4 +18,4 @@ var myIframe = document.getElementById("notebook"); iFrameResize({log:true}, myIframe); }); -
+ diff --git a/dev/notebooks/asp/index.html b/dev/notebooks/asp/index.html index aca3814..0afe65b 100644 --- a/dev/notebooks/asp/index.html +++ b/dev/notebooks/asp/index.html @@ -18,4 +18,4 @@ var myIframe = document.getElementById("notebook"); iFrameResize({log:true}, myIframe); }); - + diff --git a/dev/notebooks/jacobi_2D/index.html b/dev/notebooks/jacobi_2D/index.html index 8f9e281..4557a8f 100644 --- a/dev/notebooks/jacobi_2D/index.html +++ b/dev/notebooks/jacobi_2D/index.html @@ -18,4 +18,4 @@ var myIframe = document.getElementById("notebook"); iFrameResize({log:true}, myIframe); }); - + diff --git a/dev/notebooks/jacobi_method/index.html b/dev/notebooks/jacobi_method/index.html index ef2ba26..37fc686 100644 --- a/dev/notebooks/jacobi_method/index.html +++ b/dev/notebooks/jacobi_method/index.html @@ -18,4 +18,4 @@ var myIframe = document.getElementById("notebook"); iFrameResize({log:true}, myIframe); }); - + diff --git a/dev/notebooks/julia_async/index.html b/dev/notebooks/julia_async/index.html index 0910703..6b58759 100644 --- a/dev/notebooks/julia_async/index.html +++ b/dev/notebooks/julia_async/index.html @@ -18,4 +18,4 @@ var myIframe = document.getElementById("notebook"); iFrameResize({log:true}, myIframe); }); - + diff --git a/dev/notebooks/julia_basics/index.html b/dev/notebooks/julia_basics/index.html index 2b80d33..bd79c81 100644 --- a/dev/notebooks/julia_basics/index.html +++ b/dev/notebooks/julia_basics/index.html @@ -18,4 +18,4 @@ var myIframe = document.getElementById("notebook"); iFrameResize({log:true}, myIframe); }); - + diff --git a/dev/notebooks/julia_distributed/index.html b/dev/notebooks/julia_distributed/index.html index 4e791a1..3f684c4 100644 --- a/dev/notebooks/julia_distributed/index.html +++ b/dev/notebooks/julia_distributed/index.html @@ -18,4 +18,4 @@ var myIframe = document.getElementById("notebook"); iFrameResize({log:true}, myIframe); }); - + diff --git a/dev/notebooks/julia_intro/index.html b/dev/notebooks/julia_intro/index.html index 731ea57..22587c2 100644 --- a/dev/notebooks/julia_intro/index.html +++ b/dev/notebooks/julia_intro/index.html @@ -18,4 +18,4 @@ var myIframe = document.getElementById("notebook"); iFrameResize({log:true}, myIframe); }); - + diff --git a/dev/notebooks/julia_jacobi/index.html b/dev/notebooks/julia_jacobi/index.html index f28f194..50bb2ef 100644 --- a/dev/notebooks/julia_jacobi/index.html +++ b/dev/notebooks/julia_jacobi/index.html @@ -18,4 +18,4 @@ var myIframe = document.getElementById("notebook"); iFrameResize({log:true}, myIframe); }); - + diff --git a/dev/notebooks/julia_tutorial/index.html b/dev/notebooks/julia_tutorial/index.html index 393e3ba..c431d5e 100644 --- a/dev/notebooks/julia_tutorial/index.html +++ b/dev/notebooks/julia_tutorial/index.html @@ -18,4 +18,4 @@ var myIframe = document.getElementById("notebook"); iFrameResize({log:true}, myIframe); }); - + diff --git a/dev/notebooks/matrix_matrix/index.html b/dev/notebooks/matrix_matrix/index.html index b97b2a4..ba2117e 100644 --- a/dev/notebooks/matrix_matrix/index.html +++ b/dev/notebooks/matrix_matrix/index.html @@ -18,4 +18,4 @@ var myIframe = document.getElementById("notebook"); iFrameResize({log:true}, myIframe); }); - + diff --git a/dev/notebooks/mpi_tutorial/index.html b/dev/notebooks/mpi_tutorial/index.html index 2561022..57b6ad0 100644 --- a/dev/notebooks/mpi_tutorial/index.html +++ b/dev/notebooks/mpi_tutorial/index.html @@ -18,4 +18,4 @@ var myIframe = document.getElementById("notebook"); iFrameResize({log:true}, myIframe); }); - + diff --git a/dev/notebooks/notebook-hello/index.html b/dev/notebooks/notebook-hello/index.html index a968acb..ac16ffa 100644 --- a/dev/notebooks/notebook-hello/index.html +++ b/dev/notebooks/notebook-hello/index.html @@ -18,4 +18,4 @@ var myIframe = document.getElementById("notebook"); iFrameResize({log:true}, myIframe); }); - + diff --git a/dev/notebooks/solutions.ipynb b/dev/notebooks/solutions.ipynb index 779d2d7..0a79c0c 100644 --- a/dev/notebooks/solutions.ipynb +++ b/dev/notebooks/solutions.ipynb @@ -296,17 +296,85 @@ "id": "19641daf", "metadata": {}, "source": [ - "## TSP Exercise: Measure search overhead" + "### Exercise: Measure search overhead\n", + "Modify the code of the serial and parallel algorithms so that the functions return the number of nodes in the search tree that they visit. You can then compare how many more nodes are visited by the parallel algorithm compared with the serial algorithm (known as _search overhead_). You can then use the third cell to gather some statistics about the search overhead using your altered version of the functions. " + ] + }, + { + "cell_type": "markdown", + "id": "22ccce39", + "metadata": {}, + "source": [ + "## TSP: Exercise x (Measure search overhead)\n", + "This is the solution of how the code can be altered to measure the search overhead:" ] }, { "cell_type": "code", - "execution_count": null, - "id": "f00557a0", + "execution_count": 13, + "id": "a4d5ab70", "metadata": {}, "outputs": [], + "source": [ + "using Distributed\n", + "\n", + "if procs() == workers()\n", + " addprocs(4)\n", + "end\n", + "\n", + "@everywhere function visited(city,hops,path)\n", + " for i = 1:hops\n", + " if path[i] == city\n", + " return true\n", + " end\n", + " end\n", + " return false\n", + "end" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "bcee99f0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tsp_serial (generic function with 1 method)" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "## TSP serial \n", + "function tsp_serial_impl(connections,hops,path,current_distance, min_path, min_distance, node_count)\n", + " num_cities = length(connections)\n", + " if hops == num_cities\n", + " if current_distance < min_distance\n", + " min_path .= path\n", + " return min_path, current_distance, node_count\n", + " end\n", + " else\n", + " current_city = path[hops]\n", + " next_hops = hops + 1\n", + " for (next_city,distance_increment) in connections[current_city]\n", + " if !visited(next_city,hops,path)\n", + " node_count += 1\n", + " path[next_hops] = next_city\n", + " next_distance = current_distance + distance_increment\n", + " if next_distance < min_distance\n", + " min_path, min_distance, node_count = tsp_serial_impl(connections,next_hops,path,next_distance,min_path,min_distance, node_count)\n", + " end\n", + " end\n", + " end \n", + " end\n", + " return min_path, min_distance, node_count\n", + "end\n", + "\n", "function tsp_serial(connections,city)\n", " num_cities = length(connections)\n", " path=zeros(Int,num_cities)\n", @@ -315,29 +383,40 @@ " min_path = zeros(Int, num_cities)\n", " current_distance = 0\n", " min_distance = typemax(Int)\n", - " # Collect search time \n", - " search_time = @elapsed min_path, min_distance = tsp_serial_impl(connections,hops,path,current_distance, min_path, min_distance)\n", - " (;path=min_path,distance=min_distance, search_time)\n", + " node_count = 1\n", + " # Count the number of nodes visited in recursive function and return\n", + " min_path, min_distance, node_count = tsp_serial_impl(connections,hops,path,current_distance, min_path, min_distance, node_count)\n", + " (;path=min_path,distance=min_distance, node_count)\n", "end" ] }, { "cell_type": "code", - "execution_count": null, - "id": "30784da2", + "execution_count": 15, + "id": "327f5349", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "tsp_dist (generic function with 1 method)" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "## TSP distributed\n", - "@everywhere function tsp_dist_impl(wait_time, connections,hops,path,current_distance,min_dist_chnl, max_hops,jobs_chnl,ftr_result)\n", + "@everywhere function tsp_dist_impl(connections,hops,path,current_distance,min_dist_chnl, max_hops,jobs_chnl,ftr_result,node_count)\n", " num_cities = length(connections)\n", " if hops == num_cities\n", " min_distance = fetch(min_dist_chnl)\n", " if current_distance < min_distance\n", " take!(min_dist_chnl)\n", - " # Collect wait time to substract from overall search time \n", " if ftr_result !== nothing\n", - " wait_time += @elapsed @spawnat 1 begin\n", + " @spawnat 1 begin\n", " result = fetch(ftr_result)\n", " result.path .= path\n", " result.min_distance_ref[] = current_distance\n", @@ -351,23 +430,21 @@ " for (next_city,distance_increment) in connections[current_city]\n", " if !visited(next_city,hops,path)\n", " path[next_hops] = next_city\n", + " node_count += 1\n", " next_distance = current_distance + distance_increment\n", - " # Collect wait time because fetch may block\n", - " wait_time += @elapsed min_distance = fetch(min_dist_chnl)\n", + " min_distance = fetch(min_dist_chnl)\n", " if next_distance < min_distance\n", - " tsp_dist_impl(wait_time, connections,next_hops,path,next_distance,min_dist_chnl,max_hops,jobs_chnl,ftr_result)\n", + " node_count = tsp_dist_impl(connections,next_hops,path,next_distance,min_dist_chnl,max_hops,jobs_chnl,ftr_result,node_count)\n", " end\n", " end\n", " end \n", " else\n", - " # Collect communication time and add to wait time\n", - " wait_time += @elapsed if jobs_chnl !== nothing \n", + " if jobs_chnl !== nothing \n", " path_copy = copy(path) \n", " put!(jobs_chnl,(;hops,path=path_copy,current_distance))\n", " end\n", " end\n", - " # Return wait time\n", - " wait_time\n", + " return node_count\n", "end\n", "\n", "function tsp_dist(connections,city)\n", @@ -375,19 +452,23 @@ " num_cities = length(connections)\n", " path=zeros(Int,num_cities)\n", " result_path=zeros(Int, num_cities)\n", - " wait_time = 0\n", - " search_time = 0\n", " hops = 1\n", " path[hops] = city\n", " current_distance = 0\n", " min_distance = typemax(Int)\n", + " node_count = 1\n", " jobs_chnl = RemoteChannel(()->Channel{Any}(10))\n", " min_dist_chnl = RemoteChannel(()->Channel{Int}(1))\n", " put!(min_dist_chnl, min_distance)\n", " ftr_result = @spawnat 1 (;path=result_path,min_distance_ref=Ref(min_distance))\n", + " # Add another future to store number of visited nodes\n", + " ftr_node_count = @spawnat 1 node_count_ref = Ref(node_count)\n", " @async begin\n", - " # Collect search time from master process\n", - " search_time += @elapsed wait_time += tsp_dist_impl(wait_time,connections,hops,path,current_distance,min_dist_chnl,max_hops,jobs_chnl,nothing)\n", + " ncount = 0\n", + " ncount += tsp_dist_impl(connections,hops,path,current_distance,min_dist_chnl,max_hops,jobs_chnl,nothing, ncount)\n", + " # Update node counter\n", + " node_count_ref = fetch(ftr_node_count)\n", + " node_count_ref[] += ncount \n", " for w in workers()\n", " put!(jobs_chnl,nothing)\n", " end\n", @@ -404,79 +485,229 @@ " hops = job.hops\n", " path = job.path \n", " current_distance = job.current_distance\n", + " ncount = 0\n", " min_distance = fetch(min_dist_chnl)\n", " if current_distance < min_distance\n", - " # Collect search time from worker processes \n", - " search_time += @elapsed wait_time += tsp_dist_impl(wait_time,connections,hops,path,current_distance,min_dist_chnl,max_hops,nothing,ftr_result)\n", + " ncount += tsp_dist_impl(connections,hops,path,current_distance,min_dist_chnl,max_hops,nothing,ftr_result, ncount)\n", + " # Update node counter\n", + " @spawnat 1 begin \n", + " node_count_ref = fetch(ftr_node_count)\n", + " node_count_ref[] += ncount \n", + " end\n", " end\n", " end\n", " end\n", " end \n", " result = fetch(ftr_result)\n", - " (;path = result.path, distance = result.min_distance_ref[], search_time, wait_time)\n", - "end\n" + " # Fetch number of visited nodes for return\n", + " node_count_ref = fetch(ftr_node_count)\n", + " (;path = result.path, distance = result.min_distance_ref[], node_count=node_count_ref[])\n", + "end" ] }, { "cell_type": "code", - "execution_count": null, - "id": "694de934", + "execution_count": 16, + "id": "706242f2", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "n = 4\n", + "n = 6\n", + "n = 8\n", + "n = 10\n", + "search_overhead_perc = [0.75 0.16666666666666666 0.3333333333333333 0.2727272727272727 0.14285714285714285 0.07692307692307693 0.0 0.16666666666666666 0.4 0.16666666666666666; 0.01092896174863388 0.005154639175257732 0.031578947368421054 0.05384615384615385 0.4672897196261682 0.10434782608695652 0.09917355371900827 0.06666666666666667 -0.0056179775280898875 0.2736842105263158; 0.0 -0.009295120061967466 -0.0032278889606197547 0.01906318082788671 0.028241335044929396 0.0011111111111111111 -0.008201892744479496 0.004958047292143402 -0.005873715124816446 -0.009497336113041464; 3.87551835057939e-5 -0.014818818265230451 7.133685261806249e-5 -0.03200184183262346 -0.01696773663002659 -0.004075168167420009 6.629541235746487e-5 -0.0033114074608037486 -0.016359150396910535 -0.0025293711126468557]\n" + ] + }, + { + "data": { + "image/png": "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", + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/html": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "using Distributed\n", - "using RandomMatrix\n", "using Plots\n", + "using Statistics\n", "\n", - "function generate_rand_connections(city_range, distance_range)\n", - " # generate random connections matrix \n", - " n_cities = rand(city_range)\n", - " matrix = randTriangular(distance_range, n_cities; Diag=false)\n", - "\n", - " connections = Array{Array{Tuple{Int64,Int64},1},1}(undef, n_cities)\n", - " for i in 1:n_cities\n", - " connections[i] = Array{Tuple{Int64,Int64},1}(undef, n_cities)\n", + "# Generate random matrices\n", + "function rand_symmetric_distance_table(n)\n", + " threshold = 0.2\n", + " mincost = 3\n", + " maxcost = 10\n", + " infinity = 10000*maxcost\n", + " C = fill(infinity,n,n)\n", + " for j in 1:n\n", + " for i in 1:j\n", + " if rand() > threshold\n", + " C[i,j] = rand(mincost:maxcost)\n", + " C[j,i] = C[i,j]\n", + " end\n", + " end\n", + " C[j,j] = 0\n", " end\n", - " for i in 1:n_cities\n", - " for j in i:n_cities\n", - " distance = matrix[i,j]\n", - " connections[i][j] = (j,distance)\n", - " connections[j][i] = (i,distance)\n", + " C,infinity\n", + "end\n", + "\n", + "# Sort to get ascending distance weights\n", + "function sort_neighbors(C)\n", + " n = size(C,1)\n", + " map(1:n) do i\n", + " Ci = C[i,:]\n", + " cities = sortperm(Ci)\n", + " distances = Ci[cities]\n", + " collect(zip(cities,distances))[2:end]\n", + " end\n", + "end\n", + "\n", + "n_cities = [4, 6, 8, 10]\n", + "n_rep = 10\n", + "city = 1\n", + "node_count_serial = zeros(Union{Missing,Int64},length(n_cities), n_rep)\n", + "node_count_dist = zeros(Union{Missing,Int64},length(n_cities), n_rep)\n", + "for (i, n) in enumerate(n_cities)\n", + " @show n\n", + " for j in 1:n_rep\n", + " # Generate random connections matrix\n", + " C, inf = rand_symmetric_distance_table(n)\n", + " C = sort_neighbors(C)\n", + " # Run serial algorithm\n", + " path, distance, ncount_serial = tsp_serial(C, city)\n", + " # Check if graph is connected \n", + " if distance >= inf\n", + " println(\"The input graph size $n, it $j is not connected\")\n", + " node_count_serial[i,j] = missing\n", + " node_count_dist[i,j] = missing\n", + " else\n", + " path, distance, ncount_dist = tsp_dist(C, city)\n", + " node_count_serial[i,j] = ncount_serial\n", + " node_count_dist[i,j] = ncount_dist\n", " end\n", " end\n", - " return connections\n", "end\n", "\n", - "# Run once so compile times are not measured\n", - "distance_range = 1:100\n", - "connections = generate_rand_connections(4:4, distance_range)\n", - "tsp_dist(connections,1)\n", - "tsp_serial(connections,1)\n", + "# Calculate average and confidence interval\n", + "search_overhead_perc = (node_count_dist .- node_count_serial)./node_count_serial\n", + "avg_search_overhead = [mean(skipmissing(search_overhead_perc[i,:])) for i in axes(search_overhead_perc,1)]\n", + "conf_int = [1.96*std(skipmissing(search_overhead_perc[i,:]))/\n", + " sqrt(count(!ismissing,search_overhead_perc[i,:])) \n", + " for i in axes(search_overhead_perc,1)]\n", "\n", - "# Measure runtimes of serial and parallel algorithm\n", - "n_it = 5\n", - "city_ranges = [4:4, 6:6, 8:8, 10:10]\n", - "search_overhead = zeros(Float64, length(city_ranges), n_it )\n", - "for (i, n) in enumerate(city_ranges)\n", - " for k in 1:n_it\n", - " connections = generate_rand_connections(n, distance_range)\n", - " @show n, k\n", - " path_dist, distance_dist, search_time_dist, wait_time_dist = tsp_dist(connections,1)\n", - " path_serial, distance_serial, search_time_serial = tsp_serial(connections,1)\n", - " # Compute search overhead as difference between distributed program and serial program\n", - " # (without time spent communicating or waiting)\n", - " search_overhead[i, k] = search_time_dist - wait_time_dist - search_time_serial\n", - " end\n", - "end\n", - "\n", - "min_search_oh = minimum(search_overhead, dims=2)\n", - "city_sizes = [4,6,8,10]\n", - "plot(city_sizes, min_search_oh, yaxis=:log, seriestype=:scatter,legend=false)\n", - "plot!(city_sizes, min_search_oh, yaxis=:log, legend=false)\n", - "\n", - "xlabel!(\"Number of cities\")\n", - "ylabel!(\"Search overhead (s)\")\n", - "title!(\"Minimum search overhead for different problem sizes\")" + "# Plot\n", + "plot(n_cities, avg_search_overhead, ribbon=conf_int, markershape=:circle, legend=false)\n", + "title!(\"Average search overhead (%) and 95%-CI \\nin parallel algorithm\")\n", + "ylabel!(\"Average % extra nodes visited \\n in parallel algorithm\")\n", + "xlabel!(\"Number of cities\")" ] }, { diff --git a/dev/notebooks/solutions/index.html b/dev/notebooks/solutions/index.html index f27daf0..65d927b 100644 --- a/dev/notebooks/solutions/index.html +++ b/dev/notebooks/solutions/index.html @@ -18,4 +18,4 @@ var myIframe = document.getElementById("notebook"); iFrameResize({log:true}, myIframe); }); - + diff --git a/dev/notebooks/tsp/index.html b/dev/notebooks/tsp/index.html index d967f20..9bdeeea 100644 --- a/dev/notebooks/tsp/index.html +++ b/dev/notebooks/tsp/index.html @@ -18,4 +18,4 @@ var myIframe = document.getElementById("notebook"); iFrameResize({log:true}, myIframe); }); - + diff --git a/dev/search/index.html b/dev/search/index.html index 0b45651..861ed81 100644 --- a/dev/search/index.html +++ b/dev/search/index.html @@ -1,2 +1,2 @@ -Search · XM_40017

Loading search...

    +Search · XM_40017

    Loading search...