starpu_paje_summary.Rmd 11 KB

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