#!/bin/sh # # Copyright (C) 2009-2012 Thomas Preud'homme # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. set -u init_bench_vars () { local ourBenchs onlyWBBenchs comList com - ourBenchs="batch_queue" onlyWBBenchs="jikes_barrier" comList=`ls *.log | perl -ni -e '/-([^-]+)_comm/; $a{$1}=""; END { foreach ( sort keys %a ) {print "$_ "}}'` if [ -z "${barriereList:-}" ] then for com in $comList do if echo $com | grep "$ourBenchs" > /dev/null 2>&1 then barriereList="${barriereList:-}${barriereList:+ }$com" fi if echo $com | grep "$onlyWBBenchs" > /dev/null 2>&1 then barriereList="${barriereList:-}${barriereList:+ }$com" fi done fi if [ -z "${communicationList:-}" ] then for com in $comList do if echo $onlyWBBenchs | grep -v "$com" > /dev/null 2>&1 then communicationList="${communicationList:-}${communicationList:+ }$com" fi done fi } init_log_vars () { local firstBarriereComm - cacheList=`ls *log | perl -ni -e '/cache_([^-]+)-/; $a{$1}=""; END { foreach ( sort keys %a ) {print "$_ "}}' | sed -r "s/ +\$//"` prodList=`ls *.log | perl -ni -e '/typeProd_([^-]+)-/; $a{$1}=""; END { foreach ( sort keys %a ) {print "$_ "}}'` metriqueList="cache_hits cache_miss cycles total_time" nbIter=`ls -1 *.log | head -1 | sed -r "s/^.*nbIter_([[:digit:]]+).*$/\1/"` valuePerCacheLine=$(grep "^buf size: " *.log | head -1 | sed -r "s/^.*:buf size: ([[:digit:]]+)[^[:digit:]+]$/\1/") } parse_args () { local opt optNum - logDir=$(pwd) optNum=0 while [ $# -gt $optNum ] do optNum=$((optNum + 1)) eval opt=\$$optNum case $opt in "-e") if [ $# -gt $optNum ] then optNum=$((optNum + 1)) eval opt=\$$optNum eval "$opt" else echo "Missing argument after \"-e\"" return 1 fi ;; *) logDir="$opt" ;; esac done return 0 } use_histo () { local prod bench - prod="$1" bench="$2" [ "$prod" != "useless_loop" -a "$prod" != "line" ] return $? } contains_zero() { local prod bench datFile lineNum commTechs nbCommTechs nbArg iMin iMax - prod="$1" bench="$2" datFile="$3" lineNum="$4" numCacheConfigs="$5" if use_histo "$prod" "$bench" then eval commTechs=\$${bench}List # Count the number of spaces in the list + the line feed nbCommTechs=$(echo $commTechs | sed -r "s/[^ ]//g" | wc -c) iMin=$((lineNum + 4)) iMax=$((lineNum + 1 + nbCommTechs * 3)) for i in $(seq $iMin 3 $iMax) do if head -$i $datFile | tail -1 | grep -E "\.0+([^[:digit:]])?$" > /dev/null then return 0 fi done else iMin=$((lineNum + numCacheConfigs * 4 + 1)) # Number of lines in the file nbArg=$(wc -l $datFile | cut -d ' ' -f 1) nbArg=$((nbArg + 1)) # Last line doesn't contain a newline nbArg=$((nbArg - 4 * numCacheConfigs + 1)) nbArg=$((nbArg / numCacheConfigs / 4)) iMax=$((iMin + nbArg * numCacheConfigs * 4 - 4)) for i in $(seq $iMin 4 $iMax) do if head -$i $datFile | tail -1 | grep -E "\.0+([^[:digit:]])?$" > /dev/null then return 0 fi done fi return 1 } create_dat_header () { local prod bench metrique numCacheConfigs - prod="$1" bench="$2" metrique="$3" numCacheConfigs="$4" # Create file > bench_$bench-prod_$prod-metrique_$metrique.dat # Only one point per com and cache if use_histo "$prod" "$bench" then for i in 1 2 3 # 1: total, 2: by loop, 3: by write do if [ $i -ne 1 ] then echo >> bench_$bench-prod_$prod-metrique_$metrique.dat fi echo -n "Method\t\t" >> bench_$bench-prod_$prod-metrique_$metrique.dat for cache in $cacheList do echo -n "\t$cache" >> bench_$bench-prod_$prod-metrique_$metrique.dat done done # Several points per com and cache (one per calc argument) else for i in $(seq "$numCacheConfigs") do if [ $i -ne 1 ] then echo >> bench_$bench-prod_$prod-metrique_$metrique.dat fi for j in 1 2 3 # 1: total, 2: by loop, 3: by write do echo -n "argTypeProd\t\t" >> bench_$bench-prod_$prod-metrique_$metrique.dat for com in `eval echo \\\$\${bench}List` do echo -n "\t$com" >> bench_$bench-prod_$prod-metrique_$metrique.dat done echo >> bench_$bench-prod_$prod-metrique_$metrique.dat done done fi } get_metric_values () { local prod com cache argTypeProd logFile metricValues totalValue metricValue loopValue stepValue - prod="$1" com="$2" cache="$3" argTypeProd="$4" metriquePattern="$5" logFile=cache_$cache-*-typeProd_$prod-argTypeProd_$argTypeProd-*-${com}_comm.log metricValues=$(grep -E "$metriquePattern" $logFile | sed -r "s/^ *($metriquePattern).*$/\1/;s/^ *([[:digit:]., ]+).*$/\1/;s/[,.]/./" | tr -d ' ') totalValue=0 for metricValue in $metricValues do totalValue=$(echo "$totalValue + $metricValue" | bc) done echo -n "$totalValue" loopValue="$(echo "$totalValue / $nbIter" | bc -l)" echo -n " $loopValue" stepValue=$(echo "$totalValue / $nbIter / $valuePerCacheLine" | bc -l) echo -n " $stepValue" } create_simple_dat_body () { local prod bench metrique argTypeProd - prod="$1" bench="$2" metrique="$3" argTypeProd="$4" for com in `eval echo \\\$\${bench}List` do for i in 1 2 3 # 1: total, 2: by loop, 3: by write do echo -n "\n$com\t\t" >> bench_$bench-prod_$prod-metrique_$metrique.dat for cache in $cacheList do if [ $i -eq 1 ] then valuetmp=`get_metric_values "$prod" "$com" "$cache" "$argTypeProd" "$metriquePattern"` eval value$cache=\"$valuetmp\" fi eval echo -n "\${value$cache}" | sed -r "s/^([^ ]+ ){$((i-1))}([^ ]+).*/\t\2/" >> bench_$bench-prod_$prod-metrique_$metrique.dat done done done } create_complex_dat_body () { local prod bench metrique firstComm argTypeProdList argTypeProd - prod="$1" bench="$2" metrique="$3" metriquePattern="$4" firstComm=$(ls -1 *typeProd_$prod*.log | head -1 | sed -r "s/^.*nbIter_[^-]+-([^.]+)\.log$/\1/") argTypeProdList=`eval ls *typeProd_$prod*${firstComm}.log | perl -ni -e '/argTypeProd_([\d]+)-/; $a{$1}=""; END { foreach ( sort { $a <=> $b } keys %a ) {print "$_ "}}'` for argTypeProd in $argTypeProdList do for cache in $cacheList do if [ $cache != ${cacheList%% *} -o $argTypeProd != ${argTypeProdList%% *} ] then echo "" >> bench_$bench-prod_$prod-metrique_$metrique.dat fi for i in 1 2 3 # 1: total, 2: by loop, 3: by write do echo -n "\n$argTypeProd\t\t" >> bench_$bench-prod_$prod-metrique_$metrique.dat for com in `eval echo \\\$\${bench}List` do if [ $i -eq 1 ] then valuetmp=`get_metric_values "$prod" "$com" "$cache" "$argTypeProd" "$metriquePattern"` eval value$com=\"$valuetmp\" fi eval echo -n "\${value$com}" | sed -r "s/^([^ ]+ ){$((i-1))}([^ ]+).*/\t\2/" >> bench_$bench-prod_$prod-metrique_$metrique.dat done done done done } create_dat_body () { local prod bench metrique argTypeProd - prod="$1" bench="$2" metrique="$3" argTypeProd="$4" if use_histo "$prod" "$bench" then create_simple_dat_body "$prod" "$bench" "$metrique" "$argTypeProd" "$metriquePattern" else create_complex_dat_body "$prod" "$bench" "$metrique" "$metriquePattern" fi } create_gnuplot_header () { local prod bench gnuplotFile - prod="$1" bench="$2" gnuplotFile="$3" echo "set style fill solid border -1" > $gnuplotFile echo "set boxwidth 0.9" >> $gnuplotFile echo "set xtic rotate by -45" >> $gnuplotFile echo "set bmargin 5" >> $gnuplotFile echo "set terminal postscript landscape color" >> $gnuplotFile if use_histo "$prod" "$bench" then echo "set key autotitle columnhead" >> $gnuplotFile echo "set style data histogram" >> $gnuplotFile echo "set style histogram cluster gap 1" >> $gnuplotFile else echo "set style data linespoints" >> $gnuplotFile fi } create_simple_gnuplot_body () { local metrique ylabel yscale patternPlotFile datFile numCacheConfigs i - ylabel="$1" lineNum="$2" datFile="$3" patternPlotFile="$4" numCacheConfigs="$5" echo "set ylabel \"$ylabel\"" >> $patternPlotFile.gnuplot echo "set output 'images/$patternPlotFile.ps'" >> $patternPlotFile.gnuplot echo -n "plot '$datFile' every 3::$lineNum using 2:xtic(1)" >> $patternPlotFile.gnuplot if [ $numCacheConfigs -ge 2 ] then i=2 while [ $i -le $numCacheConfigs ] do echo -n " , '' every 3::$lineNum u $((i+1))" >> $patternPlotFile.gnuplot i=$((i+1)) done fi echo "" >> $patternPlotFile.gnuplot } create_complex_gnuplot_body () { local bench ylabel lineNum datFile patternPlotFile columnNo baseTitle numCacheConfigs - bench="$1" ylabel="$2" lineNum="$3" datFile="$4" patternPlotFile="$5" numCacheConfigs="$6" columnNo=2 echo "set ylabel \"$ylabel\"" >> $patternPlotFile.gnuplot echo "set output 'images/$patternPlotFile.ps'" >> $patternPlotFile.gnuplot for com in `eval echo \\\$\${bench}List` ; do baseTitle=`head -1 $datFile | cut -f $((columnNo + 2))` if [ $columnNo -ne 2 ] then echo -n ", '' " >> $patternPlotFile.gnuplot else echo -n "plot '$datFile' " >> $patternPlotFile.gnuplot fi echo -n "every :$numCacheConfigs:$lineNum:$((numCacheConfigs)):$lineNum using 1:$columnNo:xtic(1) title '$baseTitle (L2)'" >> $patternPlotFile.gnuplot if [ $numCacheConfigs -gt 2 ] then echo -n ", '' every :$numCacheConfigs:$lineNum:$((numCacheConfigs * 2)):$lineNum using 1:$columnNo:xtic(1) title '$baseTitle (mem)'" >> $patternPlotFile.gnuplot fi columnNo=$((columnNo + 1)) done echo >> $patternPlotFile.gnuplot } create_gnuplot_body () { local prod bench yscale ylabel lineNum datFile patternPlotFile numCacheConfigs - prod="$1" bench="$2" yscale="$3" ylabel="$4" lineNum="$5" datFile="$6" patternPlotFile="$7" numCacheConfigs="$8" echo "set $yscale y" >> $patternPlotFile.gnuplot if [ "$yscale" = "nologscale" ] then echo "set yrange [0:*]" >> $patternPlotFile.gnuplot else echo "set yrange [*:*]" >> $patternPlotFile.gnuplot fi echo "set title \"Producteur : $prod\"" >> $patternPlotFile.gnuplot if use_histo "$prod" "$bench" then create_simple_gnuplot_body "$ylabel" "$lineNum" "$datFile" "$patternPlotFile" "$numCacheConfigs" else create_complex_gnuplot_body "$bench" "$ylabel" "$lineNum" "$datFile" "$patternPlotFile" "$numCacheConfigs" fi } create_gnuplot_file () { local prod bench metrique ylabel yscale avg lineNum numCacheConfigs - prod="$1" bench="$2" metrique="$3" baseYlabel="$4" numCacheConfigs="$5" for yscale in "nologscale" "logscale" do for avg in total byLoop byWrite do case $avg in total) lineNum=0 ylabel="$baseYlabel" ;; byLoop) lineNum=1 ylabel="$baseYlabel par boucle" ;; byWrite) lineNum=2 ylabel="$baseYlabel par ecriture" ;; esac datFile=bench_$bench-prod_$prod-metrique_$metrique.dat patternPlotFile="bench_$bench-prod_$prod-$metrique-$avg-$yscale" # Name without extension of plot and ps files if [ $yscale != "logscale" ] || ! contains_zero "$prod" "$bench" "$datFile" "$lineNum" "$numCacheConfigs" then create_gnuplot_header "$prod" "$bench" "$patternPlotFile.gnuplot" create_gnuplot_body "$prod" "$bench" "$yscale" "$ylabel" "$lineNum" "$datFile" "$patternPlotFile" "$numCacheConfigs" fi done done } main() { local logDir benchName - parse_args "$@" cd $logDir init_bench_vars init_log_vars for prod in $prodList ; do case "$prod" in matrice) argTypeProd=\* ;; *) argTypeProd=\* ;; esac for bench in "communication" "barriere" ; do eval benchName="\${${bench}List:-}" if [ -n "${benchName}" ] then # Create dat headers for metrique in $metriqueList ; do case "$metrique" in cache_hits) metriquePattern="[[:digit:] ]+(L1-dcache-loads|L1-dcache-stores|L1-dcache-prefetches|LLC-loads|LLC-stores|LLC-prefetches) " ylabel="Nb cache hit" ;; cache_miss) metriquePattern="[[:digit:] ]+(L1-dcache-load-misses|L1-dcache-store-misses|L1-dcache-prefetch-misses|LLC-load-misses|LLC-store-misses|LLC-prefetch-misses) " ylabel="Nb cache miss" ;; cycles) metriquePattern="[[:digit:] ]+cycles " ylabel="Nb cycles" ;; total_time) metriquePattern="[[:digit:]., ]+seconds time elapsed " ylabel="Secondes" ;; *) echo "Pas de pattern pour cette métrique : $metrique" echo "Pas de label pour cette métrique : $metrique" exit 1 ;; esac numCacheConfigs=$(echo "$cacheList" | wc -w) create_dat_header "$prod" "$bench" "$metrique" "$numCacheConfigs" create_dat_body "$prod" "$bench" "$metrique" "$argTypeProd" "$metriquePattern" create_gnuplot_file "$prod" "$bench" "$metrique" "$ylabel" "$numCacheConfigs" done fi done done if [ ! -d images ] then mkdir images fi for gnuplotFile in *.gnuplot do gnuplot "$gnuplotFile" done cd images for psFile in *.ps do ps2pdf $psFile done } main "$@"