activity.rst 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. ..
  2. Copyright 2014 Modelling, Simulation and Design Lab (MSDL) at
  3. McGill University and the University of Antwerp (http://msdl.cs.mcgill.ca/)
  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. http://www.apache.org/licenses/LICENSE-2.0
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. Activity Tracking
  14. =================
  15. .. note:: This feature is still being worked on and all information is therefore prone to change.
  16. *Activity Tracking* is a feature that will have the simulator time the invocation of each user-defined function, being the *intTransition*, *extTransition*, *confTransition*, *outputFnc* and *timeAdvance* functions. At the end, all this timing information is gathered and a list of all timings is shown to the user. In its current state, there is not really a big use for *Activity Tracking* apart from the user being aware of the load of every seperate model.
  17. Two different output variants are currently supported:
  18. * List view: this will simply show a flat list of the name of the model, followed by its activity (in seconds). Depending on the configuration options, this will either be sorted on model name or on activity.
  19. * Cell view: this present the same information as the list view, only in a visual way. It will create a matrix-style file that contains the activity for that specific cell. This file can then be visualised using for example *Gnuplot*.
  20. The following configuration options are related to this functionality:
  21. * *setActivityTracking(at, sortOnActivity)*: enables or disables the printing of activity tracking information. Note that activity tracking is **always** performed internally, so disabling this will not increase performance.
  22. * *setActivityTrackingCellMap(cellmap, x, y)*: when activity tracking is enabled, setting this to *True* will result in a matrix-style file instead of a (printed) flat list. The resulting file will be called *activity*.
  23. In this example, we will create an activity Cell view, as this is a lot nicer than the other (more statistical) variant. Our model will be something more complex as the previous examples, but the model itself isn't really that important. A *fire spread* model was chosen, as this nicely reduces to a map and is thus perfect for Cell view.
  24. .. note:: The Cell view furthermore requires models that are to be plotted have an *x* and *y* attribute. This value will determine their location in the map. Models without such attributes will simply be ignored.
  25. This image was created by using the *experiment* file containing::
  26. x, y = 20, 20
  27. model = FireSpread(x, y)
  28. sim = Simulator(model)
  29. sim.setTerminationTime(1000.0)
  30. sim.setActivityTrackingVisualisation(True, x, y)
  31. sim.simulate()
  32. After simulation, a file called *activity* was created. This file was plotted using *gnuplot* with the commands
  33. .. code-block:: gnuplot
  34. set view map
  35. splot 'activity' matrix with image
  36. .. image:: activity.png
  37. :alt: Activity Tracking cell view
  38. :width: 100%
  39. .. note:: In order to make some more visually pleasing maps, the computation in the transition functions was severely increased. This is due to our transition function being rather small by default, which doesn't provide very accurate timings.
  40. .. warning:: Don't forget to take the word of caution (see below) into account when analyzing the results.
  41. Word of caution
  42. ---------------
  43. The *Activity Tracking* feature uses the *time.time()* function from the Python *time* library. This means that it measures *wall clock* time instead of actual *CPU* time. Should the CPU be overloaded with work, these timings will thus be inaccurate due to possible interruptions of the simulation. Most of the time however, such interrupts should arrive either outside of the timed code. Otherwise, the interrupted models should be somewhat evenly spread out, thus reducing the impact.
  44. Of course, Python provides functions to fetch the actual *CPU* time spend. These alternatives were checked, but were *insufficient* for our purpose for several reasons. The alternatives are mentioned below:
  45. * Python *time.clock()* function: this has a very low granularity on Linux, which would show total nonsense in case the transition functions are small.
  46. * Python *resource* library: this has the same problem as the *time.clock()* approach and furthermore is a lot slower
  47. * External *psutil* library: this alternative has the same problems as the above alternatives, with the additional disadvantage that it is **extremely** slow.
  48. Since *Activity Tracking* is done at every model, in every simulation step, performance of this call is critical. To show the difference between these alternatives, a *timeit* comparison is shown below:
  49. .. code-block:: bash
  50. yentl ~ $ python -m timeit -s "import time" -- "time.time()"
  51. 10000000 loops, best of 3: 0.0801 usec per loop
  52. yentl ~ $ python -m timeit -s "import time" -- "time.clock()"
  53. 10000000 loops, best of 3: 0.199 usec per loop
  54. yentl ~ $ python -m timeit -s "import resource" -- "resource.getrusage(resource.RUSAGE_SELF).ru_utime"
  55. 1000000 loops, best of 3: 0.642 usec per loop
  56. yentl ~ $ python -m timeit -s "import psutil" -- "psutil.cpu_times().user"
  57. 10000 loops, best of 3: 25.9 usec per loop
  58. As can be seen from this comparison, we have the following performance statistics:
  59. +----------+---------------+----------------------------+
  60. | method | time per loop | times slower than *time()* |
  61. +----------+---------------+----------------------------+
  62. | time() | 0.08 usec | 1x |
  63. +----------+---------------+----------------------------+
  64. | clock() | 0.199 usec | 2.5x |
  65. +----------+---------------+----------------------------+
  66. | resource | 0.642 usec | 8x |
  67. +----------+---------------+----------------------------+
  68. | psutil | 25.9 usec | 324x |
  69. +----------+---------------+----------------------------+
  70. Since this function will be called twice for every transition that happens, using one of the slower methods would have an immense difference on the actual simulation time. The main purpose of *Activity Tracking* is to increase performance, but when when e.g. *psutil* is used, the simulation is already slowed down by a massive factor, removing any chance for improvement in general situations.