SCM Repository
View of /branches/pure-cfg/src/compiler/high-to-mid/probe.sml
Parent Directory
|
Revision Log
Revision 640 -
(download)
(annotate)
Thu Mar 17 17:59:58 2011 UTC (10 years, 1 month ago) by jhr
File size: 9206 byte(s)
Thu Mar 17 17:59:58 2011 UTC (10 years, 1 month ago) by jhr
File size: 9206 byte(s)
Bug fix: flip order of components in coefficient vectors so that they match the order of the voxel vectors
(* probe.sml * * COPYRIGHT (c) 2010 The Diderot Project (http://diderot-language.cs.uchicago.edu) * All rights reserved. * * Expansion of probe operations in the HighIL to MidIL translation. *) structure Probe : sig val expand : { result : MidIL.var, (* result variable for probe *) img : MidIL.var, (* probe image argument *) v : ImageInfo.info, (* summary info about image *) h : Kernel.kernel, (* reconstruction kernel *) k : int, (* number of levels of differentiation *) pos : MidIL.var (* probe position argument *) } -> MidIL.assign list end = struct structure SrcIL = HighIL structure SrcOp = HighOps structure DstIL = MidIL structure DstTy = MidILTypes structure DstOp = MidOps structure DstV = DstIL.Var structure VMap = SrcIL.Var.Map structure IT = Shape (* generate a new variable indexed by dimension *) fun newVar_dim (prefix, d, ty) = DstV.new (prefix ^ Partials.axisToString(Partials.axis d), ty) fun assign (x, rator, args) = (x, DstIL.OP(rator, args)) fun cons (x, args) = (x, DstIL.CONS args) fun realLit (x, i) = (x, DstIL.LIT(Literal.Float(FloatLit.fromInt i))) fun intLit (x, i) = (x, DstIL.LIT(Literal.Int(IntInf.fromInt i))) (* generate code for a evaluating a single element of a probe operation *) fun probeElem { dim, (* dimension of space *) h, s, (* kernel h with support s *) n, f, (* Dst vars for integer and fractional components of position *) voxIter (* iterator over voxels *) } (result, pdOp) = let val vecsTy = DstTy.VecTy(2*s) (* vectors of coefficients cover support of kernel *) val vecDimTy = DstTy.VecTy dim (* generate the variables that hold the convolution coefficients. The * resulting list is in slowest-to-fastest axes order. *) val convCoeffs = let val Partials.D l = pdOp fun mkVar (_, [], coeffs) = coeffs | mkVar (i, d::dd, coeffs) = (case d of 0 => mkVar(i+1, dd, newVar_dim("h", i, vecsTy) :: coeffs) | 1 => mkVar(i+1, dd, newVar_dim("dh", i, vecsTy) :: coeffs) | _ => mkVar(i+1, dd, newVar_dim(concat["d", Int.toString d, "h"], i, vecsTy) :: coeffs) (* end case *)) in mkVar (0, l, []) end val _ = print(concat["probeElem: ", Partials.partialToString pdOp, " in ", Int.toString(List.length convCoeffs), "D space\n"]) (* for each dimension in space, we evaluate the kernel at the coordinates for that axis. * the coefficients are * h_{s-i} (f - i) for 1-s <= i <= s *) val coeffCode = let fun gen (x, k, (d, code)) = let val fd = newVar_dim ("f", d, DstTy.realTy) val a = DstV.new ("a", vecsTy) (* note that we reverse the order of the list since the convolution * space is flipped from the image space and we want the voxel vector * to be in increasing address order. *) val tmps = List.rev(List.tabulate(2*s, fn i => (DstV.new("t"^Int.toString i, DstTy.realTy), i - s))) fun mkArg ((t, 0), code) = (t, DstIL.VAR fd) :: code | mkArg ((t, n), code) = let val (rator, n) = if (n < 0) then (DstOp.Sub, ~n) else (DstOp.Add, n) val t' = DstV.new ("r", DstTy.realTy) in realLit (t', n) :: assign (t, rator DstTy.realTy, [fd, t']) :: code end val code = cons(a, List.map #1 tmps) :: assign(x, DstOp.EvalKernel(2*s, h, k), [a]) :: code val code = assign(fd, DstOp.Select(DstTy.VecTy dim, d), [f]) :: List.foldr mkArg code tmps in (d+1, code) end val Partials.D l = pdOp in (* we iterate from fastest to slowest axis *) #2 (ListPair.foldr gen (0, []) (convCoeffs, l)) end (* generate the reduction code *) fun genReduce (result, [hh], IT.LF{vox, offsets}, code) = assign (result, DstOp.Dot(2*s), [vox, hh]) :: code | genReduce (result, hh::r, IT.ND(_, kids), code) = let val tv = DstV.new ("tv", vecsTy) val tmps = List.tabulate(2*s, fn i => DstV.new("t"^Int.toString i, DstTy.realTy)) fun lp ([], [], code) = code | lp (t::ts, kid::kids, code) = genReduce(t, r, kid, lp(ts, kids, code)) val code = cons(tv, tmps) :: assign(result, DstOp.Dot(2*s), [hh, tv]) :: code in lp (tmps, kids, code) end | genReduce _ = raise Fail "genReduce" val reduceCode = genReduce (result, convCoeffs, voxIter, []) in coeffCode @ reduceCode end (* generate code for probing the field (D^k (v * h)) at pos *) fun expand {result, img, v, h, k, pos} = let (* FIXME: only scalar images are supported! *) val ImageInfo.ImgInfo{dim, ty=([], rTy), ...} = v val s = Kernel.support h val vecsTy = DstTy.VecTy(2*s) (* vectors of coefficients cover support of kernel *) val vecDimTy = DstTy.VecTy dim (* generate the transform code *) val x = DstV.new ("x", vecDimTy) (* image-space position *) val f = DstV.new ("f", vecDimTy) val nd = DstV.new ("nd", vecDimTy) val n = DstV.new ("n", DstTy.IVecTy dim) val transformCode = [ assign(x, DstOp.PosToImgSpace v, [img, pos]), assign(nd, DstOp.Floor dim, [x]), assign(f, DstOp.Sub vecDimTy, [x, nd]), assign(n, DstOp.RealToInt dim, [nd]) ] (* generate the shape of the differentiation tensor with variables representing * the elements *) val diffIter = let val partial = Partials.partial dim fun f (i, axes) = Partials.axis i :: axes fun g axes = let val r = DstV.new( String.concat("r" :: List.map Partials.axisToString axes), DstTy.realTy) in (r, partial axes) end in IT.create (k, dim, fn _ => (), f, g, []) end val _ = let val indentWid = ref 2 fun inc () = (indentWid := !indentWid + 2) fun dec () = (indentWid := !indentWid - 2) fun indent () = print(CharVector.tabulate(!indentWid, fn _ => #" ")) fun nd () = (indent(); print "ND\n"); fun lf (x, partial) = ( indent(); print(concat["LF(", DstV.toString x, ", ", Partials.partialToString partial, ")\n"])) fun pr (Shape.ND(attr, kids)) = (nd attr; inc(); List.app pr kids; dec()) | pr (Shape.LF attr) = lf attr in print "diffIter:\n"; pr diffIter end (* generate code to load the voxel data; since we use a vector load operation to load the * fastest dimension, the height of the tree is one less than the dimension of space. *) val voxIter = let fun f (i, (offsets, id)) = (i - (s - 1) :: offsets, i::id) fun g (offsets, id) = { offsets = ~(s-1) :: offsets, vox = DstV.new(String.concat("v" :: List.map Int.toString id), vecsTy) } in IT.create (dim-1, 2*s, fn _ => (), f, g, ([], [])) end val _ = let val indentWid = ref 2 fun inc () = (indentWid := !indentWid + 2) fun dec () = (indentWid := !indentWid - 2) fun indent () = print(CharVector.tabulate(!indentWid, fn _ => #" ")) fun nd () = (indent(); print "ND\n"); fun lf {offsets, vox} = ( indent(); print "LF{offsets = ["; print(String.concatWith "," (List.map Int.toString offsets)); print "], vox = "; print(DstV.toString vox); print "}\n") fun pr (Shape.ND(attr, kids)) = (nd attr; inc(); List.app pr kids; dec()) | pr (Shape.LF attr) = lf attr in print "voxIter:\n"; pr voxIter end val loadCode = let fun genCode ({offsets, vox}, code) = let fun computeIndices (_, []) = ([], []) | computeIndices (i, offset::offsets) = let val index = newVar_dim("i", i, DstTy.intTy) val t1 = DstV.new ("t1", DstTy.intTy) val t2 = DstV.new ("t2", DstTy.intTy) val (indices, code) = computeIndices (i+1, offsets) val code = intLit(t1, offset) :: assign(t2, DstOp.Select(DstTy.IVecTy dim, i), [n]) :: assign(index, DstOp.Add(DstTy.intTy), [t1, t2]) :: code val indices = index::indices in (indices, code) end val (indices, indicesCode) = computeIndices (0, offsets) val a = DstV.new ("a", DstTy.AddrTy v) in indicesCode @ [ assign(a, DstOp.VoxelAddress v, img::indices), assign(vox, DstOp.LoadVoxels(v, 2*s), [a]) ] @ code end in IT.foldr genCode [] voxIter end (* generate code to evaluate and construct the result tensor *) val probeElem = probeElem {dim = dim, h = h, s = s, n = n, f = f, voxIter = voxIter} fun genProbe (result, IT.ND(_, kids as (IT.LF _)::_), code) = let (* the kids will all be leaves *) fun genProbeCode (IT.LF arg, code) = probeElem arg @ code fun getProbeVar (IT.LF(t, _)) = t in List.foldr genProbeCode (cons (result, List.map getProbeVar kids) :: code) kids end | genProbe (result, IT.ND(_, kids), code) = let val tmps = List.tabulate(dim, fn i => DstV.new("t"^Int.toString i, DstTy.realTy)) val code = cons(result, tmps) :: code fun lp ([], [], code) = code | lp (t::ts, kid::kids, code) = genProbe(t, kid, lp(ts, kids, code)) in lp (tmps, kids, code) end | genProbe (result, IT.LF(t, pdOp), code) = (* for scalar fields *) probeElem (result, pdOp) @ code val probeCode = genProbe (result, diffIter, []) in (* FIXME: for dim > 1 and k > 1, we need to transform the result back into world space *) transformCode @ loadCode @ probeCode end end
root@smlnj-gforge.cs.uchicago.edu | ViewVC Help |
Powered by ViewVC 1.0.0 |