Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] View of /benchmarks/analysis/speedup.sml
ViewVC logotype

View of /benchmarks/analysis/speedup.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3349 - (download) (annotate)
Tue Oct 27 15:16:36 2015 UTC (5 years, 1 month ago) by jhr
File size: 6390 byte(s)
making copyrights consistent for all code in the repository
(* speedup.sml
 *
 * This code is part of the Diderot Project (http://diderot-language.cs.uchicago.edu)
 *
 * COPYRIGHT (c) 2015 The University of Chicago
 * All rights reserved.
 *
 * Code to generate a speedup plot for the pthread parallel implementation.
 *)

structure Speedup (*: sig

    val gen : {
	  (* data set to plot *)
	    data : Benchmark.data,
	  (* specification of benchmarks to plot, along with their styling info *)
	    bmarks : {
		name : string,
		symbol : string,
		line : string
	      } list,
	  (* baseline benchmark: should be "teem", "seq", "par-1" (for 1-processor) *)
	    baseline : string,
	  (* output file *)
	    output : string,
	  (* should the perfect speedup line be drawn? *)
	    perfect : bool
	  } -> OS.Process.status

  end*) = struct

    structure B = Benchmark
    structure P = Ploticus
    structure F = Format
    structure A2 = Array2

    fun pr (outS, s) = TextIO.output(outS, s)
    fun prl (outS, items) = List.app (fn s => pr(outS, s)) items
    fun prf (outS, fmt, items) = pr(outS, Format.format fmt items)

  (* location of lower-left corner *)
    val llX = 1.0
    val llY = 1.0
(*
    val plotWid = 6.0
    val plotHt  = 6.0
    fun dimensions (nProcs, maxY) = let
	  val np = real nProcs
	  val h = Real.max (np, realCeil maxY)
	  val w = np+1.0
	  in
	  end
*)

  (* extract the data from a benchmark *)
    fun extractData (baseline, b : B.benchmark) = let
	  fun isPar (r : B.results) = if String.isPrefix "par-" (#name r)
		then SOME(valOf(Int.fromString(String.extract(#name r, 4, NONE))), valOf(#avg_time r))
		else NONE
	  val data = List.mapPartial isPar (#results b)
	  in
	    case List.find (fn r => (baseline = #name r)) (#results b)
	     of SOME r => (valOf(#avg_time r), data)
	      | NONE => raise Fail "no baseline data"
	    (* end case *)
	  end

    type bmark_info = {
	col : int,
	name : string,
	symbol : string,
	line : string,
	data : B.benchmark
      }

    fun computeSpeedup (baseline, data : bmark_info list) = let
	(* determine the minimum max_nprocs value of the data *)
	  val maxNProcs = List.foldl (fn ({data, ...}, n) => Int.min(n, #max_nprocs data)) 256 data
	(* allocate the data table *)
	  val tbl = A2.array (maxNProcs, List.length data, 0.0)
	(* process a benchmark *)
	  fun doBenchmark ({col, data, ...} : bmark_info) = let
	      (* get performance data *)
		val (baseAvg, avgTimes) = extractData (baseline, data)
		fun update (i, t) = A2.update(tbl, i-1, col, baseAvg / t)
		in
		  List.app update avgTimes
		end
	  in
	    List.app doBenchmark data;
	    tbl
	  end

    fun genData (outS, tbl) = let
	  val lastCol = A2.nCols tbl - 1
	  fun output (r, c, v) = (
		if (c > 0)
		  then prf(outS, " %5.2f", [F.REAL v])
		  else prf(outS, "  %2d %5.2f", [F.INT(r+1), F.REAL v]);
		if (c = lastCol)
		  then pr (outS, "\n")
		  else ())
	  in
	    pr (outS, "// speedup data\n");
	    pr (outS, "//\n");
	    pr (outS, "#proc getdata\n");
	    pr (outS, "data:\n");
	    A2.appi A2.RowMajor output {base=tbl, col=0, row=0, ncols=NONE, nrows=NONE};
	    pr (outS, "\n")
	  end

    fun genAreaDef (outS, nprocs) = (
	  pr  (outS, "#proc areadef\n");
	  prf (outS, "  rectangle: %5.2f %5.2f 5.0 5.5\n", [F.REAL llX, F.REAL llY]);
	  prf (outS, "  xrange: 0.5 %d.5\n", [F.INT nprocs]);
	  prf (outS, "  yrange: 0 %d\n\n", [F.INT nprocs]))

    fun genAxis (outS, axis, label, stubInc, stubMin, stubMax, location) = (
	  prf (outS, "#proc %s\n", [F.STR axis]);
	  prf (outS, "  label: %s\n", [F.STR label]);
	  prf (outS, "  stubs: inc %d\n", [F.INT stubInc]);
	  prf (outS, "  stubrange: %d %d\n", [F.INT stubMin, F.INT stubMax]);
	  prf (outS, "  location: %5.2f\n\n", [F.REAL location]))

    fun genLinePlot (outS, xcol, ycol, symbol, line, label, sample) = let
	  fun prOpt (_, "") = ()
	    | prOpt (cmd, opts) = prf(outS, "  %s: %s\n", [F.STR cmd, F.STR opts])
	  in
	    pr  (outS, "#proc lineplot\n");
	    prf (outS, "  xfield: %d\n", [F.INT xcol]);
	    prf (outS, "  yfield: %d\n", [F.INT ycol]);
	    prOpt ("pointsymbol", symbol);
	    prOpt ("linedetails", line);
	    prOpt ("legendlabel", label);
	    prOpt ("legendsampletype", sample);
	    pr  (outS, "\n")
	  end

    fun genBmarkPlot outS (info : bmark_info) =
	  genLinePlot (outS, 1, #col info + 2, #symbol info, #line info, #name info, "line+symbol")

    fun genLegend (outS, x, y, title) = (
	  pr  (outS, "#proc legend\n");
	  prf (outS, "  location: %5.2f %5.2f\n", [F.REAL x, F.REAL y]);
	  pr  (outS, "  nlinesym: 1\n");
	  pr  (outS, "  frame: yes\n");
	  pr  (outS, "  textdetails: align=left size=10\n");
	  if (title <> "")
	    then (
	      prf (outS, "  title: %s\n", [F.STR title]);
	      pr  (outS, "  titledetails: style=b align=left size=12\n\n"))
	    else pr (outS, "\n"))

    fun gen {data=[], ...} = raise Fail "no data"
      | gen {data : B.data, bmarks, baseline, output, perfect} = let
	  val {host, version, date, ...} = hd data
	(* for each benchmark in the plot, find the data and pair it with the plotting
	 * info.
	 *)
	  val data = let
		fun find (b as {name, symbol, line}) = (
		      case List.find (fn {bmark, ...} => (bmark = name)) data
		       of NONE => raise Fail("no data for "^name)
			| SOME data => (b, data)
		      (* end case *))
		in
		  List.map find bmarks
		end
	(* assign columns in the data table to the benchmarks.  These are 0-based, but the
	 * actual first column is field 2 for Ploticus.
	 *)
	  val data = let
		fun lp (_, []) = []
		  | lp (i, ({name, symbol, line}, data)::r) = let
		      val r = lp (i+1, r)
		      in
			{col = i, name = name, symbol = symbol, line = line, data = data} :: r
		      end
		in
		  lp (0, data)
		end
	(* fill in the data table *)
	  val tbl = computeSpeedup (baseline, data)
	  val args = P.output output @ P.toEPS @ P.timesRoman 10
	  val nProcs = A2.nRows tbl
	(* generate the plot description to an output stream *)
	  fun plot outS = (
		genData (outS, tbl);
		genAreaDef (outS, nProcs);
		genAxis (outS, "xaxis", "Number of threads", 1, 1, nProcs, llY);
		genAxis (outS, "yaxis", "Speedup", 1, 0, nProcs, llX);
		if perfect
		  then genLinePlot (outS, 1, 1, "", "style=1 color=red", "perfect speedup", "")
		  else ();
		List.app (genBmarkPlot outS) data;
		genLegend (outS, 2.0, 6.5, concat["Parallel speedup on ", host, "[", date, "]"]))
	  in
plot(TextIO.stdOut);
	    P.run args plot
	  end

  end

		

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0