module Futhark.AD.Rev.Acc
( diffWithAcc,
diffUpdateAcc,
)
where
import Control.Monad
import Control.Monad.Identity
import Data.List ((\\))
import Data.Maybe (isJust)
import Futhark.AD.Rev.Monad
import Futhark.AD.Shared (accAddLambda)
import Futhark.Builder
import Futhark.IR.SOACS
import Futhark.Tools
import Futhark.Transform.Rename
import Futhark.Util (chunks, takeLast)
zeroOutUpdates :: [(VName, [SubExp])] -> Lambda SOACS -> Lambda SOACS
zeroOutUpdates :: [(VName, [SubExp])] -> Lambda SOACS -> Lambda SOACS
zeroOutUpdates [(VName, [SubExp])]
certs_to_zeroes Lambda SOACS
lam = Lambda SOACS
lam {lambdaBody = onBody $ lambdaBody lam}
where
onExp :: Exp SOACS -> Exp SOACS
onExp = Identity (Exp SOACS) -> Exp SOACS
forall a. Identity a -> a
runIdentity (Identity (Exp SOACS) -> Exp SOACS)
-> (Exp SOACS -> Identity (Exp SOACS)) -> Exp SOACS -> Exp SOACS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mapper SOACS SOACS Identity -> Exp SOACS -> Identity (Exp SOACS)
forall (m :: * -> *) frep trep.
Monad m =>
Mapper frep trep m -> Exp frep -> m (Exp trep)
mapExpM Mapper SOACS SOACS Identity
mapper
where
mapper :: Mapper SOACS SOACS Identity
mapper =
(Mapper SOACS SOACS m
forall rep (m :: * -> *). Monad m => Mapper rep rep m
forall {m :: * -> *}. Monad m => Mapper SOACS SOACS m
identityMapper :: (Monad m) => Mapper SOACS SOACS m)
{ mapOnOp = traverseSOACStms (\Scope SOACS
_ Stms SOACS
stms -> Stms SOACS -> Identity (Stms SOACS)
forall a. a -> Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Stms SOACS -> Identity (Stms SOACS))
-> Stms SOACS -> Identity (Stms SOACS)
forall a b. (a -> b) -> a -> b
$ Stms SOACS -> Stms SOACS
onStms Stms SOACS
stms),
mapOnBody = \Scope SOACS
_ Body SOACS
body -> Body SOACS -> Identity (Body SOACS)
forall a. a -> Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Body SOACS -> Identity (Body SOACS))
-> Body SOACS -> Identity (Body SOACS)
forall a b. (a -> b) -> a -> b
$ Body SOACS -> Body SOACS
onBody Body SOACS
body
}
onStms :: Stms SOACS -> Stms SOACS
onStms = (Stm SOACS -> Stm SOACS) -> Stms SOACS -> Stms SOACS
forall a b. (a -> b) -> Seq a -> Seq b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Stm SOACS -> Stm SOACS
onStm
onStm :: Stm SOACS -> Stm SOACS
onStm (Let (Pat [PatElem (LetDec SOACS)
pe]) StmAux (ExpDec SOACS)
aux (BasicOp (UpdateAcc Safety
safety VName
acc [SubExp]
is [SubExp]
_)))
| Acc VName
c Shape
_ [Type]
_ <- PatElem (LetDec SOACS) -> Type
forall dec. Typed dec => PatElem dec -> Type
patElemType PatElem (LetDec SOACS)
pe,
Just [SubExp]
zero <- VName -> [(VName, [SubExp])] -> Maybe [SubExp]
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup VName
c [(VName, [SubExp])]
certs_to_zeroes =
Pat (LetDec SOACS)
-> StmAux (ExpDec SOACS) -> Exp SOACS -> Stm SOACS
forall rep.
Pat (LetDec rep) -> StmAux (ExpDec rep) -> Exp rep -> Stm rep
Let ([PatElem (LetDec SOACS)] -> Pat (LetDec SOACS)
forall dec. [PatElem dec] -> Pat dec
Pat [PatElem (LetDec SOACS)
pe]) StmAux (ExpDec SOACS)
aux (BasicOp -> Exp SOACS
forall rep. BasicOp -> Exp rep
BasicOp (Safety -> VName -> [SubExp] -> [SubExp] -> BasicOp
UpdateAcc Safety
safety VName
acc [SubExp]
is [SubExp]
zero))
onStm (Let Pat (LetDec SOACS)
pat StmAux (ExpDec SOACS)
aux Exp SOACS
e) = Pat (LetDec SOACS)
-> StmAux (ExpDec SOACS) -> Exp SOACS -> Stm SOACS
forall rep.
Pat (LetDec rep) -> StmAux (ExpDec rep) -> Exp rep -> Stm rep
Let Pat (LetDec SOACS)
pat StmAux (ExpDec SOACS)
aux (Exp SOACS -> Stm SOACS) -> Exp SOACS -> Stm SOACS
forall a b. (a -> b) -> a -> b
$ Exp SOACS -> Exp SOACS
onExp Exp SOACS
e
onBody :: Body SOACS -> Body SOACS
onBody Body SOACS
body = Body SOACS
body {bodyStms = onStms $ bodyStms body}
updateAccParamTypes :: Int -> Shape -> Lambda SOACS -> Lambda SOACS
updateAccParamTypes :: Int -> Shape -> Lambda SOACS -> Lambda SOACS
updateAccParamTypes Int
n_inputs Shape
adj_sh Lambda SOACS
lam
| Shape
adj_sh Shape -> Shape -> Bool
forall a. Eq a => a -> a -> Bool
== Shape
forall a. Monoid a => a
mempty = Lambda SOACS
lam
| Bool
otherwise =
let ([Param Type]
cert_ps, [Param Type]
rest_ps) = Int -> [Param Type] -> ([Param Type], [Param Type])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
n_inputs (Lambda SOACS -> [LParam SOACS]
forall rep t. GLambda rep t -> [LParam rep]
lambdaParams Lambda SOACS
lam)
([Param Type]
acc_ps, [Param Type]
other_ps) = Int -> [Param Type] -> ([Param Type], [Param Type])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
n_inputs [Param Type]
rest_ps
acc_ps' :: [Param Type]
acc_ps' = (Param Type -> Param Type) -> [Param Type] -> [Param Type]
forall a b. (a -> b) -> [a] -> [b]
map ([VName] -> Param Type -> Param Type
updateParam [VName]
cert_names) [Param Type]
acc_ps
cert_names :: [VName]
cert_names = (Param Type -> VName) -> [Param Type] -> [VName]
forall a b. (a -> b) -> [a] -> [b]
map Param Type -> VName
forall dec. Param dec -> VName
paramName [Param Type]
cert_ps
body' :: Body SOACS
body' = [VName] -> Body SOACS -> Body SOACS
updateBody [VName]
cert_names (Lambda SOACS -> Body SOACS
forall rep t. GLambda rep t -> Body rep
lambdaBody Lambda SOACS
lam)
ret' :: [Type]
ret' = (Type -> Type) -> [Type] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map ([VName] -> Type -> Type
updateAccType [VName]
cert_names) (Lambda SOACS -> [Type]
forall rep t. GLambda rep t -> [t]
lambdaReturnType Lambda SOACS
lam)
in Lambda SOACS
lam
{ lambdaParams = cert_ps ++ acc_ps' ++ other_ps,
lambdaReturnType = ret',
lambdaBody = body'
}
where
updateParam :: [VName] -> Param Type -> Param Type
updateParam :: [VName] -> Param Type -> Param Type
updateParam [VName]
certs Param Type
p =
Param Type
p {paramDec = updateAccType certs (paramDec p)}
updateAccType :: [VName] -> Type -> Type
updateAccType :: [VName] -> Type -> Type
updateAccType [VName]
certs (Acc VName
cert Shape
acc_shape [Type]
ts)
| VName
cert VName -> [VName] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [VName]
certs =
VName -> Shape -> [Type] -> Type
forall shape o. VName -> Shape -> [Type] -> TypeBase shape o
Acc VName
cert Shape
acc_shape ((Type -> Type) -> [Type] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map (Type -> Shape -> Type
`arrayOfShape` Shape
adj_sh) [Type]
ts)
updateAccType [VName]
_ Type
t = Type
t
updateBody :: [VName] -> Body SOACS -> Body SOACS
updateBody :: [VName] -> Body SOACS -> Body SOACS
updateBody [VName]
certs Body SOACS
body =
Body SOACS
body {bodyStms = fmap (updateStm certs) (bodyStms body)}
updateStm :: [VName] -> Stm SOACS -> Stm SOACS
updateStm :: [VName] -> Stm SOACS -> Stm SOACS
updateStm [VName]
certs (Let Pat (LetDec SOACS)
pat StmAux (ExpDec SOACS)
aux Exp SOACS
e) =
Pat (LetDec SOACS)
-> StmAux (ExpDec SOACS) -> Exp SOACS -> Stm SOACS
forall rep.
Pat (LetDec rep) -> StmAux (ExpDec rep) -> Exp rep -> Stm rep
Let ([VName] -> Pat Type -> Pat Type
updatePat [VName]
certs Pat Type
Pat (LetDec SOACS)
pat) StmAux (ExpDec SOACS)
aux ([VName] -> Exp SOACS -> Exp SOACS
updateExp [VName]
certs Exp SOACS
e)
updatePat :: [VName] -> Pat Type -> Pat Type
updatePat :: [VName] -> Pat Type -> Pat Type
updatePat [VName]
certs (Pat [PatElem Type]
pes) =
[PatElem Type] -> Pat Type
forall dec. [PatElem dec] -> Pat dec
Pat ([PatElem Type] -> Pat Type) -> [PatElem Type] -> Pat Type
forall a b. (a -> b) -> a -> b
$ (PatElem Type -> PatElem Type) -> [PatElem Type] -> [PatElem Type]
forall a b. (a -> b) -> [a] -> [b]
map (\PatElem Type
pe -> PatElem Type
pe {patElemDec = updateAccType certs (patElemDec pe)}) [PatElem Type]
pes
updateExp :: [VName] -> Exp SOACS -> Exp SOACS
updateExp :: [VName] -> Exp SOACS -> Exp SOACS
updateExp [VName]
certs = Identity (Exp SOACS) -> Exp SOACS
forall a. Identity a -> a
runIdentity (Identity (Exp SOACS) -> Exp SOACS)
-> (Exp SOACS -> Identity (Exp SOACS)) -> Exp SOACS -> Exp SOACS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mapper SOACS SOACS Identity -> Exp SOACS -> Identity (Exp SOACS)
forall (m :: * -> *) frep trep.
Monad m =>
Mapper frep trep m -> Exp frep -> m (Exp trep)
mapExpM Mapper SOACS SOACS Identity
mapper
where
mapper :: Mapper SOACS SOACS Identity
mapper =
(Mapper SOACS SOACS m
forall rep (m :: * -> *). Monad m => Mapper rep rep m
forall {m :: * -> *}. Monad m => Mapper SOACS SOACS m
identityMapper :: (Monad m) => Mapper SOACS SOACS m)
{ mapOnBody = \Scope SOACS
_ Body SOACS
b -> Body SOACS -> Identity (Body SOACS)
forall a. a -> Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Body SOACS -> Identity (Body SOACS))
-> Body SOACS -> Identity (Body SOACS)
forall a b. (a -> b) -> a -> b
$ [VName] -> Body SOACS -> Body SOACS
updateBody [VName]
certs Body SOACS
b,
mapOnOp = pure . updateSOAC certs
}
updateSOAC :: [VName] -> SOAC SOACS -> SOAC SOACS
updateSOAC :: [VName] -> SOAC SOACS -> SOAC SOACS
updateSOAC [VName]
certs = Identity (SOAC SOACS) -> SOAC SOACS
forall a. Identity a -> a
runIdentity (Identity (SOAC SOACS) -> SOAC SOACS)
-> (SOAC SOACS -> Identity (SOAC SOACS))
-> SOAC SOACS
-> SOAC SOACS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SOACMapper SOACS SOACS Identity
-> SOAC SOACS -> Identity (SOAC SOACS)
forall (m :: * -> *) frep trep.
Monad m =>
SOACMapper frep trep m -> SOAC frep -> m (SOAC trep)
mapSOACM SOACMapper SOACS SOACS Identity
mapper
where
mapper :: SOACMapper SOACS SOACS Identity
mapper =
SOACMapper SOACS SOACS Identity
forall rep (m :: * -> *). Monad m => SOACMapper rep rep m
identitySOACMapper
{ mapOnSOACLambda = pure . updateLambda certs
}
updateLambda :: [VName] -> Lambda SOACS -> Lambda SOACS
updateLambda :: [VName] -> Lambda SOACS -> Lambda SOACS
updateLambda [VName]
certs Lambda SOACS
l =
Lambda SOACS
l
{ lambdaParams = map (updateParam certs) (lambdaParams l),
lambdaReturnType = map (updateAccType certs) (lambdaReturnType l),
lambdaBody = updateBody certs (lambdaBody l)
}
diffWithAcc ::
VjpOps ->
Pat Type ->
StmAux () ->
[(Shape, [VName], Maybe (Lambda SOACS, [SubExp]))] ->
Lambda SOACS ->
ADM () ->
ADM ()
diffWithAcc :: VjpOps
-> Pat Type
-> StmAux ()
-> [(Shape, [VName], Maybe (Lambda SOACS, [SubExp]))]
-> Lambda SOACS
-> ADM ()
-> ADM ()
diffWithAcc VjpOps
ops Pat Type
pat StmAux ()
aux [(Shape, [VName], Maybe (Lambda SOACS, [SubExp]))]
inputs Lambda SOACS
lam ADM ()
m = do
Stm (Rep ADM) -> ADM ()
forall (m :: * -> *). MonadBuilder m => Stm (Rep m) -> m ()
addStm (Stm (Rep ADM) -> ADM ()) -> Stm (Rep ADM) -> ADM ()
forall a b. (a -> b) -> a -> b
$ Pat (LetDec (Rep ADM))
-> StmAux (ExpDec (Rep ADM)) -> Exp (Rep ADM) -> Stm (Rep ADM)
forall rep.
Pat (LetDec rep) -> StmAux (ExpDec rep) -> Exp rep -> Stm rep
Let Pat Type
Pat (LetDec (Rep ADM))
pat StmAux ()
StmAux (ExpDec (Rep ADM))
aux (Exp (Rep ADM) -> Stm (Rep ADM)) -> Exp (Rep ADM) -> Stm (Rep ADM)
forall a b. (a -> b) -> a -> b
$ [WithAccInput (Rep ADM)] -> Lambda (Rep ADM) -> Exp (Rep ADM)
forall rep. [WithAccInput rep] -> Lambda rep -> Exp rep
WithAcc [WithAccInput (Rep ADM)]
[(Shape, [VName], Maybe (Lambda SOACS, [SubExp]))]
inputs Lambda (Rep ADM)
Lambda SOACS
lam
ADM ()
m
ADM () -> ADM ()
forall a. ADM a -> ADM a
returnSweepCode (ADM () -> ADM ()) -> ADM () -> ADM ()
forall a b. (a -> b) -> a -> b
$ do
adj_shape <- ADM Shape
askShape
adjs <- mapM lookupAdj $ patNames pat
adjs' <- transposeAdjs adj_shape adjs
lam' <- renameLambda lam
let lam'_vec = Int -> Shape -> Lambda SOACS -> Lambda SOACS
updateAccParamTypes Int
n_inputs Shape
adj_shape Lambda SOACS
lam'
free_vars <- filterM isActive $ namesToList $ freeIn lam'_vec
free_accs <- filterM (fmap isAcc . lookupType) free_vars
let free_vars' = [VName]
free_vars [VName] -> [VName] -> [VName]
forall a. Eq a => [a] -> [a] -> [a]
\\ [VName]
free_accs
op_certs =
((Param Type, (Shape, [VName], Maybe (Lambda SOACS, [SubExp])))
-> VName)
-> [(Param Type, (Shape, [VName], Maybe (Lambda SOACS, [SubExp])))]
-> [VName]
forall a b. (a -> b) -> [a] -> [b]
map (Param Type -> VName
forall dec. Param dec -> VName
paramName (Param Type -> VName)
-> ((Param Type, (Shape, [VName], Maybe (Lambda SOACS, [SubExp])))
-> Param Type)
-> (Param Type, (Shape, [VName], Maybe (Lambda SOACS, [SubExp])))
-> VName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Param Type, (Shape, [VName], Maybe (Lambda SOACS, [SubExp])))
-> Param Type
forall a b. (a, b) -> a
fst)
([(Param Type, (Shape, [VName], Maybe (Lambda SOACS, [SubExp])))]
-> [VName])
-> ([(Param Type,
(Shape, [VName], Maybe (Lambda SOACS, [SubExp])))]
-> [(Param Type,
(Shape, [VName], Maybe (Lambda SOACS, [SubExp])))])
-> [(Param Type, (Shape, [VName], Maybe (Lambda SOACS, [SubExp])))]
-> [VName]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Param Type, (Shape, [VName], Maybe (Lambda SOACS, [SubExp])))
-> Bool)
-> [(Param Type, (Shape, [VName], Maybe (Lambda SOACS, [SubExp])))]
-> [(Param Type, (Shape, [VName], Maybe (Lambda SOACS, [SubExp])))]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Shape, [VName], Maybe (Lambda SOACS, [SubExp])) -> Bool
forall {a} {b} {a}. (a, b, Maybe a) -> Bool
hasOperator ((Shape, [VName], Maybe (Lambda SOACS, [SubExp])) -> Bool)
-> ((Param Type, (Shape, [VName], Maybe (Lambda SOACS, [SubExp])))
-> (Shape, [VName], Maybe (Lambda SOACS, [SubExp])))
-> (Param Type, (Shape, [VName], Maybe (Lambda SOACS, [SubExp])))
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Param Type, (Shape, [VName], Maybe (Lambda SOACS, [SubExp])))
-> (Shape, [VName], Maybe (Lambda SOACS, [SubExp]))
forall a b. (a, b) -> b
snd)
([(Param Type, (Shape, [VName], Maybe (Lambda SOACS, [SubExp])))]
-> [VName])
-> [(Param Type, (Shape, [VName], Maybe (Lambda SOACS, [SubExp])))]
-> [VName]
forall a b. (a -> b) -> a -> b
$ [Param Type]
-> [(Shape, [VName], Maybe (Lambda SOACS, [SubExp]))]
-> [(Param Type, (Shape, [VName], Maybe (Lambda SOACS, [SubExp])))]
forall a b. [a] -> [b] -> [(a, b)]
zip (Int -> [Param Type] -> [Param Type]
forall a. Int -> [a] -> [a]
take Int
n_inputs (Lambda SOACS -> [LParam SOACS]
forall rep t. GLambda rep t -> [LParam rep]
lambdaParams Lambda SOACS
lam'_vec)) [(Shape, [VName], Maybe (Lambda SOACS, [SubExp]))]
inputs
lam'' <- withOperatorAccs op_certs $ diffLambda' adjs' free_vars' lam'_vec
(inputs_zeroes, inputs') <-
unzip <$> zipWithM (renameInputLambda adj_shape) (chunks lengths adjs) inputs
let certs = (Param Type -> VName) -> [Param Type] -> [VName]
forall a b. (a -> b) -> [a] -> [b]
map Param Type -> VName
forall dec. Param dec -> VName
paramName ([Param Type] -> [VName]) -> [Param Type] -> [VName]
forall a b. (a -> b) -> a -> b
$ Int -> [Param Type] -> [Param Type]
forall a. Int -> [a] -> [a]
take Int
n_inputs ([Param Type] -> [Param Type]) -> [Param Type] -> [Param Type]
forall a b. (a -> b) -> a -> b
$ Lambda SOACS -> [LParam SOACS]
forall rep t. GLambda rep t -> [LParam rep]
lambdaParams Lambda SOACS
lam''
raw_adjs <-
letTupExp "with_acc_contrib" . WithAcc inputs' $
zeroOutUpdates (zip certs inputs_zeroes) lam''
let n_arrs = [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
lengths
(arr_adjs, free_adjs) = splitAt n_arrs raw_adjs
arr_adjs' <- zipWithM (transposeAccResult adj_shape) (map (\(Shape
s, [VName]
_, Maybe (Lambda SOACS, [SubExp])
_) -> Shape
s) inputs) arr_adjs
zipWithM_ insAdj arrs arr_adjs'
zipWithM_ insAdj free_vars' free_adjs
where
n_inputs :: Int
n_inputs = [(Shape, [VName], Maybe (Lambda SOACS, [SubExp]))] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Shape, [VName], Maybe (Lambda SOACS, [SubExp]))]
inputs
lengths :: [Int]
lengths = ((Shape, [VName], Maybe (Lambda SOACS, [SubExp])) -> Int)
-> [(Shape, [VName], Maybe (Lambda SOACS, [SubExp]))] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (\(Shape
_, [VName]
as, Maybe (Lambda SOACS, [SubExp])
_) -> [VName] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [VName]
as) [(Shape, [VName], Maybe (Lambda SOACS, [SubExp]))]
inputs
arrs :: [VName]
arrs = ((Shape, [VName], Maybe (Lambda SOACS, [SubExp])) -> [VName])
-> [(Shape, [VName], Maybe (Lambda SOACS, [SubExp]))] -> [VName]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\(Shape
_, [VName]
as, Maybe (Lambda SOACS, [SubExp])
_) -> [VName]
as) [(Shape, [VName], Maybe (Lambda SOACS, [SubExp]))]
inputs
hasOperator :: (a, b, Maybe a) -> Bool
hasOperator (a
_, b
_, Maybe a
op) = Maybe a -> Bool
forall a. Maybe a -> Bool
isJust Maybe a
op
transposeAdjs :: Shape -> [Adj] -> ADM [Adj]
transposeAdjs :: Shape -> [Adj] -> ADM [Adj]
transposeAdjs Shape
adj_sh [Adj]
adjs
| Shape
adj_sh Shape -> Shape -> Bool
forall a. Eq a => a -> a -> Bool
== Shape
forall a. Monoid a => a
mempty = [Adj] -> ADM [Adj]
forall a. a -> ADM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [Adj]
adjs
| Bool
otherwise = do
let n_arrs :: Int
n_arrs = [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int]
lengths
([Adj]
acc_adjs, [Adj]
other_adjs) = Int -> [Adj] -> ([Adj], [Adj])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
n_arrs [Adj]
adjs
acc_adjs' <- (Adj -> ADM Adj) -> [Adj] -> ADM [Adj]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM Adj -> ADM Adj
transposeAdj [Adj]
acc_adjs
pure $ acc_adjs' ++ other_adjs
transposeAdj :: Adj -> ADM Adj
transposeAdj :: Adj -> ADM Adj
transposeAdj Adj
adj = do
v <- Adj -> ADM VName
adjVal Adj
adj
v' <- vecToInner v
pure $ AdjVal $ Var v'
transposeAccResult :: Shape -> Shape -> VName -> ADM VName
transposeAccResult :: Shape -> Shape -> VName -> ADM VName
transposeAccResult Shape
adj_sh Shape
shape VName
v
| Shape
adj_sh Shape -> Shape -> Bool
forall a. Eq a => a -> a -> Bool
== Shape
forall a. Monoid a => a
mempty = VName -> ADM VName
forall a. a -> ADM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure VName
v
| Bool
otherwise = do
v_t <- VName -> ADM Type
forall rep (m :: * -> *). HasScope rep m => VName -> m Type
lookupType VName
v
let r = Shape -> Int
forall a. ArrayShape a => a -> Int
shapeRank Shape
adj_sh
s = Shape -> Int
forall a. ArrayShape a => a -> Int
shapeRank Shape
shape
total = Type -> Int
forall shape o. ArrayShape shape => TypeBase shape o -> Int
arrayRank Type
v_t
perm = [Int
s .. Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
r Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1] [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
0 .. Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1] [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++ [Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
r .. Int
total Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]
letExp (baseName v <> "_tr") $ BasicOp $ Rearrange v perm
renameInputLambda :: Shape
-> t Adj
-> (a, [VName], Maybe a)
-> ADM ([SubExp], (a, t VName, Maybe (Lambda SOACS, [SubExp])))
renameInputLambda Shape
adj_sh t Adj
as_adj (a
shape, [VName]
as, Maybe a
op) = do
orig_nes_ts <- (VName -> ADM Type) -> [VName] -> ADM [Type]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM ((Type -> Type) -> ADM Type -> ADM Type
forall a b. (a -> b) -> ADM a -> ADM b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int -> Type -> Type
forall d m.
Int -> TypeBase (ShapeBase d) m -> TypeBase (ShapeBase d) m
stripArray (a -> Int
forall a. ArrayShape a => a -> Int
shapeRank a
shape)) (ADM Type -> ADM Type) -> (VName -> ADM Type) -> VName -> ADM Type
forall b c a. (b -> c) -> (a -> b) -> a -> c
. VName -> ADM Type
forall rep (m :: * -> *). HasScope rep m => VName -> m Type
lookupType) [VName]
as
let vec_nes_ts = (Type -> Type) -> [Type] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map (Type -> Shape -> Type
`arrayOfShape` Shape
adj_sh) [Type]
orig_nes_ts
zeroes <- mapM (zeroArray mempty) vec_nes_ts
as' <- mapM (letExp "acc_adj_init" . BasicOp . Replicate mempty . Var <=< adjVal) as_adj
as'' <- mapM vecToInner as'
op' <- case op of
Maybe a
Nothing -> Maybe (Lambda SOACS, [SubExp])
-> ADM (Maybe (Lambda SOACS, [SubExp]))
forall a. a -> ADM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (Lambda SOACS, [SubExp])
forall a. Maybe a
Nothing
Just a
_ -> do
add_lam <- Int -> [Type] -> ADM (Lambda SOACS)
forall (m :: * -> *).
(MonadBuilder m, Rep m ~ SOACS) =>
Int -> [Type] -> m (Lambda SOACS)
accAddLambda (a -> Int
forall a. ArrayShape a => a -> Int
shapeRank a
shape) [Type]
vec_nes_ts
nes <- mapM (letSubExp "acc_adj_zero" . zeroExp) vec_nes_ts
pure $ Just (add_lam, nes)
pure (map Var zeroes, (shape, as'', op'))
diffLambda' :: [Adj] -> [VName] -> GLambda SOACS t -> ADM (Lambda (Rep ADM))
diffLambda' [Adj]
res_adjs [VName]
get_adjs_for (Lambda [LParam SOACS]
params [t]
_ Body SOACS
body) =
[LParam (Rep ADM)] -> ADM Result -> ADM (Lambda (Rep ADM))
forall (m :: * -> *).
MonadBuilder m =>
[LParam (Rep m)] -> m Result -> m (Lambda (Rep m))
mkLambda [LParam (Rep ADM)]
[LParam SOACS]
params (ADM Result -> ADM (Lambda (Rep ADM)))
-> ADM Result -> ADM (Lambda (Rep ADM))
forall a b. (a -> b) -> a -> b
$ do
res <- Body (Rep ADM) -> ADM Result
Body SOACS -> ADM Result
forall (m :: * -> *). MonadBuilder m => Body (Rep m) -> m Result
bodyBind (Body SOACS -> ADM Result) -> ADM (Body SOACS) -> ADM Result
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< VjpOps -> [Adj] -> [VName] -> Body SOACS -> ADM (Body SOACS)
vjpBody VjpOps
ops [Adj]
res_adjs [VName]
get_adjs_for Body SOACS
body
pure $ take n_inputs res <> takeLast (length get_adjs_for) res
diffUpdateAcc ::
Pat Type ->
StmAux () ->
Safety ->
VName ->
[SubExp] ->
[SubExp] ->
ADM () ->
ADM ()
diffUpdateAcc :: Pat Type
-> StmAux ()
-> Safety
-> VName
-> [SubExp]
-> [SubExp]
-> ADM ()
-> ADM ()
diffUpdateAcc Pat Type
pat StmAux ()
aux Safety
safety VName
acc [SubExp]
is [SubExp]
vs ADM ()
m = do
let Pat ~[PatElem Type
pe] = Pat Type
pat
Stm (Rep ADM) -> ADM ()
forall (m :: * -> *). MonadBuilder m => Stm (Rep m) -> m ()
addStm (Stm (Rep ADM) -> ADM ()) -> Stm (Rep ADM) -> ADM ()
forall a b. (a -> b) -> a -> b
$ Pat (LetDec (Rep ADM))
-> StmAux (ExpDec (Rep ADM)) -> Exp (Rep ADM) -> Stm (Rep ADM)
forall rep.
Pat (LetDec rep) -> StmAux (ExpDec rep) -> Exp rep -> Stm rep
Let Pat Type
Pat (LetDec (Rep ADM))
pat StmAux ()
StmAux (ExpDec (Rep ADM))
aux (Exp (Rep ADM) -> Stm (Rep ADM)) -> Exp (Rep ADM) -> Stm (Rep ADM)
forall a b. (a -> b) -> a -> b
$ BasicOp -> Exp (Rep ADM)
forall rep. BasicOp -> Exp rep
BasicOp (BasicOp -> Exp (Rep ADM)) -> BasicOp -> Exp (Rep ADM)
forall a b. (a -> b) -> a -> b
$ Safety -> VName -> [SubExp] -> [SubExp] -> BasicOp
UpdateAcc Safety
safety VName
acc [SubExp]
is [SubExp]
vs
ADM ()
m
adj <- VName -> ADM VName
lookupAdjVal (VName -> ADM VName) -> VName -> ADM VName
forall a b. (a -> b) -> a -> b
$ PatElem Type -> VName
forall dec. PatElem dec -> VName
patElemName PatElem Type
pe
returnSweepCode $ do
adj_t <- lookupType adj
acc_t <- lookupType acc
overwrites <- case acc_t of
Acc VName
cert Shape
_ [Type]
_ -> Bool -> Bool
not (Bool -> Bool) -> ADM Bool -> ADM Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> VName -> ADM Bool
isOperatorAcc VName
cert
Type
_ -> Bool -> ADM Bool
forall a. a -> ADM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True
let elem_t = Int -> Type -> Type
forall d m.
Int -> TypeBase (ShapeBase d) m -> TypeBase (ShapeBase d) m
stripArray ([SubExp] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [SubExp]
is) Type
adj_t
slice = Type -> [DimIndex SubExp] -> Slice SubExp
fullSlice Type
adj_t ([DimIndex SubExp] -> Slice SubExp)
-> [DimIndex SubExp] -> Slice SubExp
forall a b. (a -> b) -> a -> b
$ (SubExp -> DimIndex SubExp) -> [SubExp] -> [DimIndex SubExp]
forall a b. (a -> b) -> [a] -> [b]
map SubExp -> DimIndex SubExp
forall d. d -> DimIndex d
DimFix [SubExp]
is
index_adj = ADM (Exp (Rep ADM)) -> ADM (Exp (Rep ADM))
maybe_copy (ADM (Exp (Rep ADM)) -> ADM (Exp (Rep ADM)))
-> ADM (Exp (Rep ADM)) -> ADM (Exp (Rep ADM))
forall a b. (a -> b) -> a -> b
$ Exp (Rep ADM) -> ADM (Exp (Rep ADM))
forall a. a -> ADM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Exp (Rep ADM) -> ADM (Exp (Rep ADM)))
-> Exp (Rep ADM) -> ADM (Exp (Rep ADM))
forall a b. (a -> b) -> a -> b
$ BasicOp -> Exp (Rep ADM)
forall rep. BasicOp -> Exp rep
BasicOp (BasicOp -> Exp (Rep ADM)) -> BasicOp -> Exp (Rep ADM)
forall a b. (a -> b) -> a -> b
$ VName -> Slice SubExp -> BasicOp
Index VName
adj Slice SubExp
slice
where
maybe_copy :: ADM (Exp (Rep ADM)) -> ADM (Exp (Rep ADM))
maybe_copy
| [SubExp] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([SubExp] -> Bool) -> [SubExp] -> Bool
forall a b. (a -> b) -> a -> b
$ Slice SubExp -> [SubExp]
forall d. Slice d -> [d]
sliceDims Slice SubExp
slice = ADM (Exp (Rep ADM)) -> ADM (Exp (Rep ADM))
forall a. a -> a
id
| Bool
otherwise = ADM (Exp (Rep ADM)) -> ADM (Exp (Rep ADM))
forall (m :: * -> *).
MonadBuilder m =>
m (Exp (Rep m)) -> m (Exp (Rep m))
eCopy
zeroed
| Bool
overwrites = do
z <- Name -> Exp (Rep ADM) -> ADM SubExp
forall (m :: * -> *).
MonadBuilder m =>
Name -> Exp (Rep m) -> m SubExp
letSubExp Name
"acc_adj_zero" (Exp (Rep ADM) -> ADM SubExp) -> Exp (Rep ADM) -> ADM SubExp
forall a b. (a -> b) -> a -> b
$ Type -> Exp (Rep ADM)
forall rep. Type -> Exp rep
zeroExp Type
elem_t
pure $ BasicOp $ Update Unsafe adj slice z
| Bool
otherwise = Exp rep -> ADM (Exp rep)
forall a. a -> ADM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Exp rep -> ADM (Exp rep)) -> Exp rep -> ADM (Exp rep)
forall a b. (a -> b) -> a -> b
$ BasicOp -> Exp rep
forall rep. BasicOp -> Exp rep
BasicOp (BasicOp -> Exp rep) -> BasicOp -> Exp rep
forall a b. (a -> b) -> a -> b
$ SubExp -> BasicOp
SubExp (SubExp -> BasicOp) -> SubExp -> BasicOp
forall a b. (a -> b) -> a -> b
$ VName -> SubExp
Var VName
adj
(adj_i, acc_adj) <- case safety of
Safety
Unsafe ->
(,)
(VName -> VName -> (VName, VName))
-> ADM VName -> ADM (VName -> (VName, VName))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Name -> Exp (Rep ADM) -> ADM VName
forall (m :: * -> *).
MonadBuilder m =>
Name -> Exp (Rep m) -> m VName
letExp Name
"updateacc_val_adj" (Exp SOACS -> ADM VName) -> ADM (Exp SOACS) -> ADM VName
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ADM (Exp (Rep ADM))
ADM (Exp SOACS)
index_adj)
ADM (VName -> (VName, VName)) -> ADM VName -> ADM (VName, VName)
forall a b. ADM (a -> b) -> ADM a -> ADM b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Name -> Exp (Rep ADM) -> ADM VName
forall (m :: * -> *).
MonadBuilder m =>
Name -> Exp (Rep m) -> m VName
letExp Name
"acc_adj" (Exp SOACS -> ADM VName) -> ADM (Exp SOACS) -> ADM VName
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ADM (Exp SOACS)
forall {rep}. ADM (Exp rep)
zeroed)
Safety
Safe -> do
~[adj_i, acc_adj] <-
Name -> Exp (Rep ADM) -> ADM [VName]
forall (m :: * -> *).
MonadBuilder m =>
Name -> Exp (Rep m) -> m [VName]
letTupExp Name
"updateacc_adj"
(Exp SOACS -> ADM [VName]) -> ADM (Exp SOACS) -> ADM [VName]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ADM (Exp (Rep ADM))
-> ADM (Body (Rep ADM))
-> ADM (Body (Rep ADM))
-> ADM (Exp (Rep ADM))
forall (m :: * -> *).
(MonadBuilder m, BranchType (Rep m) ~ ExtType) =>
m (Exp (Rep m))
-> m (Body (Rep m)) -> m (Body (Rep m)) -> m (Exp (Rep m))
eIf
(Shape -> [ADM (Exp (Rep ADM))] -> ADM (Exp (Rep ADM))
forall (m :: * -> *).
MonadBuilder m =>
Shape -> [m (Exp (Rep m))] -> m (Exp (Rep m))
eShapeInBounds (Type -> Shape
forall shape o. ArrayShape shape => TypeBase shape o -> shape
arrayShape Type
adj_t) ((SubExp -> ADM (Exp SOACS)) -> [SubExp] -> [ADM (Exp SOACS)]
forall a b. (a -> b) -> [a] -> [b]
map SubExp -> ADM (Exp (Rep ADM))
SubExp -> ADM (Exp SOACS)
forall (m :: * -> *). MonadBuilder m => SubExp -> m (Exp (Rep m))
eSubExp [SubExp]
is))
([ADM (Exp (Rep ADM))] -> ADM (Body (Rep ADM))
forall (m :: * -> *).
MonadBuilder m =>
[m (Exp (Rep m))] -> m (Body (Rep m))
eBody [ADM (Exp (Rep ADM))
index_adj, ADM (Exp (Rep ADM))
ADM (Exp SOACS)
forall {rep}. ADM (Exp rep)
zeroed])
([ADM (Exp (Rep ADM))] -> ADM (Body (Rep ADM))
forall (m :: * -> *).
MonadBuilder m =>
[m (Exp (Rep m))] -> m (Body (Rep m))
eBody [Exp (Rep ADM) -> ADM (Exp (Rep ADM))
forall a. a -> ADM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Exp (Rep ADM) -> ADM (Exp (Rep ADM)))
-> Exp (Rep ADM) -> ADM (Exp (Rep ADM))
forall a b. (a -> b) -> a -> b
$ Type -> Exp (Rep ADM)
forall rep. Type -> Exp rep
zeroExp Type
elem_t, Exp (Rep ADM) -> ADM (Exp (Rep ADM))
forall a. a -> ADM a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Exp (Rep ADM) -> ADM (Exp (Rep ADM)))
-> Exp (Rep ADM) -> ADM (Exp (Rep ADM))
forall a b. (a -> b) -> a -> b
$ BasicOp -> Exp (Rep ADM)
forall rep. BasicOp -> Exp rep
BasicOp (BasicOp -> Exp (Rep ADM)) -> BasicOp -> Exp (Rep ADM)
forall a b. (a -> b) -> a -> b
$ SubExp -> BasicOp
SubExp (SubExp -> BasicOp) -> SubExp -> BasicOp
forall a b. (a -> b) -> a -> b
$ VName -> SubExp
Var VName
adj])
pure (adj_i, acc_adj)
updateSubExpAdj (head vs) adj_i
insAdj acc acc_adj