basicBoundaryRelocator.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. # Copyright 2014 Modelling, Simulation and Design Lab (MSDL) at
  2. # McGill University and the University of Antwerp (http://msdl.cs.mcgill.ca/)
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. from pypdevs.relocators.boundaryRelocator import BoundaryRelocator
  16. from heapq import heappop, heappush, heapify
  17. class BasicBoundaryRelocator(BoundaryRelocator):
  18. """
  19. Basic implementation of a boundary relocator
  20. """
  21. def __init__(self, swappiness):
  22. """
  23. Constructor
  24. :param swappiness: the swappiness
  25. """
  26. BoundaryRelocator.__init__(self)
  27. self.swappiness = swappiness
  28. def setController(self, controller):
  29. """
  30. Configures the controller of this relocator
  31. :param controller: the controller
  32. """
  33. BoundaryRelocator.setController(self, controller)
  34. def getRelocations(self, gvt, activities, horizon):
  35. """
  36. Return all pending relocations
  37. :param gvt: current GVT
  38. :param activities: activities being passed on the GVT ring
  39. :param horizon: the time over which the activities were gathered
  40. :returns: all relocations that should be executed
  41. """
  42. # Clear all 'semi-global' variables
  43. self.relocate = {}
  44. self.model_activities = {}
  45. self.node_activities = [i[1] for i in activities]
  46. avg_activity = sum(self.node_activities) / len(self.node_activities)
  47. reverts = set()
  48. iterlist = [(activity, node)
  49. for node, activity in enumerate(self.node_activities)
  50. if activity > self.swappiness * avg_activity]
  51. heapify(iterlist)
  52. if sum(self.locations) == 0:
  53. self.locations = [model.location for model in self.model_ids]
  54. self.boundaries = [{} for _ in range(self.kernels)]
  55. self.constructBoundaries(self.model_ids)
  56. while iterlist:
  57. # Keep going as long as there are nodes that are overloaded
  58. srcactivity, node = heappop(iterlist)
  59. # Might have changed in the meantime, though NEVER decreased
  60. srcactivity = self.node_activities[node]
  61. # Now 'node' contains the node that has the most activity of all, so try pushing something away
  62. boundaries = self.boundaries[node]
  63. destactivity, mindest = \
  64. min([(self.node_activities[destination], destination)
  65. for destination in boundaries
  66. if boundaries[destination]])
  67. boundary = boundaries[mindest]
  68. source_deviation = srcactivity - avg_activity
  69. destination_deviation = destactivity - avg_activity
  70. original_heuristic = abs(source_deviation) + \
  71. abs(destination_deviation)
  72. move = None
  73. for option in boundary:
  74. # Swapping the model would give us the following new 'heuristic'
  75. model_activity = self.fetchModelActivity(option)
  76. new_heuristic = abs(source_deviation - model_activity) + \
  77. abs(destination_deviation + model_activity)
  78. if new_heuristic < original_heuristic:
  79. move = option.model_id
  80. original_heuristic = new_heuristic
  81. if move is not None:
  82. # Will migrate model 'move' to 'mindest'
  83. self.scheduleMove(move, mindest)
  84. if srcactivity - model_activity > avg_activity:
  85. heappush(iterlist, (srcactivity - model_activity, node))
  86. if destactivity + model_activity > avg_activity:
  87. # The destination now also became overloaded, so push from this node as well
  88. heappush(iterlist, (destactivity + model_activity, mindest))
  89. return self.relocate
  90. def useLastStateOnly(self):
  91. """
  92. Determines whether or not the activities of all steps should be accumulated, or only a single state should be used.
  93. :returns: boolean -- True if the relocator works with a single state
  94. """
  95. return False