diff --git a/notebooks/solutions.ipynb b/notebooks/solutions.ipynb
index 779d2d7..0a79c0c 100644
--- a/notebooks/solutions.ipynb
+++ b/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"
+ ],
+ "text/html": [
+ "\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\")"
]
},
{