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

Allow MLGraphBuilder.build() to be called only once #717

Merged
merged 2 commits into from
Jul 16, 2024

Conversation

a-sully
Copy link
Contributor

@a-sully a-sully commented Jul 7, 2024

Fixes #567

If MLGraphBuilder.build() results in anything other than a TypeError - e.g. it successfully resolves with an or MLGraph or rejects with a NotSupportedError - that MLGraphBuilder has now been "built" and all subsequent methods will now reject with an InvalidStateError.


Preview | Diff

Comment on lines 1404 to 1406
1. If |operand| is in [=this=]'s [=MLGraphBuilder/graph=]'s [=computational graph/inputs=], [=set/append=] |operand| to |inputs|.
1. [=list/For each=] |input| of |operand|.{{MLOperand/[[operator]]}}'s [=operator/inputs=]:
1. [=queue/Enqueue=] |input| to |queue|.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note: this PR does not address #567 (comment) since there didn't appear to be consensus on whether that was desirable (FYI @inexorabletash @fdwr). If folks have strong feelings in either direction then I propose we file a separate issue to discuss; otherwise I propose we leave this as-is for now. WDYT?

Copy link
Member

Choose a reason for hiding this comment

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

SGTM.

Copy link
Contributor

Choose a reason for hiding this comment

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

#567 (comment)

Agree it is a separate issue.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Even with this change, we can still AFAICS create a disconnected graph with a single graphBuilder, right? It's a legitimate graph construct.

image

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Correct 👍

@a-sully
Copy link
Contributor Author

a-sully commented Jul 10, 2024

@huningxin @fdwr PTAL?

index.bs Outdated Show resolved Hide resolved
index.bs Outdated Show resolved Hide resolved
Comment on lines 1404 to 1406
1. If |operand| is in [=this=]'s [=MLGraphBuilder/graph=]'s [=computational graph/inputs=], [=set/append=] |operand| to |inputs|.
1. [=list/For each=] |input| of |operand|.{{MLOperand/[[operator]]}}'s [=operator/inputs=]:
1. [=queue/Enqueue=] |input| to |queue|.
Copy link
Member

Choose a reason for hiding this comment

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

SGTM.

index.bs Show resolved Hide resolved
Copy link
Contributor

@huningxin huningxin left a comment

Choose a reason for hiding this comment

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

LGTM with a comment

Checked with @Honry that ORT WebNN EP currently doesn't share constant operands when building sub-graphs for a (merged) model.

index.bs Show resolved Hide resolved
Comment on lines 1404 to 1406
1. If |operand| is in [=this=]'s [=MLGraphBuilder/graph=]'s [=computational graph/inputs=], [=set/append=] |operand| to |inputs|.
1. [=list/For each=] |input| of |operand|.{{MLOperand/[[operator]]}}'s [=operator/inputs=]:
1. [=queue/Enqueue=] |input| to |queue|.
Copy link
Contributor

Choose a reason for hiding this comment

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

#567 (comment)

Agree it is a separate issue.

Comment on lines 1404 to 1406
1. If |operand| is in [=this=]'s [=MLGraphBuilder/graph=]'s [=computational graph/inputs=], [=set/append=] |operand| to |inputs|.
1. [=list/For each=] |input| of |operand|.{{MLOperand/[[operator]]}}'s [=operator/inputs=]:
1. [=queue/Enqueue=] |input| to |queue|.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Even with this change, we can still AFAICS create a disconnected graph with a single graphBuilder, right? It's a legitimate graph construct.

image

@@ -5966,6 +6027,8 @@ partial interface MLGraphBuilder {
<summary>
The <dfn method for=MLGraphBuilder>where(|condition|, |input|, |other|)</dfn> method steps are:
</summary>
1. If [=this=].{{MLGraphBuilder/[[hasBuilt]]}} is true, then [=exception/throw=] an "{{InvalidStateError}}" {{DOMException}}.
Copy link
Collaborator

Choose a reason for hiding this comment

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

🫤 Seeing "if hasBuilt is true then throw this kind of error" repeated in the logic of every single operator feels unclean. Can we have a common graph builder "operator initialization" function that they all call, and that error check can be the very first (and currently only) step in it, kinda like how we centralized casting and broadcasting functionality? Mind you, every single operator still then needs "1. Perform builder-operator-initialization", but it feels 🧼➕ imo. Opinion?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm I agree the current state is annoyingly duplicative, but I couldn't decide on a useful name of a helper method... This check is performed in MLGraphBuilder.build() as well all methods which mint an MLOperand. Calling a "builder-operator-initialization" algorithm from the build() steps is a bit odd (and nothing is being initialized anyways).

Lacking a good name, I figured inlining the one-liner would be more readable ¯\(ツ)

If you can think of a better name then I'm happy to change it :P

Copy link
Collaborator

@fdwr fdwr Jul 11, 2024

Choose a reason for hiding this comment

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

The pervasive naming challenge... Let me ponder a bit, after some sleep. 😴

Copy link
Member

Choose a reason for hiding this comment

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

Throwing out another idea: we could maybe use a Bikeshed text macro to reduce the burden on spec authors. We define one today for EMULATED to avoid repetition. This doesn't reduce the burden on spec readers, though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True, though we'd still have to name the macro :P

THROW_IF_BUILT?

Copy link
Collaborator

@fdwr fdwr Jul 16, 2024

Choose a reason for hiding this comment

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

THROW_IF_ALREADY_BUILT?
EnsureNotAlreadyBuilt?
...
No particularly bright insights came to me after sleep or over the weekend 😅. Going to merge now and maybe we'll think of something later...

Copy link
Collaborator

@fdwr fdwr left a comment

Choose a reason for hiding this comment

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

👍 The builder patterns I've seen generally let you create multiple objects from the same builder, but I see advantages to both, and it's easier to potentially relax this later if needed than to restrict it later.

@fdwr fdwr merged commit f08f9f7 into webmachinelearning:main Jul 16, 2024
2 checks passed
@a-sully a-sully deleted the build-once branch July 22, 2024 14:12
aarongable pushed a commit to chromium/chromium that referenced this pull request Jul 25, 2024
See webmachinelearning/webnn#717

Bug: 354724062
Change-Id: I8ac2bf94b1f5a0db93a042babdc2556eab35034a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5684454
Reviewed-by: Reilly Grant <reillyg@chromium.org>
Commit-Queue: Austin Sullivan <asully@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1332702}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this pull request Jul 25, 2024
See webmachinelearning/webnn#717

Bug: 354724062
Change-Id: I8ac2bf94b1f5a0db93a042babdc2556eab35034a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5684454
Reviewed-by: Reilly Grant <reillyg@chromium.org>
Commit-Queue: Austin Sullivan <asully@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1332702}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this pull request Jul 25, 2024
See webmachinelearning/webnn#717

Bug: 354724062
Change-Id: I8ac2bf94b1f5a0db93a042babdc2556eab35034a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5684454
Reviewed-by: Reilly Grant <reillyg@chromium.org>
Commit-Queue: Austin Sullivan <asully@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1332702}
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this pull request Jul 26, 2024
…at most one MLGraph, a=testonly

Automatic update from web-platform-tests
webnn: Allow an MLGraphBuilder to build at most one MLGraph

See webmachinelearning/webnn#717

Bug: 354724062
Change-Id: I8ac2bf94b1f5a0db93a042babdc2556eab35034a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5684454
Reviewed-by: Reilly Grant <reillyg@chromium.org>
Commit-Queue: Austin Sullivan <asully@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1332702}

--

wpt-commits: b7777fabd7363bb2e65a3a5da4538bcf0eedee9c
wpt-pr: 47285
i3roly pushed a commit to i3roly/firefox-dynasty that referenced this pull request Jul 26, 2024
…at most one MLGraph, a=testonly

Automatic update from web-platform-tests
webnn: Allow an MLGraphBuilder to build at most one MLGraph

See webmachinelearning/webnn#717

Bug: 354724062
Change-Id: I8ac2bf94b1f5a0db93a042babdc2556eab35034a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5684454
Reviewed-by: Reilly Grant <reillyg@chromium.org>
Commit-Queue: Austin Sullivan <asully@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1332702}

--

wpt-commits: b7777fabd7363bb2e65a3a5da4538bcf0eedee9c
wpt-pr: 47285
ErichDonGubler pushed a commit to erichdongubler-mozilla/firefox that referenced this pull request Jul 27, 2024
…at most one MLGraph, a=testonly

Automatic update from web-platform-tests
webnn: Allow an MLGraphBuilder to build at most one MLGraph

See webmachinelearning/webnn#717

Bug: 354724062
Change-Id: I8ac2bf94b1f5a0db93a042babdc2556eab35034a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5684454
Reviewed-by: Reilly Grant <reillyg@chromium.org>
Commit-Queue: Austin Sullivan <asully@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1332702}

--

wpt-commits: b7777fabd7363bb2e65a3a5da4538bcf0eedee9c
wpt-pr: 47285
fdwr pushed a commit to microsoft/onnxruntime that referenced this pull request Aug 1, 2024
Currently WebNN spec only allows MLGraphBuilder.build() to be called
once, we need to create new builder for every subgraph in WebNN EP.

Spec change: webmachinelearning/webnn#717
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.

Can an MLGraphBuilder be reused?
4 participants