Changes between Version 7 and Version 8 of DataParallel/Vectorisation/TypeVectorisation


Ignore:
Timestamp:
May 29, 2007 8:22:36 AM (8 years ago)
Author:
chak
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • DataParallel/Vectorisation/TypeVectorisation

    v7 v8  
    11== Type Vectorisation == 
    22 
    3 The transformation of types includes both closure conversion and the pairing of scalar with lifted computations. 
     3The transformation of types includes the generation of lifted types, the pairing of scalar with lifted computations, and closure conversion. 
    44 
    55=== Unboxed types === 
    66 
    7 Unboxed types and functions defined in `GHC.Prim` need to be treated specially during vectorisation.  This is as we cannot have `PA` instances for unboxed types and the transformation needs to know which functions from `GHC.Prim` can be safely parallelised (e.g., its fine to run many `+#` in parallel, whereas this is not really advisable for calls to side-effecting RTS functions).  Indeed, we might regard unboxed types and functions from `GHC.Prim` as the place where we make the transition from implementing vectorisation decisions in package ndp to hard-coding them into the compiler.  It is probably a good idea to eventually move as much as possible of the hardcoded information into `primops.txt.pp`, but for the moment, we simply hardcode everything in the modules in `vectorise/`. 
     7Unboxed types and functions defined in `GHC.Prim` need to be treated specially during vectorisation.  This is as we cannot have `PA` instances for unboxed types and the transformation needs to know which functions from `GHC.Prim` can be safely parallelised (e.g., its fine to run many `(+#)` in parallel, whereas this is not really advisable for calls to side-effecting RTS functions).  Indeed, we might regard unboxed types and functions from `GHC.Prim` as the place where we make the transition from implementing vectorisation decisions in package ndp to hard-coding them into the compiler.  It is probably a good idea to eventually move as much as possible of the hardcoded information into `primops.txt.pp`, but for the moment, we simply hardcode everything in the modules in `vectorise/`. 
    88 
    9 To treat unboxed type properly, we cannot simply use the type constructor `PArr` wherever we need a flattened array; instead, we define a type translation 
    10 {{{ 
    11 Int#^    = UArr Int 
    12 Float#^  = UArr Float 
    13 Double#^ = UArr Double 
    14 <and so on for other unboxed types> 
    15 t^       = PArr t* 
    16 }}} 
     9To treat unboxed types properly, we cannot simply use the type constructor `PArr` wherever we need a flattened array; instead, we define a type translation `t^` that treats unboxed types specially; e.g., `Int#^ = UArr Int`. 
    1710 
    1811We need to represent functions whose argument and/or result type are unboxed different from functions over boxed types.  The reason is the non-standard kinding rule implemented in GHC for `(->)`, which allows that the two argument type variables are instantiated to unboxed values iff the application of `(->)` is saturated.  We can't defined a second type constructor with that property unless we extend the `TypeRep.Type` representation.  We also can't simply use a type synonym for a vectorised type function constructor, because we must be able to partially apply it. 
    1912 
    20 === Transformation rules === 
     13 
     14=== Vectorisation === 
    2115 
    2216TODO: 
    23  * Be careful that `VFun (t1* -> t2*)` and `t1* -> t2*` includes `PArr t1` and `PArr t2*`; so, we can only use them if we have `PA` instances for these types. 
     17 * Types `t1* :-> t2*` and `t1* :=> t2*` include `PArr t1*` and `PArr t2*`; so, we can only use them if we have `PA` instances for these types. 
    2418 
    2519The type transformation rules achieve two goals: (1) they replace original type constructors and variables by their vectorised variants, where those are available, and (2) they alter the representation of functions: 
     
    2721T*                   = T_V  , if T_V exists 
    2822                     = T    , otherwise 
    29 a*                   = a_v 
     23a*                   = a 
    3024(t1 -> t2)* 
    3125 | isUbxFun (t1->t2) = (t1* -> t2*) :|| (t1^ -> t2^) 
    3226 | otherwise         = t1* :-> t2* 
    3327(t1 t2)*             = t1* t2* 
    34 (forall a.t)*        = forall a_v.t* 
     28(forall a.t)*        = forall a.t* 
    3529}}} 
    36 We need to distinguish between saturated function space applications involving unboxed types and those that don't, as we need to remain to be compatible with `(->_v) = (:->)`. 
     30When encountering saturated function space applications , we need to distinguish those that involve unboxed types, as we need to remain to be compatible with `(->_v) = (:->)` for boxed types.  (In other words, the distinction cannot simply be based on whether an application is saturated or not, it really needs to be one the basis of the kinds of types involved.) 
     31 
     32==== Fixed data constructor mapping ==== 
     33 
     34{{{ 
     35(->_v) = (:->) 
     36[::]_v = PArr 
     37}}} 
    3738 
    3839 
     40=== Lifting === 
    3941 
     42The lifting of types into vector space is, for all boxed monotypes, denoted by the array family constructor `PArr`.  However, need to handle the lifting of unboxed types and the extension of signatures with `PA` dictionaries explicitly: 
    4043{{{ 
    41 --- OLD 
    42 T*            = T_V , if T_V exists 
    43               = T    , otherwise 
    44 a*            = a_v 
    45 (t1 -> t2)*   = (  t1*  -> t2*,   , if kindOf t1 == # 
    46                  [:t1*  -> t2*:])   or kindOf t2 == # 
    47               = (  t1* :-> t2*,   , otherwise 
    48                  [:t1* :-> t2*:]) 
    49 (t1 t2)*      = t1* t2* 
    50 (forall a.t)* = forall a_v.t* 
     44Int#^                 = UArr Int 
     45Float#^               = UArr Float 
     46Double#^              = UArr Double 
     47..and so on for other unboxed types.. 
     48 
     49(forall a.t)^         = forall a. PA a -> t^ 
     50t^                    = PArr t* 
    5151}}} 
     52As a consequence, we cannot have impredicative instantiations of `[::]`, but this doesn't seem to be a significant restriction. 
     53 
     54 
     55=== `PArr` family instances === 
     56 
     57Remember that `PArr` is defined over vectorised types: 
     58{{{ 
     59newtype instance PArr (f :|| (arr -> brr)) 
     60  = PArrUFun (f :|| (ACls arr brr)) 
     61newtype instance PArr (a :-> b) = PArrFun (a :=> b) 
     62}}}