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

SCM Repository

[diderot] View of /branches/vis12-cl/src/compiler/cl-target/gen-output.sml
ViewVC logotype

View of /branches/vis12-cl/src/compiler/cl-target/gen-output.sml

Parent Directory Parent Directory | Revision Log Revision Log

Revision 2648 - (download) (annotate)
Thu May 29 18:22:21 2014 UTC (6 years, 5 months ago) by jhr
File size: 5475 byte(s)
  Working on OpenCL support
(* gen-output.sml
 * COPYRIGHT (c) 2014 The Diderot Project (http://diderot-language.cs.uchicago.edu)
 * All rights reserved.
 * Generate strand output functions for the OpenCL target.  The output formats always have
 * a single axis for the data elements followed by one, or more, axes for the output structure.
 * There are two cases that we handle:
 *	grid, fixed-size elements:
 *		nrrd has object axis followed by grid axes
 *	collection, fixed-size elements
 *		nrrd has object axis followed by a single axis
 * NOTE: the C target also supports dynamic-sized elements (i.e., dynamic sequences), but the
 * OpenCL target does not support these yet.
 * The object axis kind depends on the output type, but it will either be one of the tensor types
 * that Teem knows about or else nrrdKindList.  In any case, the data elements are written as a
 * flat vector following the in-memory layout.  The other axes in the file will have nrrdKindSpace
 * as their kind.
 * TODO: some of this code is common with c-target/gen-output.sml (e.g., writing outputs to
 * files), so we should refactor it.
 * TODO: for sequences of tensors (e.g., tensor[3]{2}), we should use a separate axis for the
 * sequence dimension with kind nrrdKindList.

structure GenOutput : sig

  (* gen (props, nAxes) outputs
   *	returns code for getting the output/snapshot nrrds from the program state.
   *    The arguments are:
   *	    props	- the target information
   *	    nAxes	- the number of axes in the grid of strands (NONE for a collection)
   *	    outputs	- the list of output state variables paired with their TreeIL types
   *    The return value is a record {kernels, getFns}, where
   *	    kernels	- list of OpenCL kernels used to get output variables
   *	    getFns	- list of function declarations that implement the public
   *			  output and snapshot queries.
    val gen : Properties.props * int option -> (TreeIL.Ty.ty * string) list -> {
	    kernels : CLang.decl list,
	    getFns : CLang.decl list

  end = struct

    structure IL = TreeIL
    structure V = IL.Var
    structure Ty = IL.Ty
    structure CL = CLang
    structure N = CNames
    structure Nrrd = NrrdEnums
    structure U = CLUtil
    fun gen (tgt : Properties.props, nAxes) = let
	  fun getFn snapshot (ty, name) = let
		val funcName = if snapshot
		      then N.snapshotGet(tgt, name)
		      else N.outputGet(tgt, name)
		fun mkFunc (params, body) =
		      CL.D_Func([], CL.boolTy, funcName, CL.PARAM([], wrldPtr tgt, "wrld")::params, body)
		  case ty
		   of Ty.DynSeqTy ty' => raise Fail "dynamic sequences not supported for OpenCL"
		    | _ => mkFunc (genFixedOutput(tgt, snapshot, nAxes, ty, name))
		  (* end case *)
	  fun gen' outputs = let
		val getFns = List.map (getFn false) outputs
		  if (#exec tgt)
		    then getFns @ genOutput(tgt, outputs)
		  else if (#snapshot tgt)
		    then List.map (getFn true) outputs @ getFns
		    else getFns

    fun mapi f l = let
	  fun mapf (i, [], l) = List.rev l
	    | mapf (i, x::xs, l) = mapf (i+1, xs, f(i, x)::l)
	    mapf (0, l, [])

    val nrrdPtrTy = CL.T_Ptr(CL.T_Named "Nrrd")
    val filePtrTy = CL.T_Ptr(CL.T_Named "FILE")
    val sizeTy = CL.T_Named "size_t"
    fun wrldPtr tgt = CL.T_Ptr(CL.T_Named(N.worldTy tgt))
    fun mkInt i = CL.mkInt(IntInf.fromInt i)

  (* return information about the output type.  This is a tuple
   *    (c-type, nrrd-type, nrrd-axis-kind, # elements)
    fun infoOf (tgt : Properties.props, ty) = (case ty
           of Ty.IntTy => if #longint tgt
		then (CL.int64, Nrrd.TypeLLong, Nrrd.KindScalar, 1)
		else (CL.int32, Nrrd.TypeInt, Nrrd.KindScalar, 1)
            | Ty.TensorTy [] => if #double tgt
		then (CL.double, Nrrd.TypeDouble, Nrrd.KindScalar, 1)
		else (CL.float, Nrrd.TypeFloat, Nrrd.KindScalar, 1)
            | Ty.TensorTy dims => let
                val (axisKind, nElems) = (case dims
                       of [2] => (Nrrd.Kind2Vector, 2)
                        | [3] => (Nrrd.Kind3Vector, 3)
                        | [4] => (Nrrd.Kind4Vector, 4)
                        | [2,2] => (Nrrd.Kind2DMatrix, 4)
                        | [3,3] => (Nrrd.Kind3DMatrix, 9)
                        | _ => (Nrrd.KindList, List.foldl Int.* 1 dims)
                      (* end case *))
                  if #double tgt
                    then (CL.double, Nrrd.TypeDouble, axisKind, nElems)
                    else (CL.float, Nrrd.TypeFloat, axisKind, nElems)
            | Ty.SeqTy(ty, n) => raise Fail "FIXME" (*let
		val (elemTy, nrrdTy, dims) = infoOf (tgt, ty)
		  (elemTy, nrrdTy, n::dims)
            | _ => raise Fail(concat["GetOutput.infoOf(", Ty.toString ty, ")"])
	  (* end case *))

  (* variables in the generated code *)
    val wrldV = CL.mkVar "wrld"
    val sizesV = CL.mkVar "sizes"

  (* create a kernel for copying the given output state variable to the output
   * buffer.
(* NOTES: if the output is a grid, then we want to use the grid indices as a guide for processing
 * the output.  Otherwise, the order does not matter, but we do need to worry about synchronizing
 * writes to the output buffer.
    fun mkCopyKernel (tgt, snapshot, ty, name) = let
	      [U.globalParam(wrldPtr tgt, "wrld"), U.globalParam(CL.T_Ptr ty, "outBuf")],


ViewVC Help
Powered by ViewVC 1.0.0