starpu_paje_summary.Rmd 12 KB

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