AUTH's THMMY "Parallel and distributed systems" course assignments.
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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