AUTH's THMMY "Parallel and distributed systems" course assignments.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

bitonic_v05.jl 3.0 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #
  2. # ---------------------------------------------
  3. # Bitonic v0.5 functionality
  4. #
  5. function partner(node, step)
  6. partner = node + ((((node+step) % 2) == 0) ? 1 : -1)
  7. end
  8. function active(id, p)
  9. ret = (id >= 0) && (id < p)
  10. end
  11. function exchange(localid, remoteid)
  12. if verbose
  13. println("Exchange local data from $localid with partner $remoteid")
  14. end
  15. nothing # We have all data here ;)
  16. end
  17. function minmax(data, localid, remoteid, keepsmall)
  18. # Keep min-max on local data
  19. temp = copy(data[localid+1, :])
  20. if (keepsmall)
  21. view(data, localid+1, :) .= min.(temp, data[remoteid+1, :])
  22. view(data, remoteid+1, :) .= max.(temp, data[remoteid+1, :])
  23. else
  24. view(data, localid+1, :) .= max.(temp, data[remoteid+1, :])
  25. view(data, remoteid+1, :) .= min.(temp, data[remoteid+1, :])
  26. end
  27. end
  28. """
  29. distbubletonic!(p, data)
  30. distributed bitonic v0.5 sort using a "bubble sort"-like functionality to propagate large and small
  31. items between nodes.
  32. p: The number of processes
  33. data: (p, N/p) array
  34. """
  35. function distbubletonic!(p, data)
  36. pid = 0:p-1
  37. ascending = mod.(pid,2) .== 0
  38. if verbose
  39. println("ascending: $ascending")
  40. end
  41. # local full sort here (run all MPI nodes)
  42. for i in 1:p
  43. sort!(view(data, i, :), rev = !ascending[i])
  44. end
  45. for step in 0:p-1
  46. direction = [true for x = 1:p]
  47. partnerid = partner.(pid, step)
  48. activeids = active.(partnerid, p)
  49. keepsmall = pid .< partnerid
  50. if verbose
  51. println("step: $step | active ids: $activeids | partner: $partnerid | keepsmall: $keepsmall")
  52. end
  53. # exchange with partner and keep small or large (run all MPI nodes)
  54. for i in 0:p-1
  55. l_idx = i+1
  56. r_idx = partnerid[i+1]+1
  57. if activeids[l_idx] && i < partnerid[l_idx]
  58. exchange(i, partnerid[l_idx])
  59. minmax(data, i, partnerid[l_idx], keepsmall[l_idx])
  60. sort!(view(data, l_idx, :), rev = !ascending[l_idx]) # elbow sort here
  61. sort!(view(data, r_idx, :), rev = !ascending[r_idx]) # elbow sort here
  62. end
  63. end
  64. end
  65. # [optional] reverse the odd positions (run all MPI nodes)
  66. for i in 1:p
  67. if !ascending[i]
  68. sort!(view(data, i, :))
  69. end
  70. end
  71. nothing
  72. end
  73. #
  74. # Homework setup
  75. # ---------------------------------------------
  76. #
  77. p::Int8 = 3 # The order of number of "processors"
  78. q::Int8 = 8 # The data size order (power of 2) of each "processor"
  79. verbose = false;
  80. # Run Script
  81. # ---------------------------------------------
  82. P::Int = 2^p
  83. Q::Int = 2^q
  84. N::Int = 2^(q+p)
  85. println("Distributed Bubbletonic (v0.5) test")
  86. println("p: $p -> Number of processors: $P")
  87. println("q: $q -> Data length for each node: $Q, Total: $(P*Q)")
  88. println("Create an $P x $Q array")
  89. Data = rand(Int8, P, Q)
  90. println("Sort array with $P (MPI) nodes")
  91. @time distbubletonic!(P, Data)
  92. # Test
  93. if issorted(vec(permutedims(Data)))
  94. println("Test: Passed")
  95. else
  96. println("Test: Failed")
  97. end