Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adapt implementation of ONNX operators to code from OnnxToFeld. #511

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

kffaxen
Copy link
Contributor

@kffaxen kffaxen commented Sep 15, 2020

This version of Operators enables code generated by OnnxToFeld to
be built and run. Implementation is still incomplete, however.

This version of Operators enables code generated by OnnxToFeld to
be built and run. Implementation is still incomplete, however.
where invDev = map (\ v -> 1.0 / sqrt (v + epsilon)) var <! 1 <! 1
xsHat = bcMul invDev $ bcSub xs $ mean <! 1 <! 1
ys = bcAdd (bcMul xsHat $ gamma <! 1 <! 1) $ beta <! 1 <! 1
epsilon = value $ P.realToFrac $ getAttr attrs aaFloat 1e-5 "epsilon"

-- | Flatten a tensor to a matrix
onnxFlatten :: Pushy vec => Attrs -> vec a -> Push DIM2 a
onnxFlatten attrs vec = flatPush (P.fromIntegral $ getAttr attrs aaInt 1 "axis") $ toPush vec
onnxFlatten_1 :: (Pushy vec, Syntax a) => Attrs -> vec a -> Pull DIM2 a
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything seems to be Pully in this module except this stuff. Why do we need to store a reshape (index transformation) to memory?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could in principle be done with a Pull vector and consequently be fuseable. The problem is that the index expressions would be horrible, using division and modulus since the result has fewer dimensions than the argument so that a single integer index must be split into several. We have no optimization in place that eliminates them, so they will typically end up in the innermost loop.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be great to have that kind of information in a comment in the source code.

onnxFlatten :: Pushy vec => Attrs -> vec a -> Push DIM2 a
onnxFlatten attrs vec = flatPush (P.fromIntegral $ getAttr attrs aaInt 1 "axis") $ toPush vec
onnxFlatten_1 :: (Pushy vec, Syntax a) => Attrs -> vec a -> Pull DIM2 a
onnxFlatten_1 attrs vec = toPull $ store $ flatPush (P.fromIntegral $ getAttr attrs aaInt 1 "axis") $ toPush vec
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is idxExp something from class Ix?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No.

onnxAdd :: (Num a, ShapelyU sh1 sh2)
=> Attrs -> Pull sh1 a -> Pull sh2 a -> Pull (UnionShape sh1 sh2) a
onnxAdd _ = bcAdd
onnxAdd_2 :: (Num a, ShapelyU sh1 sh2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice if the handwritten code is readable and these are binary operators, do we really need the _2 on them? Same question for the _5 on onnxBatchNormalization, _3 on onnxGemm, _1 on onnxFlatten, and so on.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The arity information is necessary because some ONNX operators can be used with different numbers of arguments. To avoid it, onnxToFeld needs to know about those operators and treat them as special cases, something I have tried to avoid, at least for now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we get a silent failure if we get the special cases wrong? If not, I would prefer an Operators.hs without extra suffixes and two additional lines (| op elem varargOps = "" and | otherwise = "_" <> show (length args)) in OnnxToFeld.hs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants