Skip to content

Commit 05fba84

Browse files
committed
Allow tensors for graph constants.
As noted in the issue, sharing weights between graphs is a effective way to enable reuse of device buffers, allowing web developers to manage weight data in graphs similarly to other input or output buffers. Resolves #760
1 parent 69bb88d commit 05fba84

File tree

1 file changed

+146
-0
lines changed

1 file changed

+146
-0
lines changed

index.bs

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,7 @@ interface MLContext {
869869
undefined dispatch(MLGraph graph, MLNamedTensors inputs, MLNamedTensors outputs);
870870

871871
Promise<MLTensor> createTensor(MLTensorDescriptor descriptor);
872+
Promise<MLConstantTensor> createConstantTensor(MLOperandDescriptor descriptor, AllowSharedBufferSource inputData);
872873

873874
Promise<ArrayBuffer> readTensor(MLTensor tensor);
874875
Promise<undefined> readTensor(MLTensor tensor, AllowSharedBufferSource outputData);
@@ -941,6 +942,7 @@ The <dfn>context type</dfn> is the type of the execution context that manages th
941942
1. [=map/For each=] |name| → |tensor| of |namedTensors|:
942943
1. If |namedDescriptors|[|name|] does not [=map/exist=], then return false.
943944
1. If |tensor|.{{MLTensor/[[descriptor]]}} is not [=MLOperandDescriptor/equal=] to |namedDescriptors|[|name|], then return false.
945+
1. If |tensor| is a {{MLConstantTensor}} then return false.
944946
1. Return true.
945947
</details>
946948

@@ -1065,6 +1067,41 @@ Creates an {{MLTensor}} associated with this {{MLContext}}.
10651067
1. Return |promise|.
10661068
</details>
10671069

1070+
### {{MLContext/createConstantTensor()}} ### {#api-mlcontext-createconstanttensor}
1071+
1072+
Creates an {{MLConstantTensor}} associated with this {{MLContext}}.
1073+
1074+
<div dfn-for="MLContext/createConstantTensor(descriptor, inputData)" dfn-type=argument>
1075+
**Arguments:**
1076+
- <dfn>descriptor</dfn>: an {{MLOperandDescriptor}}.
1077+
- <dfn>inputData</dfn>: an {{AllowSharedBufferSource}}. The buffer whose bytes will be written into the tensor.
1078+
1079+
**Returns:** {{Promise}}<{{MLConstantTensor}}>.
1080+
</div>
1081+
1082+
<details open algorithm>
1083+
<summary>
1084+
The <dfn method for=MLContext>createConstantTensor(|descriptor|, |inputData|)</dfn> method steps are:
1085+
</summary>
1086+
1. Let |global| be [=this=]'s [=relevant global object=].
1087+
1. Let |realm| be [=this=]'s [=relevant realm=].
1088+
1. If [=this=] [=MLContext/is lost=], then return [=a new promise=] in |realm| [=rejected=] with an "{{InvalidStateError}}" {{DOMException}}.
1089+
1. If [=MLOperandDescriptor/checking dimensions=] given |descriptor| returns false, then [=exception/throw=] a {{TypeError}}.
1090+
1. If [=validating buffer with descriptor=] given |inputData| and |descriptor| returns false, then return [=a new promise=] in |realm| [=rejected=] with a {{TypeError}}.
1091+
1. Let |bytes| be the result of [=getting a copy of the bytes held by the buffer source=] given |inputData|.
1092+
1. [=Assert=]: |bytes|'s [=byte sequence/length=] is equal to |descriptor|'s [=MLOperandDescriptor/byte length=].
1093+
1. Let |tensor| be the result of [=creating an MLConstantTensor=] given [=this=], and |descriptor|.
1094+
1. Let |promise| be [=a new promise=] in |realm|.
1095+
1. Enqueue the following steps to [=this=].{{MLContext/[[timeline]]}}:
1096+
1. Run these steps, but [=/abort when=] [=this=] [=MLContext/is lost=]:
1097+
1. Create |tensor|.{{MLConstantTensor/[[data]]}} given |descriptor| and initialize all bytes to zeros.
1098+
1. Copy |bytes| to |tensor|.{{MLConstantTensor/[[data]]}}.
1099+
1. If that fails, then [=queue an ML task=] with |global| to [=reject=] |promise| with an "{{UnknownError}}" {{DOMException}}, and abort these steps.
1100+
1. Otherwise, [=queue an ML task=] with |global| to [=resolve=] |promise| with |tensor|.
1101+
1. [=/If aborted=], then [=queue an ML task=] with |global| to [=reject=] |promise| with an "{{InvalidStateError}}" {{DOMException}}.
1102+
1. Return |promise|.
1103+
</details>
1104+
10681105
### {{MLContext/readTensor(tensor)}} ### {#api-mlcontext-readtensor}
10691106

10701107
Reads back the {{MLTensor/[[data]]}} of an {{MLTensor}} from the {{MLContext}}.{{MLContext/[[timeline]]}} to script.
@@ -1627,6 +1664,90 @@ Releases the resources associated with the {{MLTensor}}. This method is idempote
16271664

16281665
Note: Since no further operations can be enqueued using this tensor, implementations can free any additional resource allocations associated with this tensor once all previously submitted operations using it are complete.
16291666

1667+
## {{MLConstantTensor}} interface ## {#api-mlconstanttensor}
1668+
1669+
The {{MLConstantTensor}} interface represents a tensor which may be used as a constant to an {{MLGraph}}. The memory backing an {{MLConstantTensor}} should be allocated in an [=implementation-defined=] fashion according to the requirements of the {{MLContext}} and the {{MLOperandDescriptor}} used to create it. Operations involving the {{MLConstantTensor/[[data]]}} of an {{MLConstantTensor}} occur on the {{MLContext/[[timeline]]}} of its associated {{MLContext}}.
1670+
1671+
The [=implementation-defined=] requirements of how an {{MLConstantTensor}} is allocated may include constraints such as that the memory is allocated with a particular byte alignment or in a particular memory pool.
1672+
1673+
<script type=idl>
1674+
[SecureContext, Exposed=(Window, Worker)]
1675+
interface MLConstantTensor : MLTensor {
1676+
};
1677+
</script>
1678+
1679+
<div class=internal-slots>
1680+
{{MLConstantTensor}} has the following internal slots:
1681+
<dl dfn-type=attribute dfn-for="MLConstantTensor">
1682+
: <dfn>\[[context]]</dfn> of type {{MLContext}}
1683+
::
1684+
The {{MLConstantTensor}}'s associated context.
1685+
1686+
: <dfn>\[[descriptor]]</dfn> of type {{MLOperandDescriptor}}
1687+
::
1688+
The {{MLConstantTensor}}'s descriptor.
1689+
1690+
: <dfn>\[[isDestroyed]]</dfn> of type {{boolean}}
1691+
::
1692+
Whether the {{MLConstantTensor}}.{{MLConstantTensor/destroy()}} steps have been run. Once destroyed, the {{MLConstantTensor}} can no longer be used.
1693+
1694+
: <dfn>\[[data]]</dfn> of an [=implementation-defined=] type
1695+
::
1696+
The bytes backing the {{MLConstantTensor}}. This data may only be accessed or modified from the {{MLConstantTensor/[[context]]}}.{{MLContext/[[timeline]]}}.
1697+
</dl>
1698+
</div>
1699+
1700+
An {{MLConstantTensor}}'s <dfn for=MLConstantTensor>dataType</dfn> is its {{MLConstantTensor/[[descriptor]]}}'s {{MLOperandDescriptor/dataType}}.
1701+
1702+
An {{MLConstantTensor}}'s <dfn for=MLConstantTensor>shape</dfn> is its {{MLConstantTensor/[[descriptor]]}}'s {{MLOperandDescriptor/shape}}.
1703+
1704+
The <dfn attribute for=MLConstantTensor>dataType</dfn> [=getter steps=] are to return [=this=]'s [=MLConstantTensor/dataType=].
1705+
1706+
The <dfn attribute for=MLConstantTensor>shape</dfn> [=getter steps=] are to return [=this=]'s [=MLConstantTensor/shape=].
1707+
1708+
The <dfn attribute for=MLConstantTensor>readable</dfn> [=getter steps=] are to return true.
1709+
1710+
The <dfn attribute for=MLConstantTensor>writable</dfn> [=getter steps=] are to return false.
1711+
1712+
### Creating an {{MLConstantTensor}} ### {#api-mlconstanttensor-create}
1713+
1714+
An {{MLConstantTensor}} is created by its associated {{MLContext}}.
1715+
1716+
<details open algorithm>
1717+
<summary>
1718+
To <dfn>create an MLConstantTensor</dfn> given {{MLContext}} |context|, {{MLOperandDescriptor}} |descriptor|, and {{AllowSharedBufferSource}} |inputData|, run the following steps:
1719+
</summary>
1720+
1. Let |realm| be |context|'s [=relevant realm=].
1721+
1. Let |tensor| be a new {{MLConstantTensor}} in |realm|.
1722+
1. Set |tensor|.{{MLConstantTensor/[[context]]}} to |context|.
1723+
1. Set |tensor|.{{MLConstantTensor/[[descriptor]]}} to |descriptor|.
1724+
1. Set |tensor|.{{MLConstantTensor/[[data]]}} to |inputData|.
1725+
1. Set |tensor|.{{MLConstantTensor/[[isDestroyed]]}} to false.
1726+
1. Set |tensor|.{{MLConstantTensor/[[descriptor]]}}.{{MLTensorDescriptor/readable}} to true.
1727+
1. Set |tensor|.{{MLConstantTensor/[[descriptor]]}}.{{MLTensorDescriptor/writable}} to false.
1728+
1. Return |tensor|.
1729+
</details>
1730+
1731+
### {{MLConstantTensor/destroy()}} ### {#api-mlconstanttensor-destroy}
1732+
1733+
Releases the resources associated with the {{MLConstantTensor}}. This method is idempotent.
1734+
1735+
<div dfn-for="MLConstantTensor/destroy()" dfn-type=argument>
1736+
**Returns:** {{undefined}}.
1737+
</div>
1738+
1739+
<details open algorithm>
1740+
<summary>
1741+
The <dfn method for=MLConstantTensor>destroy()</dfn> method steps are:
1742+
</summary>
1743+
1. Set [=this=].{{MLConstantTensor/[[isDestroyed]]}} to true.
1744+
1. Enqueue the following steps to [=this=].{{MLConstantTensor/[[context]]}}.{{MLContext/[[timeline]]}}:
1745+
1. Release [=this=].{{MLConstantTensor/[[data]]}}.
1746+
1. Return {{undefined}}.
1747+
</details>
1748+
1749+
Note: Since no further operations can be enqueued using this tensor, implementations can free any additional resource allocations associated with this tensor once all previously submitted operations using it are complete.
1750+
16301751
## {{MLGraphBuilder}} interface ## {#api-mlgraphbuilder}
16311752

16321753
The {{MLGraphBuilder}} interface defines a set of operations as identified by the [[#usecases]] that can be composed into a computational graph. It also represents the intermediate state of a graph building session.
@@ -1649,6 +1770,9 @@ interface MLGraphBuilder {
16491770
// Create a scalar operand from the specified number of the specified type.
16501771
MLOperand constant(MLOperandDataType type, MLNumber value);
16511772

1773+
// Create an operand from a specified tensor.
1774+
MLOperand constant(MLConstantTensor tensor);
1775+
16521776
// Compile the graph up to the specified output operands asynchronously.
16531777
Promise<MLGraph> build(MLNamedOperands outputs);
16541778
};
@@ -1749,6 +1873,28 @@ Create a constant {{MLOperand}} of the specified data type and shape that contai
17491873
1. Return |operand|.
17501874
</details>
17511875

1876+
#### {{MLGraphBuilder/constant(tensor)}} #### {#api-mlgraphbuilder-constant-tensor}
1877+
Create a constant {{MLOperand}} of the specified data type and shape that contains the initialized data.
1878+
1879+
<div dfn-for="MLGraphBuilder/constant(tensor)" dfn-type=argument>
1880+
**Arguments:**
1881+
- <dfn>tensor</dfn>: an {{MLConstantTensor}}. The tensor containing the initialized data.
1882+
**Returns:** an {{MLOperand}}. The constant output tensor.
1883+
</div>
1884+
1885+
<details open algorithm>
1886+
<summary>
1887+
The <dfn method for=MLGraphBuilder>constant(|tensor|)</dfn> method steps are:
1888+
</summary>
1889+
1. If |tensor|.{{MLConstantTensor/[[context]]}} is not [=this=], then [=exception/throw=] a {{TypeError}}.
1890+
1. If |tensor|.{{MLConstantTensor/[[isDestroyed]]}} is true, then [=exception/throw=] a {{TypeError}}.
1891+
1. If [=this=] [=MLGraphBuilder/can not build=], then [=exception/throw=] an "{{InvalidStateError}}" {{DOMException}}.
1892+
1. *Make graph connections:*
1893+
1. Let |operand| be the result of [=creating an MLOperand=] given [=this=] and |tensor|.{{MLConstantTensor/[[descriptor]]}}.
1894+
1. Add |operand| to [=this=]'s [=MLGraphBuilder/graph=]'s [=computational graph/constants=] with |tensor| as value.
1895+
1. Return |operand|.
1896+
</details>
1897+
17521898
#### {{MLGraphBuilder/constant(type, value)}} #### {#api-mlgraphbuilder-constant-type-value}
17531899
Create a scalar constant {{MLOperand}} of the specified value and data type.
17541900

0 commit comments

Comments
 (0)