starpu_paje_summary.Rmd 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. # StarPU --- Runtime system for heterogeneous multicore architectures.
  2. #
  3. # Copyright (C) 2014-2021 Université de Bordeaux, CNRS (LaBRI UMR 5800), Inria
  4. #
  5. # StarPU is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU Lesser General Public License as published by
  7. # the Free Software Foundation; either version 2.1 of the License, or (at
  8. # your option) any later version.
  9. #
  10. # StarPU is distributed in the hope that it will be useful, but
  11. # WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. #
  14. # See the GNU Lesser General Public License in COPYING.LGPL for more details.
  15. #
  16. <div id="table-of-contents">
  17. <h2>Table of Contents</h2>
  18. <div id="text-table-of-contents">
  19. <ul>
  20. <li><a href="#sec-1">1. Introduction</a>
  21. <ul>
  22. <li>
  23. <ul>
  24. <li><a href="#sec-1-0-1">1.0.1. How to compile</a></li>
  25. <li><a href="#sec-1-0-2">1.0.2. Software dependencies</a></li>
  26. </ul>
  27. </li>
  28. </ul>
  29. </li>
  30. <li><a href="#sec-2">2. Gantt Charts of the whole Trace</a></li>
  31. <li><a href="#sec-3">3. Table Summary</a></li>
  32. <li><a href="#sec-4">4. State Duration during the Execution Time</a></li>
  33. <li><a href="#sec-5">5. Distribution Histograms</a></li>
  34. </ul>
  35. </div>
  36. </div>
  37. ```{r Setup, echo=FALSE}
  38. opts_chunk$set(echo=FALSE)
  39. ```
  40. ```{r Install_R_libraries}
  41. InstalledPackage <- function(package)
  42. {
  43. available <- suppressMessages(suppressWarnings(sapply(package, require, quietly = TRUE, character.only = TRUE, warn.conflicts = FALSE)))
  44. missing <- package[!available]
  45. if (length(missing) > 0) return(FALSE)
  46. return(TRUE)
  47. }
  48. CRANChoosen <- function()
  49. {
  50. return(getOption("repos")["CRAN"] != "@CRAN@")
  51. }
  52. UsePackage <- function(package, defaultCRANmirror = "http://cran.at.r-project.org")
  53. {
  54. if(!InstalledPackage(package))
  55. {
  56. if(!CRANChoosen())
  57. {
  58. chooseCRANmirror()
  59. if(!CRANChoosen())
  60. {
  61. options(repos = c(CRAN = defaultCRANmirror))
  62. }
  63. }
  64. suppressMessages(suppressWarnings(install.packages(package)))
  65. if(!InstalledPackage(package)) return(FALSE)
  66. }
  67. return(TRUE)
  68. }
  69. # Now install desired libraries
  70. libraries <- c("ggplot2", "plyr", "data.table", "RColorBrewer")
  71. for(libr in libraries)
  72. {
  73. if(!UsePackage(libr))
  74. {
  75. stop("Error!", libr)
  76. }
  77. }
  78. ```
  79. ```{r Load_R_files}
  80. # Load ggplot and plyr just for the following cases
  81. library(ggplot2)
  82. library(plyr)
  83. library(data.table)
  84. library(RColorBrewer)
  85. # Defining non-computation states:
  86. def_states<-c("Initializing","Deinitializing","Overhead","Nothing","Sleeping","Freeing","Allocating","WritingBack","FetchingInput","PushingOutput","Callback","Progressing","Unpartitioning","AllocatingReuse","Reclaiming","DriverCopy","DriverCopyAsync","Scheduling","Executing")
  87. # Function for reading .csv file
  88. read_df <- function(file,range1,range2) {
  89. df<-read.csv(file, header=FALSE, strip.white=TRUE)
  90. names(df) <- c("Nature","ResourceId","Type","Start","End","Duration", "Depth", "Value")
  91. df = df[!(names(df) %in% c("Nature","Type", "Depth"))]
  92. df$Origin<-as.factor(as.character(file))
  93. # Changing names if needed:
  94. df$Value <- as.character(df$Value)
  95. df$Value <- ifelse(df$Value == "F", "Freeing", as.character(df$Value))
  96. df$Value <- ifelse(df$Value == "A", "Allocating", as.character(df$Value))
  97. df$Value <- ifelse(df$Value == "W", "WritingBack", as.character(df$Value))
  98. df$Value <- ifelse(df$Value == "No", "Nothing", as.character(df$Value))
  99. df$Value <- ifelse(df$Value == "I", "Initializing", as.character(df$Value))
  100. df$Value <- ifelse(df$Value == "D", "Deinitializing", as.character(df$Value))
  101. df$Value <- ifelse(df$Value == "Fi", "FetchingInput", as.character(df$Value))
  102. df$Value <- ifelse(df$Value == "Po", "PushingOutput", as.character(df$Value))
  103. df$Value <- ifelse(df$Value == "C", "Callback", as.character(df$Value))
  104. df$Value <- ifelse(df$Value == "B", "Overhead", as.character(df$Value))
  105. df$Value <- ifelse(df$Value == "Sc", "Scheduling", as.character(df$Value))
  106. df$Value <- ifelse(df$Value == "E", "Executing", as.character(df$Value))
  107. df$Value <- ifelse(df$Value == "Sl", "Sleeping", as.character(df$Value))
  108. df$Value <- ifelse(df$Value == "P", "Progressing", as.character(df$Value))
  109. df$Value <- ifelse(df$Value == "U", "Unpartitioning", as.character(df$Value))
  110. df$Value <- ifelse(df$Value == "Ar", "AllocatingReuse", as.character(df$Value))
  111. df$Value <- ifelse(df$Value == "R", "Reclaiming", as.character(df$Value))
  112. df$Value <- ifelse(df$Value == "Co", "DriverCopy", as.character(df$Value))
  113. df$Value <- ifelse(df$Value == "CoA", "DriverCopyAsync", as.character(df$Value))
  114. # Small cleanup
  115. df$Start<-round(df$Start,digit=1)
  116. df$End<-round(df$End,digit=1)
  117. df$ResourceId<-as.factor(df$ResourceId)
  118. df$Value<-as.factor(df$Value)
  119. # Start from zero
  120. m <- min(df$Start)
  121. df$Start <- df$Start - m
  122. df$End <- df$Start+df$Duration
  123. # Return data frame
  124. df
  125. }
  126. ```
  127. ```{r Load_traces}
  128. df<-data.frame()
  129. if( !exists("input_traces") )
  130. input_traces<-c("example.native.trace.csv", "example.simgrid.trace.csv")
  131. for (i in 1:length(input_traces)){
  132. dfs<-read_df(input_traces[i])
  133. df<-rbindlist(list(df,dfs))
  134. }
  135. # Color palettes
  136. colourCount = length(unique(df$Value))
  137. getPalette = colorRampPalette(brewer.pal(9, "Set1"))
  138. # Order of Value so we can have good colors
  139. ker_states<-as.character(unique(df[!(df$Value %in% def_states),Value]))
  140. ordered_states<-append(sort(ker_states), def_states)
  141. df$Value <- factor(df$Value, levels=ordered_states)
  142. # Order of ResourceId so we can have y-axis
  143. df$ResourceId <- factor(df$ResourceId, levels=sort(as.character(unique(df$ResourceId))))
  144. ```
  145. # Introduction
  146. This document presents a basic analysis of multiple StarPU
  147. traces. First, paje *traces* will be transferred into *.csv* files and
  148. then we analyze them with **R**. This summary is a first step that
  149. should help researchers verify their hypothesis or find problematic
  150. areas that require more exhaustive investigation.
  151. Be cautious, as the following results are only a brief analysis of
  152. the traces and many important phenomena could still be hidden. Also,
  153. be very careful when comparing different states or traces. Even
  154. though some large discrepancies can be irrelevant, in other cases
  155. even the smallest differences can be essential in understanding what
  156. exactly happened during the StarPU execution.
  157. ### How to compile
  158. ./starpu_summary.sh example.native.trace example.simgrid.trace
  159. ### Software dependencies
  160. In order to run this analysis you need to have R installed:
  161. sudo apt-get install r-base
  162. Easiest way to transform *paje* traces generated by StarPU to *.csv* is to use *pjdump* program (<https://github.com/schnorr/pajeng>), so we encourage users to install it.
  163. When R is installed, one will need to start R (e.g., from terminal) and install *knitr* package:
  164. R> install.packages("knitr")
  165. Additional R packages used in this analysis (*ggplot2, plyr, data.table, RColorBrewer*) will be installed automatically when the document is compiled for the first time. If there is any trouble, install them by hand directly from R (the same way as *knitr*)
  166. # Gantt Charts of the whole Trace
  167. First, we show a simple gantt chart of every trace. X-axis is a
  168. simple timeline of the execution, *Resources* on y-axis correspond
  169. to different CPUs/GPUs that were used and finally different colors
  170. represent different *States* of the application.
  171. This kind of figures can often point to the idle time or
  172. synchronization problems. Small disadvantage is that in most cases
  173. there are too many states, thus it is impossible to display them all
  174. on a single plot without aggregation. Therefore for any strange
  175. behavior at a certain part of the trace, we strongly suggest to zoom
  176. on the interval it occurred.
  177. ```{r Gantt1}
  178. ggplot(df,aes(x=Start,xend=End, y=factor(ResourceId), yend=factor(ResourceId),color=Value)) +
  179. theme_bw() + scale_color_manual(name="State",values=getPalette(colourCount)) +
  180. geom_segment(size=8) + ylab("Resource") + xlab("Time [ms]") +
  181. facet_wrap(~Origin,ncol=1,scale="free_y")
  182. ```
  183. Second, we will concentrate only on computation kernel states, to
  184. get rid of visualization artifacts that can be introduced by other
  185. (sometimes irrelevant) states. Normally, this plot should not be too
  186. different from the previous one.
  187. ```{r Gantt2}
  188. # Select only computation kernels
  189. df1 <- df[!(df$Value %in% c("Initializing","Deinitializing","Overhead","Nothing","Sleeping","Freeing","Allocating","WritingBack","FetchingInput","PushingOutput","Callback","Progressing","Unpartitioning","AllocatingReuse","Reclaiming","DriverCopy","DriverCopyAsync","Scheduling","Executing")),]
  190. # Start from zero
  191. m <- min(df1$Start)
  192. df1$Start <- df1$Start - m
  193. df1$End <- df1$Start+df1$Duration
  194. # Plot
  195. ggplot(df1,aes(x=Start,xend=End, y=factor(ResourceId), yend=factor(ResourceId),color=Value)) +
  196. theme_bw() + scale_color_manual(name="State",values=getPalette(colourCount)) +
  197. geom_segment(size=8) + ylab("Resource") + xlab("Time [ms]") +
  198. facet_wrap(~Origin,ncol=1,scale="free_y")
  199. ```
  200. # Table Summary
  201. Here we present how much time application spent in each state
  202. (OverallDuration), how many times it was in that state (Count),
  203. mean and median values of duration (Mean and Median), and finally
  204. what is a standard deviation (StandDev).
  205. General information provided by this table can sometimes give an
  206. idea to application experts which parts of code are not working as
  207. desired. Be aware that this kind of tables hide many important
  208. things, such as outliers, multiple modes, etc.
  209. ```{r Table}
  210. options(width=120)
  211. ddply(df,.(Value,Origin), summarize, OverallDuration=sum(Duration), Count=length(Duration), Mean=mean(Duration), Median=median(Duration), StandDev=sd(Duration))
  212. ```
  213. # State Duration during the Execution Time
  214. Now, we show how duration of each state was changing during the
  215. execution. This can display a general behavior of a state; show if
  216. there are outliers or multiple modes; are some events occurring in
  217. groups, etc. . It can also suggest a strange behavior of a state
  218. during a certain time interval, which should be later investigated
  219. more carefully.
  220. However, since each event is represented by a single point (and
  221. there is no "alpha" factor), those events that happen almost
  222. simultaneously are overplotted. Therefore density of events along
  223. execution time may not be easy to read.
  224. ```{r Dur}
  225. ggplot(df,aes(x=Start,y=Duration)) + geom_point(aes(color=Value)) + theme_bw() + scale_color_manual(name="State",values=getPalette(colourCount)) + ggtitle("State Duration during the Execution Time") + theme(legend.position="none") + ylab("Duration [ms]") + xlab("Time [ms]") + facet_grid(Value~Origin, scale="free_y")
  226. ```
  227. # Distribution Histograms
  228. Finally, we show a distribution of *Duration* for each state in form
  229. of histograms. X-axis is partitioned into bins with equidistant time
  230. intervals in milliseconds, while y-axis represents the number of
  231. occurrences inside such intervals for a certain state. Note that for
  232. the first plot y-axis is not fixed, meaning that the scale changes
  233. from one row to another. This plot allows to not only to see what
  234. was the most frequent duration of a state, but also to compare
  235. duration between different states.
  236. ```{r Hist1}
  237. ggplot(df, aes(x=Duration)) + geom_histogram(aes(y=..count..,fill=factor(Value)),binwidth = diff(range(df$Duration))/30) + theme_bw() + scale_fill_manual(name="State",values=getPalette(colourCount)) + ggtitle("Histograms for State Distribution") + ylab("Count") + xlab("Duration [ms]") + theme(legend.position="none") + facet_grid(Value~Origin,scales = "free_y")
  238. ```
  239. Similar to the previous figure, only now traces are showed vertically
  240. instead of horizontally. Note that for this plot x-axis is not fixed,
  241. meaning that the scale changes from one column to another. This plot
  242. allows to compare frequency of different states and in case of
  243. multiple traces to easily compare duration distribution for each
  244. state.
  245. ```{r Hist2}
  246. ggplot(df, aes(x=Duration)) + geom_histogram(aes(y=..count..,fill=factor(Value)),binwidth = diff(range(df$Duration))/30) + theme_bw() + scale_fill_manual(name="State",values=getPalette(colourCount)) + ggtitle("Histograms for State Distribution") + ylab("Count") + xlab("Duration [ms]") + theme(legend.position="none") + facet_grid(Origin~Value,scales = "free_x")
  247. ```