X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=utils%2Fparallel%2Fgran-extr.pl;fp=utils%2Fparallel%2Fgran-extr.pl;h=509da499d619052bda81598384214f089f7bd91a;hb=0065d5ab628975892cea1ec7303f968c3338cbe1;hp=0000000000000000000000000000000000000000;hpb=28a464a75e14cece5db40f2765a29348273ff2d2;p=ghc-hetmet.git diff --git a/utils/parallel/gran-extr.pl b/utils/parallel/gran-extr.pl new file mode 100644 index 0000000..509da49 --- /dev/null +++ b/utils/parallel/gran-extr.pl @@ -0,0 +1,2114 @@ +#!/usr/local/bin/perl +############################################################################## +# Last modified: Time-stamp: +# (C) Hans Wolfgang Loidl +# +# Usage: gran-extr [options] [] +# +# Takes a file generated by running the GrAnSim simulator and +# produces data files that should be used as input for gnuplot. +# This script produces figures for: +# runtime of tasks +# percentage of communication +# heap allocation +# number of created sparks +# cumulative no. of tasks over runtime +# Furthermore, it computes the correlation between runtime and heap allocation. +# +# Options: +# -g ... filename of granularity file to be produced; should end with +# .dat; -global and -local will be automatically inserted for +# other versions. +# -c ... filename of communication file to be produced; should end with +# .dat; -global and -local will be automatically inserted for +# other versions. +# -s ... filename of sparked-threads file to be produced; should end w/ +# .dat; -global and -local will be automatically inserted for +# other versions. +# -a ... filename of heap alloc. file to be produced; should end with +# .dat; +# -f ... filename of communication time file to be produced; +# should end with .dat; +# -p ... filename of GNUPLOT file that is prouced and executed. +# -G ... provide a list of boundaries for the Intervals used in the +# granularity figure; must be a Perl list e.g. (10, 20, 50) +# this is interpreted as being open to left and right. +# -C ... provide a list of boundaries for the Intervals used in the +# communication figure; must be a Perl list e.g. (10, 20, 50) +# this is interpreted as being closed to left and right. +# -S ... provide a list of boundaries for the Intervals used in the +# sparked-threads figure; must be a Perl list e.g. (10, 20, 50) +# this is interpreted as being closed to left and right. +# -A ... provide a list of boundaries for the Intervals used in the +# heap alloc figure; must be a Perl list e.g. (10, 20, 50) +# this is interpreted as being closed to left and right. +# -F ... provide a list of boundaries for the Intervals used in the +# comm. time figure; must be a Perl list e.g. (10, 20, 50) +# this is interpreted as being open to left and right. +# -l ... left margin in the produced figures. +# -r ... right margin in the produced figures. +# -x ... enlargement of figure along x-axis. +# -y ... enlargement of figure along y-axis. +# -e ... thickness of impulses in figure. +# -i ... set the gray level of the impulses to ; must be +# between 0 and 1 with 0 meaning black. +# -k ... number of klusters (oops, clusters, I mean ;) +# -P ... print percentage of threads rather than absolute number of +# threads on the y axis +# -t ... use template for interval settings and file names +# Syntax of a line in the template file: +# : +# -T ... use smart xtics rather than GNUPLOT default x-axis naming. +# -L ... use logarithmic scale for all figures. +# -W ... print warnings +# -m ... generate monchrome output +# -h ... help; print this text. +# -v ... verbose mode. +# +############################################################################## + +# ---------------------------------------------------------------------------- +# Command line processing and initialization +# ---------------------------------------------------------------------------- + +require "getopts.pl"; + +&Getopts('hvWTPDmt:L:g:f:c:s:a:p:G:F:C:S:A:l:r:x:y:e:i:k:'); + +do process_options(); + +$OPEN_INT = 1; +$CLOSED_INT = 0; + +if ( $opt_v ) { + do print_verbose_message (); +} + +# ---------------------------------------------------------------------------- +# The real thing +# ---------------------------------------------------------------------------- + +open(INPUT,"<$input") || die "Couldn't open input file $input"; + +do skip_header(); + +$tot_total_rt = 0; +$tot_rt = 0; +$tot_bt = 0; +$tot_ft = 0; +$tot_it = 0; +$gum_style_gr = 0; + +$line_no = 0; +while () { + next if /^--/; # Comment lines start with -- + next if /^\s*$/; # Skip empty lines + $line_no++; + @fields = split(/[:,]/,$_); + $has_end = 0; + + foreach $elem (@fields) { + foo : { + $pe = $1, $end = $2 , last foo if $elem =~ /^\s*PE\s+(\d+)\s+\[(\d+)\].*$/; + $tn = $1, $has_end = 1 , last foo if $elem =~ /^\s*END\s+(\w+).*$/; + # $tn = $1 , last foo if $elem =~ /^\s*TN\s+(\w+).*$/; + $sn = $1 , last foo if $elem =~ /^\s*SN\s+(\d+).*$/; + $start = $1 , last foo if $elem =~ /^\s*ST\s+(\d+).*$/; + $is_global = $1 , last foo if $elem =~ /^\s*EXP\s+(T|F).*$/; + $bbs = $1 , last foo if $elem =~ /^\s*BB\s+(\d+).*$/; + $ha = $1 , last foo if $elem =~ /^\s*HA\s+(\d+).*$/; + $rt = $1 , last foo if $elem =~ /^\s*RT\s+(\d+).*$/; + $bt = $1, $bc = $2 , last foo if $elem =~ /^\s*BT\s+(\d+)\s+\((\d+)\).*$/; + $ft = $1, $fc = $2 , last foo if $elem =~ /^\s*FT\s+(\d+)\s+\((\d+)\).*$/; + $lsp = $1 , last foo if $elem =~ /^\s*LS\s+(\d+).*$/; + $gsp = $1 , last foo if $elem =~ /^\s*GS\s+(\d+).*$/; + $my = $1 , last foo if $elem =~ /^\s*MY\s+(T|F).*$/; + } + } + + next unless $has_end == 1; + + $total_rt = $end - $start; + $ready_time = $total_rt - $rt - $bt - $ft; + + # ------------------------------------------------------------------------ + # Accumulate runtime, block time, fetch time and ready time over all threads + # ------------------------------------------------------------------------ + + $tot_total_rt += $total_rt; + $tot_rt += $rt; + $tot_bt += $bt; + $tot_ft += $ft; + $tot_it += $ready_time; + + # ------------------------------------------------------------------------ + # Gather statistics about `load' on the PEs + # ------------------------------------------------------------------------ + + print "WARNING: ready time of thread is <0: $ready_time\n" if $pedantic && ($ready_time <0); + $pe_load[$pe] += $ready_time; + + if ( $opt_D ) { + print "Adding $ready_time to the load time of PE no. $pe yielding $pe_load[$pe]\n"; + } + + # ------------------------------------------------------------------------ + # Gather statistics about the size of a spark site + # ------------------------------------------------------------------------ + + $site_size[$sn] += $rt; + + if ( $opt_D ) { + print "Adding $rt to the size of site $sn yielding $site_size[$sn]\n"; + } + + # ------------------------------------------------------------------------ + # Gather statistics about pure exec time + # ------------------------------------------------------------------------ + + push(@all_rts,$rt); + $sum_rt += $rt; + $max_rt = $rt if $rt > $max_rt; + + $index = do get_index_open_int($rt,@exec_times); + $exec_class[$index]++; + + if ( $is_global eq 'T' ) { + $exec_global_class[$index]++; + } else { + $exec_local_class[$index]++; + } + + # ------------------------------------------------------------------------ + # Gather statistics about communication time (absolute time rather than %) + # ------------------------------------------------------------------------ + + # Note: Communicatin time is fetch time + + push(@all_fts,$ft); + $sum_ft += $ft; + $max_ft = $ft if $ft > $max_ft; + + $index = do get_index_open_int($ft,@fetch_times); + $fetch_class[$index]++; + + if ( $is_global eq 'T' ) { + $fetch_global_class[$index]++; + } else { + $fetch_local_class[$index]++; + } + + # ------------------------------------------------------------------------ + # Gather statistics about communication percentage + # ------------------------------------------------------------------------ + + $comm_perc = ( $total_rt == 0 ? 100 : (100 * $ft)/$total_rt ); + + push(@all_comm_percs,$comm_perc); + $sum_comm_perc += $comm_perc; + $max_comm_perc = $comm_perc if $comm_perc > $max_comm_perc; + + $index = do get_index_closed_int( $comm_perc, @comm_percs ); + if ( $index != -1 ) { + $comm_class[$index]++; + } else { + print "WARNING: value " . $comm_perc . " not in range (t_rt=$total_rt; ft=$ft)\n" if $pedantic; + $outside++; + } + + if ( $is_global eq 'T' ) { + if ( $index != -1 ) { + $comm_global_class[$index]++; + } else { + $outside_global++; + } + } else { + if ( $index != -1 ) { + $comm_local_class[$index]++; + } else { + $outside_local++; + } + } + + # ------------------------------------------------------------------------ + # Gather statistics about locally sparked threads + # ------------------------------------------------------------------------ + + push(@all_local_sparks,$lsp); + $sum_local_sp += $lsp; + $max_local_sp = $lsp if $lsp > $max_local_sp; + + $index = do get_index_open_int($lsp,@sparks); + $spark_local_class[$index]++; + + # ------------------------------------------------------------------------ + # Gather statistics about globally sparked threads + # ------------------------------------------------------------------------ + + push(@all_global_sparks,$gsp); + $sum_global_sp += $gsp; + $max_global_sp = $gsp if $gsp > $max_global_sp; + + $index = do get_index_open_int($gsp,@sparks); + $spark_global_class[$index]++; + + # ------------------------------------------------------------------------ + # Add the above two entries to get the total number of sparks + # ------------------------------------------------------------------------ + + $sp = $lsp + $gsp; + + push(@all_sparks,$sp); + $sum_sp += $sp; + $max_sp = $sp if $sp > $max_sp; + + $index = do get_index_open_int($sp,@sparks); + $spark_class[$index]++; + + # ------------------------------------------------------------------------ + # Gather statistics about heap allocations + # ------------------------------------------------------------------------ + + push(@all_has,$ha); + $sum_ha += $ha; + $max_ha = $ha if $ha > $max_ha; + + $index = do get_index_open_int($ha,@has); + $ha_class[$index]++; + + # do print_line($start,$end,$is_global,$bbs,$ha,$rt,$bt,$bc,$ft,$fc,$my); +} + +print STDERR "You don't want to engage me for a file with just $line_no lines, do you?(N)\n" , exit (-1) if $line_no <= 1; + +# ---------------------------------------------------------------------------- + +do write_pie_chart(); + +# ---------------------------------------------------------------------------- +# Statistics +# ---------------------------------------------------------------------------- + +if ( $opt_D ) { + print "Lengths:\n" . + " all_rts: $#all_rts;\n" . + " all_comm_percs: $#all_comm_percs;\n" . + " all_sparks: $#all_sparks; \n" . + " all_local_sparks: $#all_local_sparks; \n" . + " all_global_sparks: $#all_global_sparks; \n" . + " all_has: $#all_has\n" . + " all_fts: $#all_fts;\n"; + + + print "No of elems in all_rts: $#all_rts with sum $sum_rt\n"; + print "No of elems in all_comm_percs: $#all_rts with sum $sum_comm_perc\n"; + print "No of elems in all_has: $#all_has with sum $sum_ha\n"; + print "No of elems in all_fts: $#all_fts with sum $sum_ft\n"; + +} + +do do_statistics($line_no); + +# Just for debugging +# .................. + +if ( $opt_D ) { + open(FILE,">LOG") || die "Couldn't open file LOG\n"; + printf FILE "All total runtimes (\@all_rts:)\n"; + printf FILE "["; + printf FILE join(", ",@all_rts); + printf FILE "]\n"; + printf FILE " Mean, std. dev: $mean_rt, $std_dev_rt\n"; + printf FILE 70 x "-" . "\n"; + printf FILE "All communication times (\@all_fts:)\n"; + printf FILE "["; + printf FILE join(", ",@all_fts); + printf FILE "]\n"; + printf FILE " Mean, std. dev: $mean_ft, $std_dev_ft\n"; + printf FILE 70 x "-" . "\n"; + printf FILE "All communication percentages (\@all_comm_percs:)\n"; + printf FILE "["; + printf FILE join(", ",@all_comm_percs); + printf FILE "]\n"; + printf FILE " Mean, std. dev: $mean_comm_perc,$std_dev_comm_perc\n"; + printf FILE 70 x "-" . "\n"; + printf FILE "All sparks (\@all_sparks:)\n"; + printf FILE "["; + printf FILE join(", ",@all_sparks); + printf FILE "]\n"; + printf FILE " Mean, std. dev: $mean_spark,$std_dev_spark\n"; + printf FILE 70 x "-" . "\n"; + printf FILE "All local sparks (\@all_local_sparks:)\n"; + printf FILE "["; + printf FILE join(", ",@all_local_sparks); + printf FILE "]\n"; + printf FILE " Mean, std. dev: $mean_local_spark,$std_dev_local_spark\n"; + printf FILE 70 x "-" . "\n"; + printf FILE "All global sparks (\@all_global_sparks:)\n"; + printf FILE "["; + printf FILE join(", ",@all_global_sparks); + printf FILE "]\n"; + printf FILE " Mean, std. dev: $mean_global_spark,$std_dev_global_spark\n"; + printf FILE 70 x "-" . "\n"; + printf FILE "All local sparks (\@all_has:)\n"; + printf FILE "["; + printf FILE join(", ",@all_has); + printf FILE "]\n"; + printf FILE " Mean, std. dev: $mean_ha,$std_dev_ha\n"; + printf FILE 70 x "-" . "\n"; + + + printf FILE ("CORR of runtime and heap alloc: %f\n",$c_exec_ha); + printf FILE ("CORR of runtime and no. of sparks: %f\n",$c_exec_sp); + printf FILE ("CORR of heap alloc and no. sparks: %f\n",$c_ha_sp); + printf FILE ("CORR of runtime and local sparks: %f\n",$c_exec_lsp); + printf FILE ("CORR of runtime and global sparks: %f\n",$c_exec_gsp); + printf FILE ("CORR of heap alloc and local sparks: %f\n",$c_ha_lsp); + printf FILE ("CORR of heap alloc and global sparks: %f\n",$c_ha_gsp); + printf FILE ("CORR of runtime and communication time: %f\n",$c_exec_ft); + printf FILE ("CORR of heap alloc and communication time: %f\n",$c_ha_ft); + printf FILE ("CORR of local sparks and communication time: %f\n",$c_lsp_ft); + printf FILE ("CORR of global_sparks and communication time: %f\n",$c_gsp_ft); + close FILE; +} + +if ( $opt_P ) { + do percentify($line_no,*exec_class); + do percentify($line_no,*exec_global_class); + do percentify($line_no,*exec_local_class); + do percentify($line_no,*comm_class); + do percentify($line_no,*comm_global_class); + do percentify($line_no,*comm_local_class); + do percentify($line_no,*spark_local_class); + do percentify($line_no,*spark_global_class); + do percentify($line_no,*ha_class); + do percentify($line_no,*ft_class); +} + +# Produce cumulative RT graph and other (more or less) nice graphs +# ................................................................ + +do sort_and_cum(); + +# ---------------------------------------------------------------------------- + +open(IV,">INTERVALS") || die "Couldn't open file INTERVALS\n"; +do write_interval(IV, 'G', &guess_interval(@all_rts)); +do write_interval(IV, 'C', 0, int($mean_comm_perc), + int($mean_comm_perc+$std_dev_comm_perc), 50); +do write_interval(IV, 'S', &guess_interval(@all_sparks)); +do write_interval(IV, 'A', &guess_interval(@all_has)); +close(IV); + +# ---------------------------------------------------------------------------- +# Print results to STDOUT (mainly for testing) +# ---------------------------------------------------------------------------- + +if ( $opt_v ) { + do print_general_info(); +} + +# ---------------------------------------------------------------------------- +# Write results to data files to be processed by GNUPLOT +# ---------------------------------------------------------------------------- + +do write_data($gran_file_name, $OPEN_INT, $logscale{'g'}, $#exec_times+1, + @exec_times, @exec_class); + +do write_data($gran_global_file_name, $OPEN_INT, $logscale{'g'}, $#exec_times+1, + @exec_times, @exec_global_class); + +do write_data($gran_local_file_name, $OPEN_INT, $logscale{'g'}, $#exec_times+1, + @exec_times, @exec_local_class); + +do write_data($comm_file_name, $CLOSED_INT, $logscale{'c'}, $#comm_percs+1, + @comm_percs, @comm_class); + +do write_data($comm_global_file_name, $CLOSED_INT, $logscale{'c'}, $#comm_percs+1, + @comm_percs, @comm_global_class); + +do write_data($comm_local_file_name, $CLOSED_INT, $logscale{'c'}, $#comm_percs+1, + @comm_percs, @comm_local_class); + +do write_data($spark_file_name, $OPEN_INT, $logscale{'s'}, $#sparks+1, + @sparks, @spark_class); + +do write_data($spark_local_file_name, $OPEN_INT, $logscale{'s'}, $#sparks+1, + @sparks, @spark_local_class); + +do write_data($spark_global_file_name, $OPEN_INT, $logscale{'s'}, $#sparks+1, + @sparks, @spark_global_class); + +do write_data($ha_file_name, $OPEN_INT, $logscale{'a'}, $#has+1, + @has, @ha_class); + +do write_data($ft_file_name, $OPEN_INT, $logscale{'g'}, $#fetch_times+1, + @fetch_times, @fetch_class); + + +# ---------------------------------------------------------------------------- +# Run GNUPLOT over the data files and create figures +# ---------------------------------------------------------------------------- + +do gnu_plotify($gp_file_name); + +print "Script finished successfully!\n"; + +exit 0; + +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +# ---------------------------------------------------------------------------- +# Basic Operations on the intervals +# ---------------------------------------------------------------------------- + +sub get_index_open_int { + local ($value,@list) = @_; + local ($index,$right); + + # print "get_index: searching for index of" . $value; + # print " in " . join(':',@list); + + $index = 0; + $right = $list[$index]; + while ( ($value >= $right) && ($index < $#list) ) { + $index++; + $right = $list[$index]; + } + + return ( ($index == $#list) && ($value > $right) ) ? $index+1 : $index; +} + +# ---------------------------------------------------------------------------- + +sub get_index_closed_int { + local ($value,@list) = @_; + local ($index,$right); + + if ( ($value < $list[0]) || ($value > $list[$#list]) ) { + return ( -1 ); + } + + $index = 0; + $left = $list[$index]; + while ( ($left <= $value) && ($index < $#list) ) { + $index++; + $left = $list[$index]; + } + return ( $index-1 ); +} + +# ---------------------------------------------------------------------------- +# Write operations +# ---------------------------------------------------------------------------- + +sub write_data { + local ($file_name, $open_int, $logaxes, $n, @rest) = @_; + local (@times) = splice(@rest,0,$n); + local (@class) = @rest; + + open(GRAN,">$file_name") || die "Couldn't open file $file_name for output"; + + if ( $open_int == $OPEN_INT ) { + + for ($i=0, + $left = ( index($logaxes,"x") != -1 ? int($times[0]/2) : 0 ), + $right = 0; + $i < $n; + $i++, $left = $right) { + $right = $times[$i]; + print GRAN int(($left+$right)/2) . " " . + ($class[$i] eq "" ? "0" : $class[$i]) . "\n"; + } + print GRAN $times[$n-1]+(($times[$n-1]-$times[$n-2])/2) . " " . + ($class[$n] eq "" ? "0" : $class[$n]) . "\n"; + + } else { + + print GRAN ( (index($logaxes,"x") != -1) && ($times[0] == 0 ? int($times[1]/2) : ($times[$1] + $times[0])/2 ) . " " . $class[0] . "\n"); + for ($i=1; $i < $n-2; $i++) { + $left = $times[$i]; + $right = $times[$i+1]; + print(GRAN ($left+$right)/2 . " " . + ($class[$i] eq "" ? "0" : $class[$i]) . "\n"); + } + print GRAN ($times[$n-1]+$times[$n-2])/2 . " " . $class[$n-2] if $n >= 2; + } + + close(GRAN); +} + +# ---------------------------------------------------------------------------- + +sub write_array { + local ($file_name,$n,@list) = @_; + + open(FILE,">$file_name") || die "$file_name: $!"; + for ($i=0; $i<=$#list; $i++) { + print FILE $i . " " . ( $list[$i] eq "" ? "0" : $list[$i] ) . "\n"; + } + + if ( $opt_D ) { + print "write_array: (" . join(", ",1 .. $#list) . ")\n for file $file_name returns: \n (0, $#list, &list_max(@list)\n"; + } + + return ( (0, $#list, &list_max(@list), + "(" . join(", ",1 .. $#list) . ")\n") ); +} + +# ---------------------------------------------------------------------------- + +sub write_cumulative_data { + local ($file_name1,$file_name2,@list) = @_; + local (@ns, @elems, @xtics, $i, $j, $n, $elem, $max_clust, $xtics_str, + $xstart, $xend, $file_name0); + local ($CLUST_SZ) = $no_of_clusters; + + @ns = (); + @elems = (); + $file_name0 = $file_name1; + $file_name0 =~ s/\.dat$//; + $file_name0 .= "0.dat"; + open(CUMM,">$file_name1") || die "Couldn't open file $file_name1 (error $!)\n"; + open(CUMM0,">$file_name0") || die "Couldn't open file $file_name0 (error $!)\n"; + + print CUMM "1 0\n" unless $list[0] <= 1; + print CUMM0 "1 0\n" unless $list[0] <= 1;; + + for ($i=0; $i <= $#list; $i++) { + $elem = $list[$i]; + print CUMM ($elem) . " " . int( (100 * ($i)) / ($#list+1) ) . "\n" unless $elem == 0; + print CUMM0 ($elem) . " " . $i . "\n" unless $elem == 0;; + for ($n=1; $i < $#list && $list[$i+1] == $elem; $i++, $n++) { } + + print CUMM "$elem " . int( (100 * ($i+1)) / ($#list+1) ) . "\n"; + print CUMM0 "$elem " . ($i+1) . "\n"; + + + if ( $opt_D ) { + print "\n--> Insert: n: $n (elem $elem) in the above lists yields: \n "; + } + + # inlined version of do insert_elem($elem, $n, $#exs, @exs, @ns) + for ($j=0; $j<=$#ns && $ns[$j]>$n; $j++) { } + if ( $j > $#ns ) { + push(@ns,$n); + push(@elems,$elem); + } else { + splice(@ns,$j,0,$n); # insert $n at pos $j and move the + splice(@elems,$j,0,$elem); # rest of the array to the right + } + + if ( $opt_D ) { + print "[" . join(", ",@ns) . "]" . "\n and \n" . + "[" . join(", ",@elems) . "]\n"; + } + + } + + close(CUMM); + close(CUMM0); + + open(CLUSTERS_ALL,">" . (&dirname($file_name2)) . "CL-" . + &basename($file_name2)) + || die "Couldn't open file CL-$file_name2 (error $!)\n"; + for ($i=0; $i <= $#ns; $i++) { + print CLUSTERS_ALL "$elems[$i] $ns[$i]\n"; + } + close(CLUSTERS_ALL); + + # Interesting are only the first parts of the list (clusters!) + splice(@elems, $CLUST_SZ); + splice(@ns, $CLUST_SZ); + + open(CLUSTERS,">$file_name2") || die "Couldn't open file $file_name2 (error $!)\n"; + + $xstart = &list_min(@elems); + $xend = &list_max(@elems); + $step = ($xend - $xstart) / ( $CLUST_SZ == 1 ? 1 : ($CLUST_SZ-1)); + + @xtics = (); + for ($i=0, $x=$xstart; $i <= $#ns; $i++, $x+=$step) { + print CLUSTERS "$x $ns[$i]\n"; + push(@xtics,"\"$elems[$i]\" $x"); + } + close(CLUSTERS); + + $max_clust = $ns[0]; + $xtics_str = "(" . join(", ",@xtics) . ")\n"; + + return ( ($xstart, $xend, $max_clust, $xtics_str) ); +} + +# ---------------------------------------------------------------------------- + +sub get_xtics { + local ($open_int, @list) = @_; + + local ($str); + + if ( $open_int == $OPEN_INT ) { + $last = pop(@list); + $str = "( \">0\" 0"; + foreach $x (@list) { + $str .= ", \">$x\" $x"; + } + $str .= ", \"Large\" $last)\n"; + } else { + $left = shift(@list); + $right = shift(@list) if $#list >= 0; + $last = pop(@list) if $#list >= 0; + $str = "( \"$left-$right\" " . $left; + $left = $right; + foreach $right (@list) { + $str .= ", \"$left-$right\" " . ($left+$right)/2; + $left = $right; + } + $str .= ", \"$left-$last\" " . $last .")\n" unless $last eq ""; + } + return $str; +} + +# ---------------------------------------------------------------------------- + +sub print_line { + local ($start,$end,$is_global,$bbs,$ha,$rt,$bt,$bc,$ft,$fc,$my) = @_; + + printf("START: %u, END: %u ==> tot_exec: %u\n", + $start,$end,$end-$start); + printf(" BASIC_BLOCKS: %u, HEAP_ALLOCATIONS: %u \n",$bbs,$ha); + printf(" TOT_EXEC: %u = RUN_TIME %u + BLOCK_TIME %u + FETCH_TIME %u\n", + $end-$start,$rt,$bt,$ft); + printf(" BLOCK_TIME %u / BLOCK_COUNT %u; FETCH_TIME %u / FETCH_COUNT %u\n", + $bt,$bc,$ft,$fc); + printf(" %s %s\n", + $is_global eq 'T' ? "GLOBAL" : "LOCAL", + $my eq 'T' ? "MANDATORY" : "NOT MANDATORY"); +} + +# ---------------------------------------------------------------------------- + +sub gnu_plotify { + local ($gp_file_name) = @_; + + local (@open_xrange,@closed_xrang,@spark_xrange,@ha_xrange, @ft_range, + $exec_xtics,$comm_perc_xtics,$spark_xtics,$has_xtics, + $cumu0_rts_file, $cumu0_has_file, $cumu0_fts_file); + + $cumu0_rts_file = $cumulat_rts_file_name; + $cumu0_rts_file =~ s/\.dat$//; + $cumu0_rts_file .= "0.dat"; + + $cumu0_has_file = $cumulat_has_file_name; + $cumu0_has_file =~ s/\.dat$//; + $cumu0_has_file .= "0.dat"; + + $cumu0_fts_file = $cumulat_fts_file_name; + $cumu0_fts_file =~ s/\.dat$//; + $cumu0_fts_file .= "0.dat"; + + $cumu0_cps_file = $cumulat_cps_file_name; + $cumu0_cps_file =~ s/\.dat$//; + $cumu0_cps_file .= "0.dat"; + + @open_xrange = &range($OPEN_INT,$logscale{'g'},@exec_times); + @closed_xrange = &range($CLOSED_INT,$logscale{'c'},@comm_percs); + @spark_xrange = &range($OPEN_INT,$logscale{'s'},@sparks); + @ha_xrange = &range($OPEN_INT,$logscale{'a'},@has); + @ft_xrange = &range($OPEN_INT,$logscale{'f'},@fts); + + $exec_xtics = $opt_T ? &get_xtics($OPEN_INT,@exec_times) : "" ; + $comm_perc_xtics = $opt_T ? &get_xtics($CLOSED_INT,@comm_percs) : ""; + $spark_xtics = $opt_T ? &get_xtics($OPEN_INT,@sparks) : ""; + $has_xtics = $opt_T ? &get_xtics($OPEN_INT,@has) : ""; + $fts_xtics = $opt_T ? &get_xtics($OPEN_INT,@fts) : ""; + + open(GP_FILE,">$gp_file_name") || + die "Couldn't open gnuplot file $gp_file_name for output\n"; + + if ( $opt_m ) { + print GP_FILE "set term postscript \"Roman\" 20\n"; + } else { + print GP_FILE "set term postscript color \"Roman\" 20\n"; + } + + do write_gp_record(GP_FILE, + $gran_file_name, &dat2ps_name($gran_file_name), + "Granularity (pure exec. time)", $ylabel, $logscale{'g'}, + @open_xrange,$max_rt_class,$exec_xtics); + do write_gp_record(GP_FILE, + $gran_global_file_name, &dat2ps_name($gran_global_file_name), + "Granularity (pure exec. time) of exported threads", + $ylabel, $logscale{'g'}, + @open_xrange,$max_rt_global_class,$exec_xtics); + do write_gp_record(GP_FILE, + $gran_local_file_name, &dat2ps_name($gran_local_file_name), + "Granularity (pure exec. time) of not exported threads", + $ylabel,$logscale{'g'}, + @open_xrange,$max_rt_local_class,$exec_xtics); + + do write_gp_record(GP_FILE, + $comm_file_name, &dat2ps_name($comm_file_name), + "% of communication",$ylabel,$logscale{'c'}, + @closed_xrange,$max_comm_perc_class,$comm_perc_xtics); + do write_gp_record(GP_FILE, + $comm_global_file_name, &dat2ps_name($comm_global_file_name), + "% of communication of exported threads",$ylabel,$logscale{'c'}, + @closed_xrange,$max_comm_perc_global_class,$comm_perc_xtics); + do write_gp_record(GP_FILE, + $comm_local_file_name, &dat2ps_name($comm_local_file_name), + "% of communication of not exported threads",$ylabel,$logscale{'c'}, + @closed_xrange,$max_comm_perc_local_class,$comm_perc_xtics); + do write_gp_record(GP_FILE, + $ft_file_name, &dat2ps_name($ft_file_name), + "Communication time", $ylabel, $logscale{'g'}, + @open_xrange,$max_ft_class,$fts_xtics); + + + do write_gp_record(GP_FILE, + $spark_file_name, &dat2ps_name($spark_file_name), + "No. of sparks created", $ylabel, $logscale{'s'}, + @spark_xrange,$max_spark_class,$spark_xtics); + + do write_gp_record(GP_FILE, + $spark_local_file_name, &dat2ps_name($spark_local_file_name), + "No. of sparks created (parLocal)", $ylabel, $logscale{'s'}, + @spark_xrange,$max_spark_local_class,$spark_xtics); + + do write_gp_record(GP_FILE, + $spark_global_file_name, &dat2ps_name($spark_global_file_name), + "No. of sparks created (parGlobal)", $ylabel, $logscale{'s'}, + @spark_xrange,$max_spark_global_class,$spark_xtics); + + do write_gp_record(GP_FILE, + $ha_file_name, &dat2ps_name($ha_file_name), + "Heap Allocations (words)", $ylabel, $logscale{'a'}, + @ha_xrange,$max_ha_class,$has_xtics); + + do write_gp_lines_record(GP_FILE, + $cumulat_rts_file_name, &dat2ps_name($cumulat_rts_file_name), + "Cumulative pure exec. times","% of threads", + $logscale{'Cg'}, + $xend_cum_rts, $yend_cum_rts,""); + # $xtics_cluster_rts as last arg? + + do write_gp_lines_record(GP_FILE, + $cumulat_has_file_name, &dat2ps_name($cumulat_has_file_name), + "Cumulative heap allocations","% of threads", + $logscale{'Ca'}, + $xend_cum_has, $yend_cum_has,""); + # $xtics_cluster_has as last arg? + + do write_gp_lines_record(GP_FILE, + $cumu0_rts_file, &dat2ps_name($cumu0_rts_file), + "Cumulative pure exec. times","Number of threads", + $logscale{'Cg'}, + $xend_cum_rts, $yend_cum0_rts,""); + # $xtics_cluster_rts as last arg? + + do write_gp_lines_record(GP_FILE, + $cumu0_has_file, &dat2ps_name($cumu0_has_file), + "Cumulative heap allocations","Number of threads", + $logscale{'Ca'}, + $xend_cum_has, $yend_cum0_has,""); + # $xtics_cluster_has as last arg? + + do write_gp_lines_record(GP_FILE, + $cumulat_fts_file_name, &dat2ps_name($cumulat_fts_file_name), + "Cumulative communication times","% of threads", + $logscale{'Cg'}, + $xend_cum_fts, $yend_cum_fts,""); + # $xtics_cluster_rts as last arg? + + do write_gp_lines_record(GP_FILE, + $cumu0_fts_file, &dat2ps_name($cumu0_fts_file), + "Cumulative communication times","Number of threads", + $logscale{'Cg'}, + $xend_cum_fts, $yend_cum0_fts,""); + # $xtics_cluster_rts as last arg? + + do write_gp_lines_record(GP_FILE, + $cumulat_cps_file_name, &dat2ps_name($cumulat_cps_file_name), + "Cumulative communication percentages","% of threads", + "", # No logscale here ! + $xend_cum_cps, $yend_cum_cps,""); + # $xtics_cluster_rts as last arg? + + do write_gp_lines_record(GP_FILE, + $cumu0_cps_file, &dat2ps_name($cumu0_cps_file), + "Cumulative communication percentages","Number of threads", + "", # No logscale here ! + $xend_cum_cps, $yend_cum0_cps,""); + # $xtics_cluster_rts as last arg? + + do write_gp_record(GP_FILE, + $clust_rts_file_name, &dat2ps_name($clust_rts_file_name), + "Pure exec. time", "No. of threads", $logscale{'CG'}, + $xstart_cluster_rts,$xend_cluster_rts,$max_cluster_rts,$xtics_cluster_rts); + + do write_gp_record(GP_FILE, + $clust_has_file_name, &dat2ps_name($clust_has_file_name), + "Pure exec. time", "No. of threads", $logscale{'CA'}, + $xstart_cluster_has,$xend_cluster_has,$max_cluster_has,$xtics_cluster_has); + + do write_gp_record(GP_FILE, + $clust_fts_file_name, &dat2ps_name($clust_fts_file_name), + "Communication time", "No. of threads", $logscale{'CG'}, + $xstart_cluster_fts,$xend_cluster_fts,$max_cluster_fts,$xtics_cluster_rts); + + + do write_gp_simple_record(GP_FILE, + $pe_file_name, &dat2ps_name($pe_file_name), + "Processing Elements (PEs)", "Ready Time (not running)", + $logscale{'Yp'},$xstart_pe,$xend_pe,$max_pe,$xtics_pe); + + do write_gp_simple_record(GP_FILE, + $sn_file_name, &dat2ps_name($sn_file_name), + "Spark sites", "Pure exec. time", + $logscale{'Ys'},$xstart_sn,$xend_sn,$max_sn,$xtics_sn); + + close GP_FILE; + + print "Gnu plotting figures ...\n"; + system "gnuplot $gp_file_name"; + + print "Extending thickness of impulses ...\n"; + do gp_ext($gran_file_name, + $gran_global_file_name, + $gran_local_file_name, + $comm_file_name, + $comm_global_file_name, + $comm_local_file_name, + $spark_file_name, + $spark_local_file_name, + $spark_global_file_name, + $ha_file_name, + $ft_file_name, + $clust_fts_file_name, + $clust_rts_file_name, + $clust_has_file_name, + $pe_file_name, + $sn_file_name + ); + + +} + +# ---------------------------------------------------------------------------- + +sub gp_ext { + local (@file_names) = @_; + local ($file_name); + local ($ps_file_name); + local ($prg); + + #$prg = system "which gp-ext-imp"; + #print " Using script $prg for impuls extension\n"; + $prg = $ENV{GRANDIR} ? $ENV{GRANDIR} . "/bin/gp-ext-imp" + : $ENV{HOME} . "/bin/gp-ext-imp" ; + if ( $opt_v ) { + print " (using script $prg)\n"; + } + + foreach $file_name (@file_names) { + $ps_file_name = &dat2ps_name($file_name); + system "$prg -w $ext_size -g $gray " . + $ps_file_name . " " . + $ps_file_name . "2" ; + system "mv " . $ps_file_name . "2 " . $ps_file_name; + } +} + +# ---------------------------------------------------------------------------- + +sub write_gp_record { + local ($file,$in_file,$out_file,$xlabel,$ylabel,$logaxes, + $xstart,$xend,$ymax,$xtics) = @_; + + if ( $xstart >= $xend ) { + print ("WARNING: empty xrange [$xstart:$xend] changed to [$xstart:" . $xstart+1 . "]\n") if ( $pedantic || $opt_v ); + $xend = $xstart + 1; + } + + if ( $ymax <=0 ) { + $ymax = 2; + print "WARNING: empty yrange changed to [0:$ymax]\n" if ( $pedantic || $opt_v ); + } + + $str = "set size " . $xsize . "," . $ysize . "\n" . + "set xlabel \"" . $xlabel . "\"\n" . + "set ylabel \"" . $ylabel . "\"\n" . + ($xstart eq "" ? "" + : "set xrange [" . int($xstart) .":" . int($xend) . "]\n") . + ($ymax eq "" ? "" + : "set yrange [" . (index($logaxes,"y") != -1 ? 1 : 0) . + ":" . &list_max(2,int($ymax+$ymax/5)) . "]\n") . + ($xtics ne "" ? "set xtics $xtics" : "") . + "set tics out\n" . + "set border\n" . + "set title \"$nPEs PEs\"\n" . + "set nokey \n" . + "set nozeroaxis\n" . + "set format xy \"%g\"\n" . + (index($logaxes,"x") != -1 ? + "set logscale x\n" : + "set nologscale x\n") . + (index($logaxes,"y") != -1 ? + "set logscale y\n" : + "set nologscale y\n") . + "set output \"" . $out_file . "\"\n" . + "plot \"" . $in_file . "\" with impulses\n\n"; + print $file $str; +} + +# ---------------------------------------------------------------------------- + +sub write_gp_lines_record { + local ($file,$in_file,$out_file,$xlabel,$ylabel,$logaxes, + $xend,$yend,$xtics) = @_; + + local ($str); + + $str = "set xlabel \"" . $xlabel . "\"\n" . + "set ylabel \"" . $ylabel . "\"\n" . + "set xrange [" . ( index($logaxes,"x") != -1 ? 1 : 0 ) . ":$xend]\n" . + "set yrange [" . ( index($logaxes,"y") != -1 ? 1 : 0 ) . ":$yend]\n" . + "set border\n" . + "set nokey\n" . + ( $xtics ne "" ? "set xtics $xtics" : "" ) . + (index($logaxes,"x") != -1 ? + "set logscale x\n" : + "set nologscale x\n") . + (index($logaxes,"y") != -1 ? + "set logscale y\n" : + "set nologscale y\n") . + "set nozeroaxis\n" . + "set format xy \"%g\"\n" . + "set output \"" . $out_file . "\"\n" . + "plot \"" . $in_file . "\" with lines\n\n"; + print $file $str; +} + + +# ---------------------------------------------------------------------------- + +sub write_gp_simple_record { + local ($file,$in_file,$out_file,$xlabel,$ylabel,$logaxes, + $xstart,$xend,$ymax,$xtics) = @_; + + $str = "set size " . $xsize . "," . $ysize . "\n" . + "set xlabel \"" . $xlabel . "\"\n" . + "set ylabel \"" . $ylabel . "\"\n" . + ($xstart eq "" ? "" + : "set xrange [" . int($xstart) .":" . int($xend) . "]\n") . + ($ymax eq "" ? "" + : "set yrange [" . (index($logaxes,"y") != -1 ? 1 : 0) . + ":" . &list_max(2,int($ymax+$ymax/5)) . "]\n") . + ($xtics ne "" ? "set xtics $xtics" : "") . + "set border\n" . + "set nokey\n" . + "set tics out\n" . + "set nozeroaxis\n" . + "set format xy \"%g\"\n" . + (index($logaxes,"x") != -1 ? + "set logscale x\n" : + "set nologscale x\n") . + (index($logaxes,"y") != -1 ? + "set logscale y\n" : + "set nologscale y\n") . + "set output \"" . $out_file . "\"\n" . + "plot \"" . $in_file . "\" with impulses\n\n"; + print $file $str; +} + +# ---------------------------------------------------------------------------- + +sub dat2ps_name { + local ($dat_name) = @_; + + $dat_name =~ s/\.dat$/\.ps/; + return ($dat_name); +} + +# ---------------------------------------------------------------------------- + +sub range { + local ($open_int, $logaxes, @ints) = @_; + + local ($range, $left_margin, $right_margin); + + $range = $ints[$#ints]-$ints[0]; + $left_margin = 0; # $range/10; + $right_margin = 0; # $range/10; + + if ( $opt_D ) { + print "\n==> Range: logaxes are $logaxes i.e. " . + (index($logaxes,"x") != -1 ? "matches x axis\n" + : "DOESN'T match x axis\n"); + } + if ( index($logaxes,"x") != -1 ) { + if ( $open_int == $OPEN_INT ) { + return ( ($ints[0]/2-$left_margin, + $ints[$#ints]+($ints[$#ints]-$ints[$#ints-1])/2+$right_margin) ); + } else { + return ( ( &list_max(1,$ints[0]-$left_margin), + $ints[$#ints]+($ints[$#ints]-$ints[$#ints-1])/2+$right_margin) ); + } + } else { + if ( $open_int == $OPEN_INT ) { + return ( ($ints[0]/2-$left_margin, + $ints[$#ints]+($ints[$#ints]-$ints[$#ints-1])/2+$right_margin) ); + } else { + return ( ($ints[0]-$left_margin, + $ints[$#ints]+($ints[$#ints]-$ints[$#ints-1])/2+$right_margin) ); + } + } +} + +# ---------------------------------------------------------------------------- + +sub percentify { + local ($sum,*classes) = @_; + + for ($i=0; $i<=$#classes; $i++) { + $classes[$i] = (100 * $classes[$i]) / $sum; + } +} + +# ---------------------------------------------------------------------------- +# ToDo: get these statistics functions from "stat.pl" +# ---------------------------------------------------------------------------- + +sub mean_std_dev { + local ($sum,@list) = @_; + + local ($n, $s, $s_); + + #print "\nmean_std_dev: sum is $sum ; list has length $#list"; + + $n = $#list+1; + $mean_value = $sum/$n; + + $s_ = 0; + foreach $x (@list) { + $s_ += $x; + $s += ($mean_value - $x) ** 2; + } + if ( $sum != $s_ ) { + print "ERROR in mean_std_dev: provided sum is wrong " . + "(provided: $sum; computed: $s_)\n"; + print " list_sum: " . &list_sum(@list) . "\n"; + exit (2); + } + + return ( ($mean_value, sqrt($s / ($n - 1)) ) ); +} + +# ---------------------------------------------------------------------------- + +sub _mean_std_dev { + return ( &mean_std_dev(&list_sum(@_), @_) ); +} + +# ---------------------------------------------------------------------------- +# Compute covariance of 2 vectors, having their sums precomputed. +# Input: $n ... number of all elements in @list_1 as well as in @list_2 +# (i.e. $n = $#list_1+1 = $#list_2+1). +# $mean_1 ... mean value of all elements in @list_1 +# @list_1 ... list of integers; first vector +# $mean_2 ... mean value of all elements in @list_2 +# @list_2 ... list of integers; first vector +# Output: covariance of @list_1 and @list_2 +# ---------------------------------------------------------------------------- + +sub cov { + local ($n, $mean_1, @rest) = @_; + local (@list_1) = splice(@rest,0,$n); + local ($mean_2, @list_2) = @rest; + + local ($i,$s,$s_1,$s_2); + + for ($i=0; $i<$n; $i++) { + $s_1 += $list_1[$i]; + $s_2 += $list_2[$i]; + $s += ($mean_1 - $list_1[$i]) * ($mean_2 - $list_2[$i]); + } + if ( $mean_1 != ($s_1/$n) ) { + print "ERROR in cov: provided mean value is wrong " . + "(provided: $mean_1; computed: " . ($s_1/$n) . ")\n"; + exit (2); + } + if ( $mean_2 != ($s_2/$n) ) { + print "ERROR in cov: provided mean value is wrong " . + "(provided: $mean_2; computed: " . ($s_2/$n) . ")\n"; + exit (2); + } + return ( $s / ($n - 1) ) ; +} + +# ---------------------------------------------------------------------------- +# Compute correlation of 2 vectors, having their sums precomputed. +# Input: $n ... number of all elements in @list_1 as well as in @list_2 +# (i.e. $n = $#list_1+1 = $#list_2+1). +# $sum_1 ... sum of all elements in @list_1 +# @list_1 ... list of integers; first vector +# $sum_2 ... sum of all elements in @list_2 +# @list_2 ... list of integers; first vector +# Output: correlation of @list_1 and @list_2 +# ---------------------------------------------------------------------------- + +sub corr { + local ($n, $sum_1, @rest) = @_; + local (@list_1) = splice(@rest,0,$n); + local ($sum_2, @list_2) = @rest; + + local ($mean_1,$mean_2,$std_dev_1,$std_dev_2); + + if ( $opt_D ) { + print "\ncorr: n=$n sum_1=$sum_1 sum_2=$sum_2\n"; + print " list_sum of list_1=" . &list_sum(@list_1) . + " list_sum of list_2=" . &list_sum(@list_2) . "\n"; + print " len of list_1=$#list_1 len of list_2=$#list_2\n"; + } + + ($mean_1, $std_dev_1) = &mean_std_dev($sum_1,@list_1); + ($mean_2, $std_dev_2) = &mean_std_dev($sum_2,@list_2); + + if ( $opt_D ) { + print "corr: $mean_1, $std_dev_1; $mean_2, $std_dev_2\n"; + } + + return ( ($std_dev_1 * $std_dev_2) == 0 ? + 0 : + &cov($n, $mean_1, @list_1, $mean_2, @list_2) / + ( $std_dev_1 * $std_dev_2 ) ); +} + +# ---------------------------------------------------------------------------- + +sub list_sum { + local (@list) = @_; + + local ($sum); + + foreach $x (@list) { + $sum += $x; + } + + return ($sum); +} + +# ---------------------------------------------------------------------------- + +sub list_max { + local (@list) = @_; + + local ($max) = shift; + + foreach $x (@list) { + $max = $x if $x > $max; + } + + return ($max); +} + +# ---------------------------------------------------------------------------- + +sub list_min { + local (@list) = @_; + + local ($min) = shift; + + foreach $x (@list) { + $min = $x if $x < $min; + } + + return ($min); +} + +# ---------------------------------------------------------------------------- + +sub guess_interval { + local (@list) = @_ ; + + local ($min,$max,$sum,$mean,$std_dev,@intervals); + + $min = &list_min(@list); + $max = &list_max(@list); + $sum = &list_sum(@list); + ($mean, $std_dev) = &mean_std_dev($sum,@list); + + @intervals = (int($mean-$std_dev),int($mean-$std_dev/2),int($mean), + int($mean+$std_dev/2),int($mean+$std_dev)); + + while ($#intervals>=0 && $intervals[0]<0) { + shift(@intervals); + } + + return (@intervals); +} + +# ---------------------------------------------------------------------------- + +sub write_interval { + local ($file,$flag,@intervals) = @_; + + printf $file "$flag: (" . join(", ",@intervals) . ")\n"; +} + +# ---------------------------------------------------------------------------- + +sub read_template { + + if ( $opt_v ) { + print "Reading settings from template file $templ_file_name ...\n"; + } + + open(TEMPLATE,$templ_file_name) || die "Couldn't open file $templ_file_name"; + while (