diff --git a/doc/sphinx/ngraph_theme/static/css/theme.css b/doc/sphinx/ngraph_theme/static/css/theme.css
index 3c4cb1f1c9d..ab4bc961415 100644
--- a/doc/sphinx/ngraph_theme/static/css/theme.css
+++ b/doc/sphinx/ngraph_theme/static/css/theme.css
@@ -49,24 +49,19 @@ div.menu-float {
text-align: center;
background: #393F4D;
opacity: 0.9717;
- /* margin-left: 55%; */
- /* margin-right: 3%; */
padding: 3px;
border-top: 1px solid #999999;
border-left: 1px solid #999999;
border-right: 1px solid #999999;
margin-top: -2px;
margin-left: -2px;
- /* -moz-box-shadow: 2px 3px 2px #d3d3d3; */
- /* -webkit-box-shadow: 2px 3px 2px #d3d3d3 */
- /* box-shadow: 3px 4px 3px #d3d3d3; */
-webkit-border-radius: 0.1px;
-moz-border-radius: 0.1px;
border-radius: 0.1px;
z-index:1000;
}
-div.menu-float a, div.floating-menu h3 {display:inline-block; margin:0 0.5em; font-size: 143%; line-height: 1.41em; color: #fcfcfc; }
+div.menu-float a, div.floating-menu h3 {display:inline-block; margin:0 0.5em; font-size: 133%; line-height: 1.31em; color: #fcfcfc; }
#nav {
@@ -1535,7 +1530,7 @@ a:hover {
}
a:visited {
- color: #FFA400;
+ color: #DC700D;
}
html {
@@ -1644,7 +1639,6 @@ h1 {
h2 {
font-size: 133%;
- text-decoration: underline 4px dotted #D3D3D3;
margin-top: -2px;
}
@@ -1761,7 +1755,7 @@ div[class^='highlight'] td.code {
.wy-menu-vertical p.caption {
font-family: Nunito, 'Nunito Sans', Helvetica, 'Helvetica Neue', sans;
- text-decoration: underline 2px #393F4D;
+ /* text-decoration: underline 2px #393F4D; */
font-size: 110%;
color: #23221d;
background-color: #FAFBFD;
@@ -2215,6 +2209,10 @@ div[class^='highlight'] pre {
padding: 6px;
color: #FDC939;
}
+.rst-other-versions a:hover {
+ color: #555;
+ background-color: #e0e0e0;
+}
.rst-versions.rst-badge {
width: auto;
bottom: 20px;
@@ -2430,7 +2428,6 @@ div[class^='highlight'] pre {
.rst-content tt.literal, .rst-content tt.literal, .rst-content code.literal {
font-size: 91% !important;
color: #152a58;
- text-decoration: underline 2px dotted #cdcac5;
background-color: #fff;
line-height: 0.8955em;
}
@@ -2666,7 +2663,7 @@ span[id*='MathJax-Span'] {
font-family: 'Nunito Sans', Nunito, Helvetica, 'Helvetica Neue', sans;
font-weight: bolder;
border-top: 5px dotted #FFA400;
- border-bottom: 29px solid #d3d3d3;
+ border-bottom: 28px solid #d3d3d3;
font-size: 131%;
color: #393F4D;
width: auto;
@@ -2816,15 +2813,12 @@ span[id*='MathJax-Span'] {
}
.wy-menu-vertical a:hover {
background-color: #fafbfd;
- text-decoration: underline 1.33em dotted;
- cursor: pointer;
}
.wy-menu-vertical a:hover span.toctree-expand {
color: #e8e8e8;
}
.wy-menu-vertical a:active {
background-color: #FAFBFD;
- cursor: pointer;
color: #555;
}
.wy-menu-vertical a:active span.toctree-expand {
diff --git a/doc/sphinx/source/backends/index.rst b/doc/sphinx/source/backends/index.rst
index c07988f389c..d4472f9c857 100644
--- a/doc/sphinx/source/backends/index.rst
+++ b/doc/sphinx/source/backends/index.rst
@@ -51,7 +51,7 @@ How to use?
#. A single iteration of the executable is executed by calling the ``call``
method on the ``Executable`` object.
-.. figure:: ../graphics/ExecutionInterfaceRunGraphs.png
+.. figure:: ../graphics/execution-interface-run-graph.svg
:width: 650px
The execution interface for nGraph
diff --git a/doc/sphinx/source/buildlb.rst b/doc/sphinx/source/buildlb.rst
index 6e89c65d6e1..8f4eeca9fa5 100644
--- a/doc/sphinx/source/buildlb.rst
+++ b/doc/sphinx/source/buildlb.rst
@@ -106,7 +106,7 @@ The process documented here will work on Ubuntu\* 16.04 (LTS) or on Ubuntu
.. code-block:: console
- $ cmake .. [-DNGRAPH_USE_PREBUILT_LLVM=OFF] [-DNGRAPH_TARGET_ARCH=skylake-avx512]
+ $ cmake .. [-DNGRAPH_TARGET_ARCH=skylake-avx512]
#. Run ``$ make`` and ``make install`` to install ``libngraph.so`` and the
header files to ``~/ngraph_dist``:
diff --git a/doc/sphinx/source/core/constructing-graphs/distribute-train.rst b/doc/sphinx/source/core/constructing-graphs/distribute-train.rst
index 96d6dc0fdb2..4f6f0fd57ac 100644
--- a/doc/sphinx/source/core/constructing-graphs/distribute-train.rst
+++ b/doc/sphinx/source/core/constructing-graphs/distribute-train.rst
@@ -33,7 +33,7 @@ Finally, to run the training using two nGraph devices, invoke
.. code-block:: console
- $ mpirun
+ mpirun
To deploy data-parallel training, the ``AllReduce`` op should be added after the
steps needed to complete the :doc:`backpropagation <../constructing-graphs/derive-for-training>`;
@@ -48,7 +48,7 @@ See the `full code`_ in the ``examples`` folder ``/doc/examples/mnist_mlp/dist_m
.. code-block:: console
- $ mpirun -np 2 dist_mnist_mlp
+ mpirun -np 2 dist_mnist_mlp
.. _Intel MLSL: https://github.com/intel/MLSL/releases
diff --git a/doc/sphinx/source/core/constructing-graphs/execute.rst b/doc/sphinx/source/core/constructing-graphs/execute.rst
index a53cb6bacbf..491c215218b 100644
--- a/doc/sphinx/source/core/constructing-graphs/execute.rst
+++ b/doc/sphinx/source/core/constructing-graphs/execute.rst
@@ -5,17 +5,40 @@ Execute a computation
######################
This section explains how to manually perform the steps that would normally be
-performed by a framework :term:`bridge` to execute a computation. The nGraph
-library is targeted toward automatic construction; it is far easier for a
-processing unit (GPU, CPU, or an `Intel Nervana NNP`_) to run a computation than
-it is for a human to map out how that computation happens. Unfortunately, things
+performed by a framework :term:`bridge` to execute a computation. nGraph graphs
+are targeted toward automatic construction; it is far easier for a processor
+(a CPU, GPU, or `purpose-built silicon`_) to execute a computation than it is
+for a human to map out how that computation happens. Unfortunately, things
that make by-hand graph construction simpler tend to make automatic construction
more difficult, and vice versa.
-Here we will do all the bridge steps manually. The :term:`model description`
-walk-through below is based on the :file:`abc.cpp` code in the ``/doc/examples/``
-directory. We'll be deconstructing the steps that must happen (either programmatically
-or manually) in order to successfully execute a computation:
+Nevertheless, it can be helpful to break down what is happening during graph
+construction. The documetation that follows explains two approaches frameworks
+can use to compile with nGraph operations:
+
+* :ref:`Using complete shapes `
+* :ref:`Using partial shapes `
+
+The nGraph :abbr:`Intermediate Representation (IR)` uses a strong, dynamic
+type system, including static shapes. This means that at compilation, every
+tensor (or, equivalently, every node output) in the graph is assigned
+**complete shape information**; that is, one and only one shape. The static
+process by which this assignment takes place is called :term:`shape propagation`.
+
+In the :ref:`first scenario `, the :term:`model description`
+walk-through is based on the :file:`abc.cpp` code in the ``/doc/examples/abc``
+directory, and it deconstructs the steps that must happen (either programmatically
+or manually) in order to successfully execute a computation given complete
+shape information.
+
+.. _scenario_one:
+
+Scenario One: Using Complete Shapes
+===================================
+
+A step-by-step example of how a framework might execute with complete shape
+information is provided here. For a step-by-step example using dynamic
+shapes, see :ref:`scenario_two`.
* :ref:`define_cmp`
* :ref:`specify_backend`
@@ -25,13 +48,11 @@ or manually) in order to successfully execute a computation:
* :ref:`invoke_cmp`
* :ref:`access_outputs`
-The full code is at the :ref:`end of this page `.
-
.. _define_cmp:
Define the computation
-======================
+----------------------
To a :term:`framework`, a computation is simply a transformation of inputs to
outputs. While a :term:`bridge` can programmatically construct the graph
@@ -111,10 +132,10 @@ function, in the order they are to be passed to the compiled function. A
.. _specify_backend:
Specify the backend upon which to run the computation
-=====================================================
+-----------------------------------------------------
For a framework bridge, a *backend* is the environment that can perform the
-computations; it can be done with a CPU, GPU, or an Intel Nervana NNP. A
+computations; it can be done with a CPU, GPU, or `purpose-built silicon`_. A
*transformer* can compile computations for a backend, allocate and deallocate
tensors, and invoke computations.
@@ -123,7 +144,7 @@ and allocate backends. A backend is somewhat analogous to a multi-threaded
process.
There are two backends for the CPU: the optimized ``"CPU"`` backend, which uses
-the `Intel MKL-DNN`_, and the ``"INTERPRETER"`` backend, which runs reference
+the `DNNL`_, and the ``"INTERPRETER"`` backend, which runs reference
versions of kernels that favor implementation clarity over speed. The
``"INTERPRETER"`` backend can be slow, and is primarily intended for testing.
See the documentation on :doc:`runtime options for various backends <../../backends/index>`
@@ -139,7 +160,7 @@ To continue with our original example and select the ``"CPU_Backend"``:
.. _compile_cmp:
Compile the computation
-=======================
+-----------------------
Compilation triggers something that can be used as a factory for producing a
``CallFrame`` which is a *function* and its associated *state* that can run
@@ -152,7 +173,7 @@ thread needs to execute the function at the same time, create multiple
.. _allocate_backend_storage:
Allocate backend storage for the inputs and outputs
-===================================================
+---------------------------------------------------
At the graph level, functions are stateless. They do have internal state related
to execution, but there is no user-visible state. Variables must be passed as
@@ -182,7 +203,7 @@ with ``Tensor``.
.. _initialize_inputs:
Initialize the inputs
-=====================
+---------------------
Next we need to copy some data into the tensors.
@@ -196,7 +217,7 @@ copying data to/from the tensor.
.. _invoke_cmp:
Invoke the computation
-======================
+----------------------
To invoke the function, we simply pass argument and resultant tensors to the
call frame:
@@ -209,7 +230,7 @@ call frame:
.. _access_outputs:
Access the outputs
-==================
+------------------
We can use the ``read`` method to access the result:
@@ -217,10 +238,10 @@ We can use the ``read`` method to access the result:
:language: cpp
:lines: 60-77
-.. _all_together:
+.. _sshp:
-Put it all together
-===================
+Compiling with Complete Shape Information
+-----------------------------------------
.. literalinclude:: ../../../../examples/abc/abc.cpp
:language: cpp
@@ -228,7 +249,96 @@ Put it all together
:caption: "The (a + b) * c example for executing a computation on nGraph"
+.. _scenario_two:
+
+Scenario Two: Known Partial Shape
+=================================
+
+The :ref:`second scenario ` involves the use of dynamic tensors.
+A :term:`dynamic tensor` is a tensor whose shape can change from one "iteration"
+to the next. When a dynamic tensor is created, a framework :term:`bridge` might
+supply only *partial* shape information: it might be **all** the tensor
+dimensions, **some** of the tensor dimensions, or **none** of the tensor
+dimensions; furthermore, the rank of the tensor may be left unspecified.
+The "actual" shape of the tensor is not specified until some function writes
+some value to it. The actual shape can change when the value of the tensor
+is overwritten. It is the backend’s responsibility to set the actual shape.
+The :term:`model description` for the second scenario based on the
+:file:`partial_shape.cpp` code in the ``/doc/examples/dynamic_tensor``
+directory, and it deconstructs the steps that must happen (either
+programmatically or manually) in order to successfully retreive shape data.
+
+* :ref:`create_dyn_tensor`
+* :ref:`call_graph_vw_`
+* :ref:`call_graph_vwnew`
+* :ref:`kpsh`
+
+
+Create and compile a graph for ``f(x) = x + x`` where the provided info
+of shape ``x`` is ``(2,?)``:
+
+.. literalinclude:: ../../../../examples/dynamic_tensor/partial_shape.cpp
+ :language: cpp
+ :lines: 27-32
+
+
+.. _create_dyn_tensor:
+
+Create a dynamic tensor
+-----------------------
+
+Create a dynamic tensor of shape ``(2,?)``
+
+.. literalinclude:: ../../../../examples/dynamic_tensor/partial_shape.cpp
+ :language: cpp
+ :lines: 35
+
+At this point, ``t_out->get_shape()`` would throw an exception, while
+``t_out->get_partial_shape()`` would return ``"(2,?)"``.
+
+
+.. _call_graph_vw_:
+
+Write shape
+-----------
+
+Call the graph to write a value with shape (2,3) to t_out
+
+.. literalinclude:: ../../../../examples/dynamic_tensor/partial_shape.cpp
+ :language: cpp
+ :lines: 38-40
+
+At this point, ``t_out->get_shape()`` would return ``Shape{2,3}``,
+while ``t_out->get_partial_shape()`` would return ``"(2,?)"``.
+
+
+.. _call_graph_vwnew:
+
+Write new shape
+---------------
+
+Call the graph again, to write a value with a different shape to ``t_out``.
+
+.. literalinclude:: ../../../../examples/dynamic_tensor/partial_shape.cpp
+ :language: cpp
+ :lines: 44-45
+
+At this point, ``t_out->get_shape()`` would return ``Shape{2,20}``,
+while ``t_out->get_partial_shape()`` would return ``"(2,?)"``.
+
+
+.. _kpsh:
+
+Compiling with Known Partial Shape
+----------------------------------
+
+.. literalinclude:: ../../../../examples/dynamic_tensor/partial_shape.cpp
+ :language: cpp
+ :linenos:
+ :caption: "Full code for compiling with dynamic tensors and partial shape"
+
+
+.. _purpose-built silicon: https://www.intel.ai/nervana-nnp
+.. _DNNL: https://intel.github.io/mkl-dnn/
-.. _Intel MKL-DNN: https://01.org/mkl-dnn
-.. _Intel Nervana NNP: https://ai.intel.com/intel-nervana-neural-network-processors-nnp-redefine-ai-silicon/
diff --git a/doc/sphinx/source/core/constructing-graphs/index.rst b/doc/sphinx/source/core/constructing-graphs/index.rst
index 16a90ecd40c..e618dc8e0b5 100644
--- a/doc/sphinx/source/core/constructing-graphs/index.rst
+++ b/doc/sphinx/source/core/constructing-graphs/index.rst
@@ -30,34 +30,5 @@ resources, it can either:
.. note:: This section is aimed at intermediate-level developers. It assumes an
understanding of the concepts in the previous sections. It does not assume
- knowledge of any particular frontend framework.
-
-Since our primary audience is developers who are pushing the boundaries of deep
-learning systems, we go beyond the use of deep learning primitives, and include
-APIs and documentation for developers who want the ability to write programs
-that use custom backends. For example, we know that GPU resources can be useful
-backends for *some* kinds of algorithmic operations while they impose inherent
-limitations or slow down others.
-
-One of our goals with the nGraph library is to enable developers with tools to
-quickly build programs that access and process data from a breadth of edge and
-networked devices. This might mean bringing compute resources closer to edge
-devices, or it might mean programatically adjusting a model or the compute
-resources it requires, at an unknown or arbitrary time after it has been deemed
-to be trained well enough.
-
-To get started, we've provided a basic example for how to :doc:`execute` a
-computation that can run on an nGraph backend; this is analogous to a
-framework bridge. We also provide a larger example for training and
-evaluating a simple MNIST MLP model.
-
-For data scientists or algorithm developers who are trying to extract specifics
-about the state of a model at a certain node, or who want to optimize a model
-at a more granular level, we provide an example for how to :doc:`import` and
-run inference after it has been exported from a DL framework.
-
-This section is under development; we'll continually populate it with more
-articles geared toward data scientists, algorithm designers, framework developers,
-backend engineers, and others. We welcome ideas and contributions from the
-community.
+ knowledge of any particular frontend framework.
diff --git a/doc/sphinx/source/core/overview.rst b/doc/sphinx/source/core/overview.rst
index e873ccbb036..5c04219f803 100644
--- a/doc/sphinx/source/core/overview.rst
+++ b/doc/sphinx/source/core/overview.rst
@@ -1,7 +1,7 @@
.. core/overview.rst:
-Basic concepts
+Basic Concepts
==============
.. figure:: ../graphics/nGraphCompilerstack.png
diff --git a/doc/sphinx/source/core/passes/passes.rst b/doc/sphinx/source/core/passes/passes.rst
index 0658c70bd6b..d9b591d3cad 100644
--- a/doc/sphinx/source/core/passes/passes.rst
+++ b/doc/sphinx/source/core/passes/passes.rst
@@ -62,7 +62,7 @@ hardware-specific primitives; here they get matched via Intel® MKL-DNN.
.. _figure-simple-compiler:
-.. figure:: ../../graphics/simple-compiler-passes.png
+.. figure:: ../../graphics/simple-compiler-passes.svg
:width: 750px
:alt: Simple kernel fusion
diff --git a/doc/sphinx/source/core/quantization.rst b/doc/sphinx/source/core/quantization.rst
new file mode 100644
index 00000000000..51bb7432a55
--- /dev/null
+++ b/doc/sphinx/source/core/quantization.rst
@@ -0,0 +1,169 @@
+.. core/quantization.rst:
+
+
+.. _quantization:
+
+Quantization
+============
+
+:term:`Quantization` refers the process of reducing the number of bits that
+represent a number. In a :abbr:`DL (Deep Learning)` context, weights and
+activations can be represented using 8-bit integers (INT8) to compress the
+model size of a trained neural network without any significant loss in model
+accuracy. INT8 is one kind of quantization. Compared with 32-bit floating point
+(FP32), using arithmetic with lower precision, such as INT8, to calculate
+weights and activation requires less memory.
+
+
+Implementing a quantized model with nGraph
+------------------------------------------
+
+To implement a quantized model with nGraph, provide a partially (or fully)
+quantized model (where the convolution layer in the model is replaced
+with a quantized convolution, for example) to the nGraph Library along with
+quantized parameters: weights, activations, scale, and zero point.
+
+.. note:: As of version |version|, only quantization for inference is supported.
+
+nGraph Quantized Operators (Ops)
+--------------------------------
+
+nGraph uses scale and zero point (also used by ONNX) to map real values to
+quantized values. All quantized ops use scale and zero point
+and can be used just like any other nGraph op.
+
+**Scale**: the quantization scale of the tensor
+
+**Zero point**: the zero point of the tensor
+
+**Round mode**: used in combination with scale and zero point to round real
+values to quantized values
+
+.. table:: Quantization Ops
+
+
+ +-----------------------------------------------------------------+------------------------------------------------+
+ | Op | Description |
+ +=================================================================+================================================+
+ | :doc:`Quantize <../ops/quantize>` | Maps real values (r) to quantized values (q) |
+ | | using scale (s), zero point (z), |
+ | | and round mode; produces a quantized tensor. |
+ +-----------------------------------------------------------------+------------------------------------------------+
+ | :doc:`Dequantize <../ops/dequantize>` | Maps quantized values (q) to real values (r) |
+ | | using scale (s) and zero point (z); converts |
+ | | a quantized tensor to a floating-point tensor. |
+ +-----------------------------------------------------------------+------------------------------------------------+
+ | :mod:`FakeQuantize ` | Performs element-wise linear quantization. |
+ +-----------------------------------------------------------------+------------------------------------------------+
+ | :mod:`QuantizedConvolution ` | Performs 8-bit convolution. |
+ +-----------------------------------------------------------------+------------------------------------------------+
+ | :mod:`QuantizedDot ` | Performs 8-bit dot. |
+ +-----------------------------------------------------------------+------------------------------------------------+
+
+Some frameworks such as TensorFlow\* have fused ops. nGraph provides optional
+operations to help users easily translate (map) any quantized model created from
+frameworks with fused ops to nGraph. Unlike builders, experimental ops take
+scale and zero point instead of min and max.
+
+.. table:: Experimental Quantized Ops (optional)
+
+
+ +-----------------------------------+-------------------------------------+
+ | Operator | Description |
+ +===================================+=====================================+
+ | QuantizedConvolutionBias | This experimental op can be |
+ | | fused with a ReLU op. |
+ +-----------------------------------+-------------------------------------+
+ | QuantizedConvolutionBiasAdd | This experimental op constructs a |
+ | | quantized convolution with bias and |
+ | | optional ReLU. And then takes input |
+ | | for the add operation. |
+ +-----------------------------------+-------------------------------------+
+ | QuantizedConvolutionBiasSignedAdd | Same as QuantizedConvolutionBiasAdd |
+ | | but with signed add. |
+ +-----------------------------------+-------------------------------------+
+ | QuantizedConvolutionRelu | This experimental op is designed |
+ | | for a particular use case that |
+ | | would require convolution |
+ | | and ReLU to be combined. |
+ +-----------------------------------+-------------------------------------+
+ | QuantizedDotBias | This experimental op can be fused |
+ | | with a ReLU op. |
+ +-----------------------------------+-------------------------------------+
+
+nGraph Quantization Design
+--------------------------
+
+The goal of nGraph quantization is to flexibly support a wide variety of
+frameworks and users. The use of scale and zero point as well as quantized
+builders in the nGraph design helps to achieve this goal.
+
+Scale and Zero Point
+~~~~~~~~~~~~~~~~~~~~
+
+Using scale and zero point allows nGraph to be framework agnostic (i.e., it
+can equally support all deep learning frameworks). nGraph Bridges will
+automatically convert min and max (provided by a DL framework) to scale and zero
+point as needed. Quantized builders are available to help the bridges perform
+this calculation. However, if users are directly using nGraph (and not using a
+bridge), they are required to provide scale and zero point for quantized ops.
+
+Another advantage of using scale and zero point to express quantization
+parameters is that users can flexibly implement quantized ops into various
+nGraph backends. When implementing quantized ops, all current nGraph backends
+will directly use scale and zero point (and not min and max) to perform
+the quantized computation.
+
+Quantized Builders
+~~~~~~~~~~~~~~~~~~
+
+Quantized builders are helper utilities to assist framework integrators to
+enable quantized models with nGraph. They serve as an API (interface) between
+framework bridges and nGraph, allowing framework bridges to directly construct
+ops in the nGraph Abstraction Layer.
+
+Quantized builders help nGraph framework bridges by:
+
+* Breaking down a fused quantized operator in the framework to a subgraph (of
+ quantized and non-quantized operators) in the nGraph core IR
+
+* Converting from min and max to scale and zero point based on the quantization
+ mode described by the DL framework
+
+.. note:: Fused ops and quantized builders serve the same purpose.
+ In the future, fused ops will replace quantized builders.
+
+.. table:: nGraph Quantized Builders
+
+ +--------------------------+-----------------------------------+-----------------------------------------+
+ | Category | Builder | Description |
+ +==========================+===================================+=========================================+
+ | Scaled Mode | ScaledQuantize | Converts min and max to scale |
+ | Min / Max Builders | | and zero point using a scaled mode |
+ | | | calculation and then constructs and |
+ | | | returns an nGraph Quantize operator. |
+ | +-----------------------------------+-----------------------------------------+
+ | | ScaledDequantize | Converts min and max to scale |
+ | | | and zero point using a scaled mode |
+ | | | calculation and then constructs and |
+ | | | returns an nGraph Dequantize operator. |
+ +--------------------------+-----------------------------------+-----------------------------------------+
+ | Quantized Convolution | ScaledQuantizedConvolution | Constructs a quantized convolution |
+ | and Variants | | with an optional ReLU. |
+ | +-----------------------------------+-----------------------------------------+
+ | | ScaledQuantizedConvolutionBias | Constructs a quantized convolution |
+ | | | with bias and an optional ReLU. |
+ | +-----------------------------------+-----------------------------------------+
+ | | ScaledQuantizedConvolutionBiasAdd | Constructs a quantized convolution |
+ | | | with bias and an optional ReLU, where |
+ | | | the output is added to the output |
+ | | | of another convolution (sum_input). |
+ +--------------------------+-----------------------------------+-----------------------------------------+
+ | Quantized Dot (Matmul) | ScaledQuantizedDot | Constructs a quantized dot (Matmul) |
+ | and Variants | | with an optional ReLU. |
+ | +-----------------------------------+-----------------------------------------+
+ | | ScaledQuantizedDotBias | Constructs a quantized dot (Matmul) |
+ | | | with bias and an optional ReLU. |
+ +--------------------------+-----------------------------------+-----------------------------------------+
+ | Quantized Concat | ScaledQuantizedConcat | Constructs a quantized concatenation. |
+ +--------------------------+-----------------------------------+-----------------------------------------+
diff --git a/doc/sphinx/source/dynamic/index.rst b/doc/sphinx/source/dynamic/index.rst
new file mode 100644
index 00000000000..7808eabf961
--- /dev/null
+++ b/doc/sphinx/source/dynamic/index.rst
@@ -0,0 +1,41 @@
+.. dynamic/index.rst:
+
+
+Dynamic Shapes
+==============
+
+For an example on how to use dynamic shapes, see the :ref:`scenario_two`
+documentation.
+
+Runtime Error Checking
+----------------------
+
+Static type-checking in the presence of dynamic shapes will make optimistic
+assumptions about things like shape mismatches. For example, if an elementwise
+op is provided inputs of shapes ``(2,?)`` and ``(?,5)``, the type checker will
+proceed under the assumption that the user is not going to pass tensors with
+inconsistent shape at runtime, and therefore infer an output shape of ``(2,5)``.
+That means that shape mismatches can now occur at runtime.
+
+
+.. _partial_shapes:
+
+PartialShape, Dimension, and Rank Classes
+-----------------------------------------
+
+Partial shape information is expressed via the ``PartialShape``, ``Dimension``,
+and ``Rank`` classes.
+
+.. note:: ``Rank`` is an alias for ``Dimension``, used when the value represents
+ the number of axes in a shape, rather than the size of one dimension in a shape.
+
+
+.. doxygenclass:: ngraph::PartialShape
+ :project: ngraph
+ :members:
+
+
+.. doxygenclass:: ngraph::Dimension
+ :project: ngraph
+ :members:
+
diff --git a/doc/sphinx/source/frameworks/index.rst b/doc/sphinx/source/frameworks/index.rst
index a87d7622f0d..a1eaaf4bdae 100644
--- a/doc/sphinx/source/frameworks/index.rst
+++ b/doc/sphinx/source/frameworks/index.rst
@@ -1,3 +1,5 @@
+:orphan:
+
.. frameworks/index.rst
Working with Frameworks
@@ -11,4 +13,4 @@ Working with Frameworks
onnx_integ.rst
paddle_integ.rst
tensorflow_connect.rst
- other.rst
+ other/index.rst
diff --git a/doc/sphinx/source/frameworks/onnx_integ.rst b/doc/sphinx/source/frameworks/onnx_integ.rst
index db40ed7262d..6c4739d6c9c 100644
--- a/doc/sphinx/source/frameworks/onnx_integ.rst
+++ b/doc/sphinx/source/frameworks/onnx_integ.rst
@@ -1,7 +1,7 @@
.. frameworks/onnx_integ.rst:
-ONNX overview
-=============
+ONNX
+====
nGraph is able to import and execute ONNX models. Models are converted to
nGraph's :abbr:`Intermediate Representation (IR)` and converted to ``Function``
diff --git a/doc/sphinx/source/frameworks/other.rst b/doc/sphinx/source/frameworks/other/index.rst
similarity index 93%
rename from doc/sphinx/source/frameworks/other.rst
rename to doc/sphinx/source/frameworks/other/index.rst
index f9c9809db97..d3bae434f3b 100644
--- a/doc/sphinx/source/frameworks/other.rst
+++ b/doc/sphinx/source/frameworks/other/index.rst
@@ -1,16 +1,18 @@
-.. frameworks/other.rst:
+.. frameworks/other/index.rst:
.. _fw_other:
+.. contents::
+
Integrating other frameworks
============================
This section details some of the *configuration options* and some of the
*environment variables* that can be used to tune for optimal performance when
your system already has a version of nGraph installed with one or more of our
-supported :doc:`../backends/index`.
+supported :doc:`../../backends/index`.
-Regardless of the framework, after the :doc:`../buildlb` step, a good place
+Regardless of the framework, after the :doc:`../../buildlb` step, a good place
to start usually involves making the libraries available to the framework. On
Linux\* systems built on Intel® Architecture, that command tends to looks
something like:
@@ -24,7 +26,7 @@ something like:
Find or display version
-----------------------
-If you're working with the :doc:`../python_api/index`, the following command
+If you're working with the :doc:`../../python_api/index`, the following command
may be useful:
.. code-block:: console
@@ -92,10 +94,10 @@ Training Deep Neural Networks
-----------------------------
Before tweaking various environment variables, be aware that how the computation
-gets executed depends upon the ordering of the data format that the model is
-using. ``NHWC`` and ``NCHW`` are the two more common layouts in Deep Learning
-models. Your ultimate runtime can vary greatly -- even when all other factors
-are exactly the same -- when this detail is overlooked.
+gets executed depends on the data layout that the model is using. ``NHWC`` and
+``NCHW`` are common layouts in Deep Learning models. Your ultimate
+runtime can vary greatly -- even when all other factors are exactly the same --
+when this detail is overlooked.
For CPU (and most cuDNN) backends, the preferred layout is currently ``NCHW``.
@@ -110,7 +112,7 @@ Intel® Math Kernel Library for Deep Neural Networks
---------------------------------------------------
.. important:: Intel® MKL-DNN is automatically enabled as part of an
- nGraph default :doc:`build <../buildlb>`; you do *not* need to add it
+ nGraph default :doc:`build <../../buildlb>`; you do *not* need to add it
separately or as an additional component to be able to use these
configuration settings.
@@ -229,4 +231,3 @@ thus can make more efficient use of the underlying hardware.
.. _BUILDING.md: https://github.com/NervanaSystems/ngraph/blob/master/python/BUILDING.md
.. _GCC wiki for details: https://gcc.gnu.org/wiki/FunctionMultiVersioning
.. _following article may be helpful: https://clearlinux.org/documentation/clear-linux/tutorials/fmv
-
diff --git a/doc/sphinx/source/frameworks/overview.rst b/doc/sphinx/source/frameworks/overview.rst
index 1c2712f4690..da3312e3b7b 100644
--- a/doc/sphinx/source/frameworks/overview.rst
+++ b/doc/sphinx/source/frameworks/overview.rst
@@ -16,8 +16,9 @@ the nGraph Compiler, it helps to familiarize yourself with some basic concepts.
We use the term :term:`bridge` to describe code that connects to any nGraph
device backend(s) while maintaining the framework's programmatic or user
interface. We have a `bridge for the TensorFlow framework`_. We also have a
-:doc:`paddle_integ` bridge. Intel previously :doc:`contributed work to an MXNet bridge <../project/extras/testing_latency>`;
-however, support for the MXNet bridge is no longer active.
+:doc:`paddle_integ` bridge. Intel previously :doc:`contributed work to an MXNet
+bridge <../project/extras/testing_latency>`; however, support for the MXNet
+bridge is no longer active.
`ONNX`_ on its own is not a framework; it can be used with nGraph's
:doc:`../python_api/index` to import and execute ONNX models.
@@ -37,7 +38,7 @@ data scientists, or for deployment in cloud container environments, nGraph's
We invite anyone working on new and novel frameworks or neural network designs
to explore our highly-modularized stack of components.
-Please read the :doc:`other` section for other framework-agnostic
+Please read the :doc:`other/index` section for other framework-agnostic
configurations available to users of the nGraph Compiler stack.
.. figure:: ../graphics/overview-translation-flow.svg
diff --git a/doc/sphinx/source/frameworks/paddle_integ.rst b/doc/sphinx/source/frameworks/paddle_integ.rst
index 024ff424d7a..9c9d5ab76e0 100644
--- a/doc/sphinx/source/frameworks/paddle_integ.rst
+++ b/doc/sphinx/source/frameworks/paddle_integ.rst
@@ -1,7 +1,7 @@
.. frameworks/paddle_integ.rst:
-PaddlePaddle integration
-========================
+PaddlePaddle\*
+==============
PaddlePaddle is an open source deep learning framework developed by Baidu. It
aims to enable performant large-scale distributed computation for deep learning.
@@ -47,8 +47,8 @@ nGraph code in one place allows for easy maintenance.
.. _figure-paddle-design:
-.. figure:: ../graphics/paddlepaddle_design.png
- :width: 555px
+.. figure:: ../graphics/paddlepaddle_design.svg
+ :width: 100%
:alt:
*Figure A* above depicts nGraph access from PaddlePaddle. The PaddlePaddle
@@ -65,7 +65,7 @@ is organized in the following file structure:
.. _figure-paddle-dir:
.. figure:: ../graphics/PaddlePaddleDir.svg
- :width: 555px
+ :width: 100%
:alt:
Compilation of nGraph is handled by the ``ngraph.cmake`` file in the
diff --git a/doc/sphinx/source/frameworks/quickstart.rst b/doc/sphinx/source/frameworks/quickstart.rst
index 005258db9fa..ae4e3c8e278 100644
--- a/doc/sphinx/source/frameworks/quickstart.rst
+++ b/doc/sphinx/source/frameworks/quickstart.rst
@@ -79,7 +79,7 @@ Other integration paths
If you are considering incorporating components from the nGraph Compiler stack
in your framework or neural network design, another useful doc is the section
-on :doc:`other` . Contents here are also useful if you are working on
+on :doc:`other/index` . Contents here are also useful if you are working on
something built-from-scratch, or on an existing framework that is less
widely-supported than the popular frameworks like TensorFlow and PyTorch.
diff --git a/doc/sphinx/source/frameworks/tensorflow_connect.rst b/doc/sphinx/source/frameworks/tensorflow_connect.rst
index a73360210e4..5719ee0f67c 100644
--- a/doc/sphinx/source/frameworks/tensorflow_connect.rst
+++ b/doc/sphinx/source/frameworks/tensorflow_connect.rst
@@ -1,7 +1,7 @@
.. frameworks/tensorflow_connect.rst:
-nGraph Bridge for TensorFlow
-============================
+TensorFlow\*
+============
See the `README`_ on the `ngraph_bridge repo`_ for the many ways to connect
diff --git a/doc/sphinx/source/glossary.rst b/doc/sphinx/source/glossary.rst
index f6199a54d28..63e9e348096 100644
--- a/doc/sphinx/source/glossary.rst
+++ b/doc/sphinx/source/glossary.rst
@@ -101,11 +101,25 @@ Glossary
In the context of a function graph, the term "result" refers to
what stands in for the returned value.
+ dynamic tensor
+
+ A tensor whose shape can change from one "iteration" to the next. When
+ created, a framework :term:`bridge` might supply only *partial* shape
+ information: it might be **all** the tensor dimensions, **some** of the
+ tensor dimensions, or **none** of the tensor dimensions; furthermore,
+ the rank of the tensor may be left unspecified.
+
shape
The shape of a tensor is a tuple of non-negative integers that
represents an exclusive upper bound for coordinate values.
+ shape propagation
+
+ The static process by which assignment of every tensor (or,
+ equivalently, every node output) in the graph is assigned
+ **complete shape information**.
+
shared pointer
The C++ standard template library has the template
diff --git a/doc/sphinx/source/graphics/ExecutionInterfaceRunGraphs.png b/doc/sphinx/source/graphics/ExecutionInterfaceRunGraphs.png
deleted file mode 100644
index d3bfceacccf..00000000000
Binary files a/doc/sphinx/source/graphics/ExecutionInterfaceRunGraphs.png and /dev/null differ
diff --git a/doc/sphinx/source/graphics/dl-current-state.png b/doc/sphinx/source/graphics/dl-current-state.png
deleted file mode 100644
index d652d749b23..00000000000
Binary files a/doc/sphinx/source/graphics/dl-current-state.png and /dev/null differ
diff --git a/doc/sphinx/source/graphics/dl-current-state.xcf b/doc/sphinx/source/graphics/dl-current-state.xcf
deleted file mode 100644
index 367d521a372..00000000000
Binary files a/doc/sphinx/source/graphics/dl-current-state.xcf and /dev/null differ
diff --git a/doc/sphinx/source/graphics/execution-interface-run-graph.svg b/doc/sphinx/source/graphics/execution-interface-run-graph.svg
new file mode 100644
index 00000000000..a7350f65a42
--- /dev/null
+++ b/doc/sphinx/source/graphics/execution-interface-run-graph.svg
@@ -0,0 +1 @@
+
diff --git a/doc/sphinx/source/graphics/paddlepaddle_design.png b/doc/sphinx/source/graphics/paddlepaddle_design.png
deleted file mode 100644
index bf289aa4e50..00000000000
Binary files a/doc/sphinx/source/graphics/paddlepaddle_design.png and /dev/null differ
diff --git a/doc/sphinx/source/graphics/paddlepaddle_design.svg b/doc/sphinx/source/graphics/paddlepaddle_design.svg
new file mode 100644
index 00000000000..e85952a7821
--- /dev/null
+++ b/doc/sphinx/source/graphics/paddlepaddle_design.svg
@@ -0,0 +1 @@
+
diff --git a/doc/sphinx/source/graphics/scalability-matters.png b/doc/sphinx/source/graphics/scalability-matters.png
deleted file mode 100644
index 221da00a8cd..00000000000
Binary files a/doc/sphinx/source/graphics/scalability-matters.png and /dev/null differ
diff --git a/doc/sphinx/source/graphics/scalability-matters.xcf b/doc/sphinx/source/graphics/scalability-matters.xcf
deleted file mode 100644
index 3d1c564531d..00000000000
Binary files a/doc/sphinx/source/graphics/scalability-matters.xcf and /dev/null differ
diff --git a/doc/sphinx/source/graphics/simple-compiler-passes.png b/doc/sphinx/source/graphics/simple-compiler-passes.png
deleted file mode 100644
index e1c6eb8830e..00000000000
Binary files a/doc/sphinx/source/graphics/simple-compiler-passes.png and /dev/null differ
diff --git a/doc/sphinx/source/graphics/simple-compiler-passes.svg b/doc/sphinx/source/graphics/simple-compiler-passes.svg
new file mode 100644
index 00000000000..7bfa2aaec8e
--- /dev/null
+++ b/doc/sphinx/source/graphics/simple-compiler-passes.svg
@@ -0,0 +1 @@
+
diff --git a/doc/sphinx/source/index.rst b/doc/sphinx/source/index.rst
index 11cec06a752..1e297fc1dbf 100644
--- a/doc/sphinx/source/index.rst
+++ b/doc/sphinx/source/index.rst
@@ -39,38 +39,58 @@ nGraph Compiler Stack Documentation
introduction.rst
.. toctree::
- :maxdepth: 2
+ :maxdepth: 1
:caption: Framework Support
- frameworks/index.rst
- frameworks/validated/list.rst
-
+ frameworks/overview.rst
+ frameworks/tensorflow_connect.rst
+ frameworks/onnx_integ.rst
+ frameworks/paddle_integ.rst
+ frameworks/other/index.rst
.. toctree::
:maxdepth: 1
:caption: nGraph Core
- buildlb.rst
core/overview.rst
- core/fusion/index.rst
- nGraph Core Ops
+ buildlb.rst
core/constructing-graphs/index.rst
core/passes/passes.rst
+ core/fusion/index.rst
+ nGraph Core Ops
provenance/index.rst
+ Graph Execution API
+ core/quantization.rst
+ dynamic/index.rst
.. toctree::
:maxdepth: 1
- :caption: APIs
+ :caption: Backend Support
+
+ Basic Concepts
+ backends/plaidml-ng-api/index.rst
+ Integrating Other Backends
+
+
+.. toctree::
+ :maxdepth: 1
+ :caption: Training
+
+ training/index.rst
+ training/qat.rst
+
+
+.. toctree::
+ :maxdepth: 1
+ :caption: Validated Workloads
- python_api/index.rst
- backends/index.rst
- backends/cpp-api.rst
+ frameworks/validated/list.rst
.. toctree::
:maxdepth: 1
- :caption: Inspecting Graphs
+ :caption: Debugging Graphs
inspection/index.rst
diff --git a/doc/sphinx/source/ops/add.rst b/doc/sphinx/source/ops/add.rst
index bd5e0efdf8b..0171e9670e5 100644
--- a/doc/sphinx/source/ops/add.rst
+++ b/doc/sphinx/source/ops/add.rst
@@ -58,6 +58,6 @@ Backprop
C++ Interface
=============
-.. doxygenclass:: ngraph::op::Add
+.. doxygenclass:: ngraph::op::v0::Add
:project: ngraph
:members:
diff --git a/doc/sphinx/source/ops/and.rst b/doc/sphinx/source/ops/and.rst
index 19456bcdcc7..c7fe81f6bd6 100644
--- a/doc/sphinx/source/ops/and.rst
+++ b/doc/sphinx/source/ops/and.rst
@@ -50,6 +50,6 @@ Mathematical Definition
C++ Interface
=============
-.. doxygenclass:: ngraph::op::And
+.. doxygenclass:: ngraph::op::v0::And
:project: ngraph
:members:
diff --git a/doc/sphinx/source/ops/broadcast.rst b/doc/sphinx/source/ops/broadcast.rst
index 2e027084533..8242ea0fc7e 100644
--- a/doc/sphinx/source/ops/broadcast.rst
+++ b/doc/sphinx/source/ops/broadcast.rst
@@ -91,6 +91,6 @@ Backprop
C++ Interface
=============
-.. doxygenclass:: ngraph::op::Broadcast
+.. doxygenclass:: ngraph::op::v0::Broadcast
:project: ngraph
:members:
diff --git a/doc/sphinx/source/ops/divide.rst b/doc/sphinx/source/ops/divide.rst
index 56f190bf99b..554de7db677 100644
--- a/doc/sphinx/source/ops/divide.rst
+++ b/doc/sphinx/source/ops/divide.rst
@@ -56,6 +56,6 @@ Backprop
C++ Interface
=============
-.. doxygenclass:: ngraph::op::Divide
+.. doxygenclass:: ngraph::op::v0::Divide
:project: ngraph
:members:
diff --git a/doc/sphinx/source/ops/equal.rst b/doc/sphinx/source/ops/equal.rst
index 807bd2932b5..5eb845b94e1 100644
--- a/doc/sphinx/source/ops/equal.rst
+++ b/doc/sphinx/source/ops/equal.rst
@@ -49,6 +49,6 @@ Mathematical Definition
C++ Interface
=============
-.. doxygenclass:: ngraph::op::Equal
+.. doxygenclass:: ngraph::op::v0::Equal
:project: ngraph
:members:
diff --git a/doc/sphinx/source/ops/greater.rst b/doc/sphinx/source/ops/greater.rst
index 34aeda8c2a3..187d3be95f8 100644
--- a/doc/sphinx/source/ops/greater.rst
+++ b/doc/sphinx/source/ops/greater.rst
@@ -48,6 +48,6 @@ Mathematical Definition
C++ Interface
=============
-.. doxygenclass:: ngraph::op::Greater
+.. doxygenclass:: ngraph::op::v0::Greater
:project: ngraph
:members:
diff --git a/doc/sphinx/source/ops/greater_eq.rst b/doc/sphinx/source/ops/greater_eq.rst
index 57880e10730..b7add4a37bf 100644
--- a/doc/sphinx/source/ops/greater_eq.rst
+++ b/doc/sphinx/source/ops/greater_eq.rst
@@ -48,6 +48,6 @@ Mathematical Definition
C++ Interface
=============
-.. doxygenclass:: ngraph::op::GreaterEq
+.. doxygenclass:: ngraph::op::v0::GreaterEq
:project: ngraph
:members:
diff --git a/doc/sphinx/source/ops/index.rst b/doc/sphinx/source/ops/index.rst
index 0c6c0641028..76d8904c3af 100644
--- a/doc/sphinx/source/ops/index.rst
+++ b/doc/sphinx/source/ops/index.rst
@@ -4,7 +4,7 @@
List of Core ``ops``
####################
-Not currently a comprehensive list.
+Some operations are experimental.
:ref:`more_about`
@@ -160,10 +160,9 @@ Not currently a comprehensive list.
More about Core Ops
-------------------
-An ``Op``'s primary role is to function as a node in a ddirected acyclic
+An ``Op``'s primary role is to function as a node in a directed acyclic
computation graph.
-
*Core ops* are ops that are available and generally useful to all framework
bridges and that can be compiled by all transformers. A framework bridge may
define framework-specific ops to simplify graph construction, provided that the
@@ -188,14 +187,6 @@ where there is no ambiguity.
If a framework supports extending the set of ops it offers, a bridge may even
expose transformer-specific ops to the framework user.
-
-.. figure:: ../graphics/tablengraphops.png
- :width: 535px
- :alt: Operations Available in the nGraph IR
-
- Operations Available in the nGraph IR
-
-
.. important:: Our design philosophy is that the graph is not a script for
running kernels; rather, our compilation will match ``ops`` to appropriate
kernels for the backend(s) in use. Thus, we expect that adding of new Core
diff --git a/doc/sphinx/source/ops/less.rst b/doc/sphinx/source/ops/less.rst
index 51e8251c03f..3d163c13347 100644
--- a/doc/sphinx/source/ops/less.rst
+++ b/doc/sphinx/source/ops/less.rst
@@ -48,6 +48,6 @@ Mathematical Definition
C++ Interface
=============
-.. doxygenclass:: ngraph::op::Less
+.. doxygenclass:: ngraph::op::v0::Less
:project: ngraph
:members:
diff --git a/doc/sphinx/source/ops/less_eq.rst b/doc/sphinx/source/ops/less_eq.rst
index 6f7b84011b0..3e446581f96 100644
--- a/doc/sphinx/source/ops/less_eq.rst
+++ b/doc/sphinx/source/ops/less_eq.rst
@@ -48,6 +48,6 @@ Mathematical Definition
C++ Interface
=============
-.. doxygenclass:: ngraph::op::LessEq
+.. doxygenclass:: ngraph::op::v0::LessEq
:project: ngraph
:members:
diff --git a/doc/sphinx/source/ops/maximum.rst b/doc/sphinx/source/ops/maximum.rst
index 243bbeb6047..c7a22a168d8 100644
--- a/doc/sphinx/source/ops/maximum.rst
+++ b/doc/sphinx/source/ops/maximum.rst
@@ -56,6 +56,6 @@ Backprop
C++ Interface
=============
-.. doxygenclass:: ngraph::op::Maximum
+.. doxygenclass:: ngraph::op::v0::Maximum
:project: ngraph
:members:
diff --git a/doc/sphinx/source/ops/minimum.rst b/doc/sphinx/source/ops/minimum.rst
index 2d82245bf0c..a2fb51f2f21 100644
--- a/doc/sphinx/source/ops/minimum.rst
+++ b/doc/sphinx/source/ops/minimum.rst
@@ -56,6 +56,6 @@ Backprop
C++ Interface
=============
-.. doxygenclass:: ngraph::op::Minimum
+.. doxygenclass:: ngraph::op::v0::Minimum
:project: ngraph
:members:
diff --git a/doc/sphinx/source/ops/multiply.rst b/doc/sphinx/source/ops/multiply.rst
index e8ccbe3024b..a08887a21da 100644
--- a/doc/sphinx/source/ops/multiply.rst
+++ b/doc/sphinx/source/ops/multiply.rst
@@ -56,6 +56,6 @@ Backprop
C++ Interface
=============
-.. doxygenclass:: ngraph::op::Multiply
+.. doxygenclass:: ngraph::op::v0::Multiply
:project: ngraph
:members:
diff --git a/doc/sphinx/source/ops/not.rst b/doc/sphinx/source/ops/not.rst
index b8257e50563..5a0dde3e3c5 100644
--- a/doc/sphinx/source/ops/not.rst
+++ b/doc/sphinx/source/ops/not.rst
@@ -46,6 +46,6 @@ Mathematical Definition
C++ Interface
=============
-.. doxygenclass:: ngraph::op::Not
+.. doxygenclass:: ngraph::op::v0::Not
:project: ngraph
:members:
diff --git a/doc/sphinx/source/ops/not_equal.rst b/doc/sphinx/source/ops/not_equal.rst
index 5bd35f7722b..e3907710a73 100644
--- a/doc/sphinx/source/ops/not_equal.rst
+++ b/doc/sphinx/source/ops/not_equal.rst
@@ -49,6 +49,6 @@ Mathematical Definition
C++ Interface
=============
-.. doxygenclass:: ngraph::op::NotEqual
+.. doxygenclass:: ngraph::op::v0::NotEqual
:project: ngraph
:members:
diff --git a/doc/sphinx/source/ops/one_hot.rst b/doc/sphinx/source/ops/one_hot.rst
index 7cb152fc78a..469e73b96f4 100644
--- a/doc/sphinx/source/ops/one_hot.rst
+++ b/doc/sphinx/source/ops/one_hot.rst
@@ -57,6 +57,6 @@ Mathematical Definition
C++ Interface
=============
-.. doxygenclass:: ngraph::op::OneHot
+.. doxygenclass:: ngraph::op::v0::OneHot
:project: ngraph
:members:
diff --git a/doc/sphinx/source/ops/or.rst b/doc/sphinx/source/ops/or.rst
index 1c4805a4a05..b94d9c4c9e3 100644
--- a/doc/sphinx/source/ops/or.rst
+++ b/doc/sphinx/source/ops/or.rst
@@ -50,6 +50,6 @@ Mathematical Definition
C++ Interface
=============
-.. doxygenclass:: ngraph::op::Or
+.. doxygenclass:: ngraph::op::v0::Or
:project: ngraph
:members:
diff --git a/doc/sphinx/source/ops/power.rst b/doc/sphinx/source/ops/power.rst
index a1db1054b51..3ac1ed3e663 100644
--- a/doc/sphinx/source/ops/power.rst
+++ b/doc/sphinx/source/ops/power.rst
@@ -54,6 +54,6 @@ Backprop
C++ Interface
=============
-.. doxygenclass:: ngraph::op::Power
+.. doxygenclass:: ngraph::op::v0::Power
:project: ngraph
:members:
diff --git a/doc/sphinx/source/ops/slice.rst b/doc/sphinx/source/ops/slice.rst
index 94417c0eece..1bfcfc336e6 100644
--- a/doc/sphinx/source/ops/slice.rst
+++ b/doc/sphinx/source/ops/slice.rst
@@ -65,7 +65,7 @@ where :math:`I=I_1, I_2, \ldots, I_n` is a coordinate of the output.
C++ Interface
=============
-.. doxygenclass:: ngraph::op::Slice
+.. doxygenclass:: ngraph::op::v0::Slice
:project: ngraph
:members:
diff --git a/doc/sphinx/source/ops/xor.rst b/doc/sphinx/source/ops/xor.rst
index f6cf467a929..52d2ea2900f 100644
--- a/doc/sphinx/source/ops/xor.rst
+++ b/doc/sphinx/source/ops/xor.rst
@@ -50,6 +50,6 @@ Mathematical Definition
C++ Interface
=============
-.. doxygenclass:: ngraph::op::Xor
+.. doxygenclass:: ngraph::op::v0::Xor
:project: ngraph
:members:
diff --git a/doc/sphinx/source/project/release-notes.rst b/doc/sphinx/source/project/release-notes.rst
index 3a416335f4a..be14a68d376 100644
--- a/doc/sphinx/source/project/release-notes.rst
+++ b/doc/sphinx/source/project/release-notes.rst
@@ -21,6 +21,27 @@ We are pleased to announce the release of version |version|.
Core updates for |version|
--------------------------
++ New ops
++ Provenance improvements from 0.25.1
++ More dynamic shape ops
++ More informative errors
+
+
+
+Latest documentation updates
+----------------------------
+
++ Additional details on quantization
++ Index updates
++ API updates
+
+.. important:: Pre-releases (``-rc-0.*``) have newer features, and are less stable.
+
+
+
+Changelog on Previous Releases
+==============================
+
+ All ops support ``Output`` arguments
+ Additional ops
+ ONNX handling unknown domains
@@ -31,21 +52,16 @@ Core updates for |version|
+ Negative indices/axes fixes
+ Better support for MKL-DNN 1.0 (DNNL)
+ Additional constant element types
-
-Latest documentation updates
-----------------------------
-
+ Add new Sphinx-friendly theme (can be built natively for an alternative to ngraph.ai docs).
+ Update PaddlePaddle documentation to reflect demo directories instead of example directory.
+ Update doc regarding the validation of ``Sum`` op.
-.. important:: Pre-releases (``-rc-0.*``) have newer features, and are less stable.
+0.26.1
+------
++ Performance increase for ``ConstantFolding`` pass
-Changelog on Previous Releases
-==============================
-
0.25.1
------
@@ -155,6 +171,7 @@ Changelog on Previous Releases
pre-0.20
--------
+
+ More dynamic shape preparation
+ Distributed interface factored out
+ fp16 and bfloat16 types
@@ -168,8 +185,6 @@ pre-0.20
+ Additional ONNX ops
+ Add graph visualization tools to doc
+ Update doxygen to be friendlier to frontends
-
-.. 0.18
+ Python formatting issue
+ mkl-dnn work-around
+ Event tracing improvements
@@ -177,16 +192,12 @@ pre-0.20
+ Begin tracking framework node names
+ ONNX quantization
+ More fusions
-
-.. 0.17
+ Allow negative padding in more places
+ Add code generation for some quantized ops
+ Preliminary dynamic shape support
+ initial distributed ops
+ Pad op takes CoordinateDiff instead of Shape pad values to allow for negative
padding.
-
-.. 0.16
+ NodeInput and NodeOutput classes prepare for simplifications of Node
+ Test improvements
+ Additional quantization ops
diff --git a/doc/sphinx/source/provenance/index.rst b/doc/sphinx/source/provenance/index.rst
index 5b790a5a89b..824fb9acb8b 100644
--- a/doc/sphinx/source/provenance/index.rst
+++ b/doc/sphinx/source/provenance/index.rst
@@ -3,8 +3,10 @@
Provenance
##########
+
+.. include:: overview.rst
+
.. toctree::
:maxdepth: 1
-
- overview.rst
-.. other.rst
+
+.. other.rst
\ No newline at end of file
diff --git a/doc/sphinx/source/training/data_ingest.rst b/doc/sphinx/source/training/data_ingest.rst
new file mode 100644
index 00000000000..1c09760d662
--- /dev/null
+++ b/doc/sphinx/source/training/data_ingest.rst
@@ -0,0 +1,31 @@
+.. training/data_ingest.rst:
+
+Data Ingestion
+##############
+
+
+Using TensorFlow
+----------------
+
+.. include:: tf_dist.rst
+
+
+Using PaddlePaddle
+------------------
+
+.. include:: paddle_dist.rst
+
+
+Using a custom framework
+------------------------
+
+.. include:: ../core/constructing-graphs/distribute-train.rst
+
+To synchronize gradients across all workers, the essential operation for data
+parallel training, due to its simplicity and scalability over parameter servers,
+is ``allreduce``. The AllReduce op is one of the nGraph Library’s core ops. To
+enable gradient synchronization for a network, we simply inject the AllReduce op
+into the computation graph, connecting the graph for the autodiff computation
+and optimizer update (which then becomes part of the nGraph graph). The
+nGraph Backend will handle the rest.
+
diff --git a/doc/sphinx/source/training/index.rst b/doc/sphinx/source/training/index.rst
new file mode 100644
index 00000000000..c35b7a14d03
--- /dev/null
+++ b/doc/sphinx/source/training/index.rst
@@ -0,0 +1,13 @@
+.. training/index.rst:
+
+
+Distributed Training
+####################
+
+
+.. toctree::
+ :maxdepth: 1
+
+ overview.rst
+ data_ingest.rst
+
diff --git a/doc/sphinx/source/training/overview.rst b/doc/sphinx/source/training/overview.rst
new file mode 100644
index 00000000000..fbf844ceda1
--- /dev/null
+++ b/doc/sphinx/source/training/overview.rst
@@ -0,0 +1,31 @@
+.. training/overview.rst:
+
+
+Basic Concepts
+==============
+
+.. important:: Distributed training is not officially supported as of version
+ |version|; however, some configuration options have worked for nGraph
+ devices in testing environments.
+
+
+Data scientists with locally-scalable rack or cloud-based resources will likely
+find it worthwhile to experiment with different modes or variations of
+distributed training. Deployments using nGraph Library with supported backends
+can be configured to train with data parallelism and will soon work with model
+parallelism. Distributing workloads is increasingly important, as more data and
+bigger models mean the ability to :doc:`../core/constructing-graphs/distribute-train`
+work with larger and larger datasets, or to work with models having many layers
+that aren't designed to fit to a single device.
+
+Distributed training with data parallelism splits the data and each worker
+node has the same model; during each iteration, the gradients are aggregated
+across all workers with an op that performs "allreduce", and applied to update
+the weights.
+
+Using multiple machines helps to scale and speed up deep learning. With large
+mini-batch training, one could train ResNet-50 with Imagenet-1k data to the
+*Top 5* classifier in minutes using thousands of CPU nodes. See
+`arxiv.org/abs/1709.05011`_.
+
+.. _arxiv.org/abs/1709.05011: https://arxiv.org/format/1709.05011
\ No newline at end of file
diff --git a/doc/sphinx/source/training/paddle_dist.rst b/doc/sphinx/source/training/paddle_dist.rst
new file mode 100644
index 00000000000..347f52d330b
--- /dev/null
+++ b/doc/sphinx/source/training/paddle_dist.rst
@@ -0,0 +1,7 @@
+.. training/paddle_dist.rst:
+
+Distributed Training with PaddlePaddle
+======================================
+
+
+
diff --git a/doc/sphinx/source/training/qat.rst b/doc/sphinx/source/training/qat.rst
new file mode 100644
index 00000000000..3c87270e311
--- /dev/null
+++ b/doc/sphinx/source/training/qat.rst
@@ -0,0 +1,32 @@
+.. training/qat.rst:
+
+
+Quantization-Aware Training
+===========================
+
+:abbr:`Quantization-Aware Training (QAT)` is a technique used to
+quantize models during the training process. The main idea is that
+the quantization is emulated in the forward path by inserting some
+"Quantization" and "De-Quantization" nodes (Q-DQ) several places in
+the network to emulate the inference quantization noise. The
+expectation is the backward propagation will alter the weights so
+that they will adapt to this noise, and the result loss will be much
+better than traditional Post-Training Quantization.
+
+For the weights, it is also common to take different quantization
+functions that cut off outliers. Some examples are available in the
+`Distiller guide`_. Distiller is an open-source Python package for
+neural network compression research. Network compression can reduce
+the footprint of a neural network, increase its inference speed, and
+save energy. Additionally, a framework for pruning, regularization
+and quantization algorithms is provided. A set of tools for analyzing
+and evaluating compression performance on previously-known
+State-of-the-Art (SotA) algorithms
+
+When using :abbr:`QAT (Quantization-Aware Training)` techniques, the
+position in which the Q-DQ ops are placed needs to align with the
+fusions hardware does for inference.
+
+
+.. _Distiller guide: https://nervanasystems.github.io/distiller/algo_quantization.html#quantization-aware-training
+
diff --git a/doc/sphinx/source/training/tf_dist.rst b/doc/sphinx/source/training/tf_dist.rst
new file mode 100644
index 00000000000..96fff54540f
--- /dev/null
+++ b/doc/sphinx/source/training/tf_dist.rst
@@ -0,0 +1,7 @@
+.. training/tf_dist.rst:
+
+Distributed Training with TensorFlow
+====================================
+
+
+
diff --git a/python/ngraph/ops.py b/python/ngraph/ops.py
index 753322fbd63..3b808d89bec 100644
--- a/python/ngraph/ops.py
+++ b/python/ngraph/ops.py
@@ -310,7 +310,7 @@ def scale_shift(data, scale, shift, name=None): # type: (Node, Node, Node, str)
@nameable_op
-def space_to_depth(data, block_size, name=None): # type: (Node, int, str) -> Node
+def space_to_depth(data, mode, block_size, name=None): # type: (Node, str, int, str) -> Node
"""Perform SpaceToDepth operation on the input tensor.
SpaceToDepth rearranges blocks of spatial data into depth.
@@ -318,11 +318,16 @@ def space_to_depth(data, block_size, name=None): # type: (Node, int, str) -> No
and width dimensions are moved to the depth dimension.
:param data: The node with data tensor.
+ :param mode: Specifies how the output depth dimension is gathered from block coordinates.
+
+ blocks_first: The output depth is gathered from [block_size, ..., block_size, C]
+ depth_first: The output depth is gathered from [C, block_size, ..., block_size]
+
:param block_size: The size of the block of values to be moved. Scalar value.
:param name: Optional output node name.
:return: The new node performing a SpaceToDepth operation on input tensor.
"""
- return SpaceToDepth(data, block_size)
+ return SpaceToDepth(data, mode, block_size)
@nameable_op
diff --git a/python/pyngraph/ops/fused/hard_sigmoid.cpp b/python/pyngraph/ops/fused/hard_sigmoid.cpp
index c5e32bdddef..d5759acbf0e 100644
--- a/python/pyngraph/ops/fused/hard_sigmoid.cpp
+++ b/python/pyngraph/ops/fused/hard_sigmoid.cpp
@@ -27,5 +27,7 @@ void regclass_pyngraph_op_HardSigmoid(py::module m)
py::class_, ngraph::op::Op>
hardsigmoid(m, "HardSigmoid");
hardsigmoid.doc() = "ngraph.impl.op.HardSigmoid wraps ngraph::op::HardSigmoid";
- hardsigmoid.def(py::init&, float&, float&>());
+ hardsigmoid.def(py::init&,
+ const std::shared_ptr&,
+ const std::shared_ptr&>());
}
diff --git a/python/pyngraph/ops/fused/space_to_depth.cpp b/python/pyngraph/ops/fused/space_to_depth.cpp
index a23277e3426..65ffee867da 100644
--- a/python/pyngraph/ops/fused/space_to_depth.cpp
+++ b/python/pyngraph/ops/fused/space_to_depth.cpp
@@ -27,5 +27,5 @@ void regclass_pyngraph_op_SpaceToDepth(py::module m)
py::class_, ngraph::op::Op>
spacetodepth(m, "SpaceToDepth");
spacetodepth.doc() = "ngraph.impl.op.SpaceToDepth wraps ngraph::op::SpaceToDepth";
- spacetodepth.def(py::init&, int&>());
+ spacetodepth.def(py::init&, const std::string&, int&>());
}
diff --git a/python/test/ngraph/test_ops_fused.py b/python/test/ngraph/test_ops_fused.py
index 28f37a62a87..bf7bb23857d 100644
--- a/python/test/ngraph/test_ops_fused.py
+++ b/python/test/ngraph/test_ops_fused.py
@@ -351,17 +351,19 @@ def test_hard_sigmoid_operator():
runtime = get_runtime()
data_shape = [3]
- alpha = np.float32(0.5)
- beta = np.float32(0.6)
+ alpha_value = np.float32(0.5)
+ beta_value = np.float32(0.6)
data_value = np.array([-1, 0, 1], dtype=np.float32)
parameter_data = ng.parameter(data_shape, name='Data', dtype=np.float32)
+ parameter_alpha = ng.parameter([], name='Alpha', dtype=np.float32)
+ parameter_beta = ng.parameter([], name='Beta', dtype=np.float32)
- model = ng.hard_sigmoid(parameter_data, alpha, beta)
- computation = runtime.computation(model, parameter_data)
+ model = ng.hard_sigmoid(parameter_data, parameter_alpha, parameter_beta)
+ computation = runtime.computation(model, parameter_data, parameter_alpha, parameter_beta)
- result = computation(data_value)
+ result = computation(data_value, alpha_value, beta_value)
expected = [0.1, 0.6, 1.]
assert np.allclose(result, expected)
@@ -429,11 +431,12 @@ def test_space_to_depth_operator():
data_shape = [1, 2, 4, 4]
data_value = np.arange(start=0, stop=32, step=1.0, dtype=np.float32).reshape(data_shape)
+ mode = 'blocks_first'
block_size = 2
parameter_data = ng.parameter(data_shape, name='Data', dtype=np.float32)
- model = ng.space_to_depth(parameter_data, block_size)
+ model = ng.space_to_depth(parameter_data, mode, block_size)
computation = runtime.computation(model, parameter_data)
result = computation(data_value)
diff --git a/src/contrib/mlir/CMakeLists.txt b/src/contrib/mlir/CMakeLists.txt
index 45bad89b191..a252f8fb60a 100644
--- a/src/contrib/mlir/CMakeLists.txt
+++ b/src/contrib/mlir/CMakeLists.txt
@@ -61,9 +61,9 @@ target_link_libraries(
# some libs need whole archive linkage because of Globals static initialization
function(whole_archive_link target)
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
- set(link_flags "-Llib -Wl,-all_load ")
+ set(link_flags "-L${LLVM_BUILD_LIBRARY_DIR} -Wl,-force_load ")
FOREACH(LIB ${ARGN})
- string(CONCAT link_flags ${link_flags} "${LIB}")
+ string(CONCAT link_flags ${link_flags} "${LIB} ")
ENDFOREACH(LIB)
else()
set(link_flags "-Llib -Wl,--whole-archive,")
@@ -77,10 +77,11 @@ function(whole_archive_link target)
set_target_properties(${target} PROPERTIES LINK_FLAGS ${link_flags})
endfunction(whole_archive_link)
-whole_archive_link(mlir_backend
+set(LIBS
${LLVM_BUILD_LIBRARY_DIR}/libMLIRAffineOps.a
${LLVM_BUILD_LIBRARY_DIR}/libMLIRStandardOps.a
)
+whole_archive_link(mlir_backend ${LIBS})
# Link LLVM libs
target_link_libraries(
mlir_backend PRIVATE
diff --git a/src/contrib/mlir/backend/pass/affine_lowerer.cpp b/src/contrib/mlir/backend/pass/affine_lowerer.cpp
index e4ad584246d..70d80a4e2fb 100644
--- a/src/contrib/mlir/backend/pass/affine_lowerer.cpp
+++ b/src/contrib/mlir/backend/pass/affine_lowerer.cpp
@@ -183,7 +183,20 @@ namespace
void runOnModule() override;
SmallVector buildOutputDefs(Operation* op, PatternRewriter& rewriter);
- Value* createTempTensor(Type type, PatternRewriter& rewriter);
+ /// Allocates a linear buffer for a temporary tensor
+ Value* createTempBuffer(Type type, PatternRewriter& rewriter);
+
+ /// Creates an allocation or view of a memref.
+ /// type MemRef Type
+ /// buffer Optional buffer value to create view over
+ /// offset Optional offset into the buffer this view starts at
+ ///
+ /// If buffer is null, a new allocation of a memref is created.
+ /// Offset is ignored. If buffer is non-null, then we create a temp
+ /// view over a pre-allocated buffer (see createTempBuffer)
+
+ Value*
+ createTempMemref(Type type, Value* buffer, unsigned offset, PatternRewriter& rewriter);
/// Inserts dealloc Ops for each temporary allocated by AllocOp
void insertDeallocs(PatternRewriter& rewriter);
@@ -313,44 +326,63 @@ namespace
}
else
{
+ // For temporaries, we create two instructions:
+ // 1. Linear buffer allocation: If the ng value already has a buffer ID assigned,
+ // we re-use that linear buffer SSA value, else generate an AllocOp.
+ // 2. View creation: Create a view with the tensor shape and an N-D to 1 map over
+ // the linear buffer.
+ // If two memrefs are defined via 2 Views over the same buffer, then they share and
+ // will re-use the same buffer.
auto tensorType = origResult->getType().cast();
- Value* newResult;
+ Value* newResult = nullptr;
Attribute bufferIdAttr = getBufferId(op);
+ Type memRefType = typeConverter.convertType(tensorType);
+
+ Value* bufferValue = nullptr;
if (!bufferIdAttr)
{
// Allocate new memref
- newResult = createTempTensor(typeConverter.convertType(tensorType), rewriter);
+ newResult = createTempMemref(memRefType, nullptr, 0, rewriter);
}
else
{
unsigned bufferId = bufferIdAttr.cast().getInt();
- // Re-use a memref if it exist, else create a new one and update map
+ // Re-use a buffer if it exist, else create a new one and update map
IdToMemRefMap::iterator it = m_id_to_memref.find(bufferId);
if (it == m_id_to_memref.end())
{
- // create a new memref
- newResult =
- createTempTensor(typeConverter.convertType(tensorType), rewriter);
- m_id_to_memref[bufferId] = newResult;
+ // create a new buffer
+ bufferValue = createTempBuffer(memRefType, rewriter);
+ m_id_to_memref[bufferId] = bufferValue;
}
else
{
- newResult = it->second;
+ bufferValue = it->second;
}
+ // Create a temp view over the linear buffer
+ newResult = createTempMemref(memRefType, bufferValue, 0, rewriter);
}
+ NGRAPH_CHECK(newResult != nullptr, "Temp memref value is not set");
newResults.push_back(newResult);
}
}
return newResults;
}
- Value* DialectLoweringPass::createTempTensor(Type type, PatternRewriter& rewriter)
+ Value* DialectLoweringPass::createTempBuffer(Type type, PatternRewriter& rewriter)
{
MemRefType memRefType = type.cast();
NGRAPH_CHECK(memRefType.hasStaticShape(), "Dynamic shapes are not supported");
- Value* alloc = rewriter.create(rewriter.getUnknownLoc(), memRefType);
+ // deduce linear buffer shape
+ unsigned sizeInBytes = memRefType.getSizeInBits() / 8;
+
+ MemRefType bufferType =
+ MemRefType::get({sizeInBytes}, IntegerType::get(8, type.getContext()), {});
+
+ Value* alloc = rewriter.create(rewriter.getUnknownLoc(), bufferType);
+
memRefsToDealloc.push_back(alloc);
// TODO:
@@ -366,6 +398,45 @@ namespace
return alloc;
}
+ Value* DialectLoweringPass::createTempMemref(Type type,
+ Value* buffer,
+ unsigned offset,
+ PatternRewriter& rewriter)
+ {
+ NGRAPH_CHECK(offset == 0, "Only zero offset is supported");
+ MemRefType memRefType = type.cast();
+ if (buffer)
+ {
+ // We have a buffer to map to. Create a view over it.
+
+ // Create the N-D to 1D affine expression mapping the memref shape to the underlying
+ // linear
+ // buffer
+ // This is simply (d0, d1, d2, .. dN-1) --> d0 * S0 + d1 * S1 ... + dN-1 * SN-1
+ // Where Si is the stride along the i_th dimension
+ auto shape = memRefType.getShape();
+ SmallVector strides(shape.size(), 0);
+ strides[shape.size() - 1] = 1;
+ for (int64_t i = shape.size() - 2; i >= 0; i--)
+ {
+ strides[i] = strides[i + 1] * shape[i + 1];
+ }
+
+ auto map = makeStridedLinearLayoutMap(strides, offset, rewriter.getContext());
+ MemRefType newMemRefType = MemRefType::get(shape, memRefType.getElementType(), map);
+ auto viewOp = rewriter.create(
+ buffer->getDefiningOp()->getLoc(), newMemRefType, buffer, llvm::None);
+ return viewOp.getResult();
+ }
+
+ // No buffer, create an atomic memref without underlying buffer
+ NGRAPH_CHECK(memRefType.hasStaticShape(), "Dynamic shapes are not supported");
+
+ Value* alloc = rewriter.create(rewriter.getUnknownLoc(), memRefType);
+ memRefsToDealloc.push_back(alloc);
+ return alloc;
+ }
+
/// Add llvm.noalias attribute to all the memref function arguments. We know that this is safe
/// by nGraph op semantics.
void DialectLoweringPass::insertNoAliasArgAttrs()
@@ -521,7 +592,7 @@ namespace
NGRAPH_CHECK(lhs->getType().isa());
Type elemTy = lhs->getType().dyn_cast().getElementType();
- LoopNestBuilder(pivs, lbs, ubs, steps)([&] {
+ AffineLoopNestBuilder(pivs, lbs, ubs, steps)([&] {
ValueHandle val = iLHS(ivs);
ValueHandle zero = createZeroConstant(elemTy);
iRes(ivs) = intrinsics::select(val > zero, val, zero);
@@ -591,12 +662,14 @@ namespace
{
IndexHandle n, k;
- LoopBuilder(&n, nLb, nUb, nStep)(
- [&] { LoopBuilder(&k, kLb, kUb, kStep)([&] { iRes(n, k) = zeroInit; }); });
+ LoopBuilder::makeAffine(&n, nLb, nUb, nStep)([&] {
+ LoopBuilder::makeAffine(&k, kLb, kUb, kStep)([&] { iRes(n, k) = zeroInit; });
+ });
}
- LoopBuilder(&n, nLb, nUb, nStep)([&] {
- LoopBuilder(&m, mLb, mUb, mStep)([&] {
- LoopBuilder(&k, kLb, kUb, kStep)([&] { iRes(n, k) += iLhs(n, m) * iRhs(m, k); });
+ LoopBuilder::makeAffine(&n, nLb, nUb, nStep)([&] {
+ LoopBuilder::makeAffine(&m, mLb, mUb, mStep)([&] {
+ LoopBuilder::makeAffine(&k, kLb, kUb, kStep)(
+ [&] { iRes(n, k) += iLhs(n, m) * iRhs(m, k); });
});
});
@@ -658,7 +731,7 @@ namespace
indexVarSteps.push_back(vOperand.step(i));
}
- LoopNestBuilder(indexVarPtrs, indexVarLbs, indexVarUbs, indexVarSteps)([&] {
+ AffineLoopNestBuilder(indexVarPtrs, indexVarLbs, indexVarUbs, indexVarSteps)([&] {
IndexedValue ivRes(result);
IndexedValue ivOperand(operand);
@@ -758,12 +831,12 @@ namespace
// params[P_0, P_1, .. P_(A-1), indices[I_0, .., I_(M-1)],
// P_(A+1), ... P_(N-1)];
- LoopNestBuilder(indicesIVPtrs, indicesLbs, indicesUbs, indicesSteps)([&] {
+ AffineLoopNestBuilder(indicesIVPtrs, indicesLbs, indicesUbs, indicesSteps)([&] {
// Load axis value from indices array and cast it to Index Type
ValueHandle axisIdx = ValueHandle::create(
(ValueHandle)iIndices(indicesIVs), rewriter.getIndexType());
- LoopNestBuilder(paramsIVPtrs, paramsLbs, paramsUbs, paramsSteps)([&] {
+ AffineLoopNestBuilder(paramsIVPtrs, paramsLbs, paramsUbs, paramsSteps)([&] {
// construct indices for param
// [P_0, P_1, .. P_axis-1, Indices[I0, I1, .. I_k-1], P_axis+1, P_axis+2, .. P_n-1]
for (auto i = 0, j = 0; i < vParams.rank(); i++)
@@ -965,8 +1038,7 @@ namespace
NGRAPH_CHECK(affineExprs.size() == isEq.size() && isEq.size() == 2 * spatialRank,
"Invalid number of expressions in the IntegerSet");
- nonPaddedRange =
- rewriter.getIntegerSet(spatialRank, 2 * spatialRank, affineExprs, isEq);
+ nonPaddedRange = IntegerSet::get(spatialRank, 2 * spatialRank, affineExprs, isEq);
}
// Initialize output to zero
@@ -975,9 +1047,9 @@ namespace
auto resSpatialIndices = makeIndexHandles(spatialRank);
auto resSpatialIndicesPtrs = makeIndexHandlePointers(resSpatialIndices);
- LoopBuilder(&n, batchLb, batchUb, 1)([&] {
- LoopBuilder(&k, numFiltersLb, numFiltersUb, 1)([&] {
- LoopNestBuilder(
+ LoopBuilder::makeAffine(&n, batchLb, batchUb, 1)([&] {
+ LoopBuilder::makeAffine(&k, numFiltersLb, numFiltersUb, 1)([&] {
+ AffineLoopNestBuilder(
resSpatialIndicesPtrs, resSpatialLbs, resSpatialUbs, resSteps)([&] {
SmallVector resIndices;
// Result indices
@@ -994,13 +1066,13 @@ namespace
IndexHandle n, k, c;
// Convolution loop
- LoopBuilder(&n, batchLb, batchUb, 1)([&] {
+ LoopBuilder::makeAffine(&n, batchLb, batchUb, 1)([&] {
// Number of filters loop
- LoopBuilder(&k, numFiltersLb, numFiltersUb, 1)([&] {
+ LoopBuilder::makeAffine(&k, numFiltersLb, numFiltersUb, 1)([&] {
// Channels loop
- LoopBuilder(&c, numChannelsLb, numChannelsUb, 1)([&] {
+ LoopBuilder::makeAffine(&c, numChannelsLb, numChannelsUb, 1)([&] {
// Results loop
- LoopNestBuilder(
+ AffineLoopNestBuilder(
resSpatialIndicesPtrs, resSpatialLbs, resSpatialUbs, resSteps)([&] {
// Compute image start indices
SmallVector imgStartIndices;
@@ -1017,10 +1089,10 @@ namespace
resIndices.insert(
resIndices.end(), resSpatialIndices.begin(), resSpatialIndices.end());
// Filters spatial loop
- LoopNestBuilder(filtersSpatialIndicesPtrs,
- filtersSpatialLbs,
- filtersSpatialUbs,
- filtersSteps)([&] {
+ AffineLoopNestBuilder(filtersSpatialIndicesPtrs,
+ filtersSpatialLbs,
+ filtersSpatialUbs,
+ filtersSteps)([&] {
SmallVector imgIndices, filtersIndices;
// Image indices
// Here we compute the virtual start index into the padded image.
@@ -1131,7 +1203,7 @@ namespace
NGRAPH_CHECK(lhs->getType().isa());
Type elemTy = lhs->getType().cast().getElementType();
- LoopNestBuilder(pivs, lbs, ubs, steps)([&] {
+ AffineLoopNestBuilder(pivs, lbs, ubs, steps)([&] {
ValueHandle val = iLHS(ivs);
if (isa(op))
{
@@ -1173,7 +1245,7 @@ namespace
auto pivs = makeIndexHandlePointers(ivs);
// Steps
auto steps = vLHS.getSteps();
- LoopNestBuilder(pivs, lbs, ubs, steps)(
+ AffineLoopNestBuilder(pivs, lbs, ubs, steps)(
// single stmt body
[&] {
if (isa(op))
@@ -1266,7 +1338,7 @@ namespace
auto pivs = makeIndexHandlePointers(ivs);
auto steps = vRes.getSteps();
auto initVal = vArg.lb(axis);
- LoopNestBuilder(pivs, resLbs, resUbs, steps)(
+ AffineLoopNestBuilder(pivs, resLbs, resUbs, steps)(
[&] { iRes(ivs) = ValueHandle::create(initVal, resTy); });
}
@@ -1282,7 +1354,7 @@ namespace
"Expected integer result type in index reduction");
// iterate over all argument dimensions
- LoopNestBuilder(pAllIVs, argLbs, argUbs, steps)([&] {
+ AffineLoopNestBuilder(pAllIVs, argLbs, argUbs, steps)([&] {
// build a list of non-reduction IVs
for (auto i = 0; i < vArg.rank(); i++)
{
diff --git a/src/contrib/mlir/core/compiler.cpp b/src/contrib/mlir/core/compiler.cpp
index 564e064474a..2859608b663 100644
--- a/src/contrib/mlir/core/compiler.cpp
+++ b/src/contrib/mlir/core/compiler.cpp
@@ -64,7 +64,6 @@
#include
#include
#include
-#include
#include
#include
#include
diff --git a/src/contrib/mlir/core/compiler.hpp b/src/contrib/mlir/core/compiler.hpp
index 49bb3a179fe..cbe8772dac6 100644
--- a/src/contrib/mlir/core/compiler.hpp
+++ b/src/contrib/mlir/core/compiler.hpp
@@ -24,7 +24,6 @@
#include "ngraph/descriptor/tensor.hpp"
#include "ngraph/node.hpp"
-#include
#include
#include
#include
diff --git a/src/contrib/mlir/core/ngraph_dialect/dialect.cpp b/src/contrib/mlir/core/ngraph_dialect/dialect.cpp
index dc13d2b6868..d7ce4f5ca04 100644
--- a/src/contrib/mlir/core/ngraph_dialect/dialect.cpp
+++ b/src/contrib/mlir/core/ngraph_dialect/dialect.cpp
@@ -18,12 +18,12 @@
// not expose public API to the rest of nGraph codebase and heavily depends on MLIR API.
#include "dialect.hpp"
+#include
+#include
#include "ngraph/check.hpp"
#include "ops.hpp"
#include "type.hpp"
-#include
-
using namespace mlir;
NGraphOpsDialect::NGraphOpsDialect(mlir::MLIRContext* ctx)
@@ -39,63 +39,64 @@ NGraphOpsDialect::NGraphOpsDialect(mlir::MLIRContext* ctx)
>();
}
-mlir::Type NGraphOpsDialect::parseType(llvm::StringRef tyData, mlir::Location loc) const
+mlir::Type NGraphOpsDialect::parseType(mlir::DialectAsmParser& parser) const
{
- StringRef origTypeStr = tyData;
MLIRContext* context = getContext();
// Process nGraph tensor type.
- if (tyData.consume_front("tensor"))
+ // failure is true
+ if (!parser.parseOptionalKeyword("tensor"))
{
- if (!tyData.consume_front("<") || !tyData.consume_back(">"))
+ llvm::SMLoc typeLoc = parser.getCurrentLocation();
+ if (parser.parseLess())
{
- return (emitError(loc, "expected '<' and '>' enclosing the tensor shape: " + tyData),
- Type());
+ parser.emitError(typeLoc, "expected '<' and '>' enclosing the tensor shape");
+ return Type();
}
- // Get x-separated sub-strings.
- SmallVector subStrings;
- tyData.split(subStrings, "x");
-
// Parse shape dimensions.
SmallVector shape;
- for (unsigned i = 0, end = subStrings.size() - 1; i < end; ++i)
- {
- StringRef dimStr = subStrings[i];
- int64_t dim = -1;
- // NOTE: `consumeInteger` returns false if an integer was parsed successfully.
- if (dimStr.consumeInteger(/*Radix=*/10, dim) || !dimStr.empty())
- {
- return (
- emitError(loc, "expected a list of '[0-9]+x' dimension specifiers: " + tyData),
- Type());
- }
-
- shape.push_back(dim);
- }
+ parser.parseDimensionList(shape);
+
+ // Parse the current element type.
+ Type eltType;
- // Parse nGraph element type.
- auto elem_ty = mlir::parseType(subStrings.back(), context);
- if (!elem_ty)
+ parser.parseType(eltType);
+ if (!eltType)
{
- return (emitError(loc, "Unexpected element type in tensor type: " + tyData), Type());
+ typeLoc = parser.getCurrentLocation();
+ parser.emitError(typeLoc, "Invalid tensor element type");
}
-
- return NGTensorType::get(context, elem_ty, shape);
+ parser.parseGreater();
+ return NGTensorType::get(context, eltType, shape);
}
+ else
+ {
+ // parse nGraph scalar type
+ return parseEltType(parser);
+ }
+}
+mlir::Type NGraphOpsDialect::parseEltType(mlir::DialectAsmParser& parser) const
+{
// Process nGraph integer element types.
+ MLIRContext* context = getContext();
+ int width = 0;
+ bool isSigned = false;
+ llvm::SMLoc loc = parser.getCurrentLocation();
+
+ StringRef tyData = parser.getFullSymbolSpec();
+ StringRef origTypeStr = tyData;
+
if (tyData.startswith("i") || tyData.startswith("u"))
{
- bool isSigned = tyData.consume_front("i");
- bool isUnsigned = tyData.consume_front("u");
- NGRAPH_CHECK(isSigned != isUnsigned, "nGraph integer cannot be signed and unsigned");
-
+ isSigned = tyData.consume_front("i");
+ tyData.consume_front("u");
unsigned width = 0;
// NOTE: `consumeInteger` returns false if an integer was parsed successfully.
if (tyData.consumeInteger(/*Radix=*/10, width) || width == 0 || !tyData.empty())
{
- return (emitError(loc, "Unexpected nGraph integer type: " + origTypeStr), Type());
+ parser.emitError(loc, "Unexpected nGraph integer type: " + origTypeStr);
}
switch (width)
@@ -108,9 +109,7 @@ mlir::Type NGraphOpsDialect::parseType(llvm::StringRef tyData, mlir::Location lo
return isSigned ? NGIntegerType::getInt32(context) : NGIntegerType::getUInt32(context);
case 64:
return isSigned ? NGIntegerType::getInt64(context) : NGIntegerType::getUInt64(context);
- default:
- return (emitError(loc, "Unexpected width for nGraph integer type: " + origTypeStr),
- Type());
+ default: parser.emitError(loc, "Unexpected width for nGraph integer type: " + origTypeStr);
}
}
@@ -119,43 +118,49 @@ mlir::Type NGraphOpsDialect::parseType(llvm::StringRef tyData, mlir::Location lo
"Floating point types should be processed by standard parser");
// NOTE: We may hit this error if the nGraph type is not yet supported in parser.
- return (emitError(loc, "Unknown nGraph type: " + origTypeStr), Type());
+ parser.emitError(loc, "Unknown nGraph type: " + origTypeStr);
+
+ return Type();
}
-void NGraphOpsDialect::printType(mlir::Type type, raw_ostream& os) const
+void NGraphOpsDialect::printType(mlir::Type type, mlir::DialectAsmPrinter& printer) const
{
switch (type.getKind())
{
case NG_TENSOR_TYPE_ID:
{
- os << "tensor<";
+ printer << "tensor<";
auto tensorTy = type.cast();
for (auto dim : tensorTy.getShape())
{
- os << dim << 'x';
+ printer << dim << 'x';
}
- os << tensorTy.getElementType() << '>';
+ printer << tensorTy.getElementType() << '>';
return;
}
case NG_I8_TYPE_ID:
case NG_I16_TYPE_ID:
case NG_I32_TYPE_ID:
case NG_I64_TYPE_ID:
+ {
+ auto intTy = type.cast();
+ printer << "i" << intTy.getWidth();
+ return;
+ }
case NG_U8_TYPE_ID:
case NG_U16_TYPE_ID:
case NG_U32_TYPE_ID:
case NG_U64_TYPE_ID:
{
auto intTy = type.cast();
- os << "i" << intTy.getWidth();
+ printer << "u" << intTy.getWidth();
return;
}
case NG_BOOL_TYPE_ID:
{
- os << "bool";
+ printer << "bool";
return;
}
- default: { NGRAPH_CHECK(false, "Incorrect type to print?");
- }
+ default: NGRAPH_UNREACHABLE("Incorrect type to print?");
}
}
diff --git a/src/contrib/mlir/core/ngraph_dialect/dialect.hpp b/src/contrib/mlir/core/ngraph_dialect/dialect.hpp
index 32b4f4a4b42..b9c7fa90b89 100644
--- a/src/contrib/mlir/core/ngraph_dialect/dialect.hpp
+++ b/src/contrib/mlir/core/ngraph_dialect/dialect.hpp
@@ -34,9 +34,12 @@ namespace mlir
{
public:
explicit NGraphOpsDialect(mlir::MLIRContext* ctx);
- mlir::Type parseType(llvm::StringRef tyData, mlir::Location loc) const override;
- void printType(mlir::Type type, llvm::raw_ostream& os) const override;
+
+ mlir::Type parseType(mlir::DialectAsmParser& parser) const override;
+ void printType(mlir::Type type, mlir::DialectAsmPrinter& printer) const override;
static StringRef getDialectNamespace() { return "ng"; }
+ private:
+ mlir::Type parseEltType(mlir::DialectAsmParser& parser) const;
};
}
diff --git a/src/contrib/mlir/core/ngraph_dialect/fused_ops.td b/src/contrib/mlir/core/ngraph_dialect/fused_ops.td
index 826c04fab45..df0c21de3bb 100644
--- a/src/contrib/mlir/core/ngraph_dialect/fused_ops.td
+++ b/src/contrib/mlir/core/ngraph_dialect/fused_ops.td
@@ -21,9 +21,10 @@
#ifdef NG_FUSED_OPS
#else
#define NG_FUSED_OPS
+
// Squeeze Op
def NGSqueezeOp :
- NG_OneResult_Op<"squeeze", [NoSideEffect, FusedOp]>,
+ NG_OneResult_Op<"squeeze", [NoSideEffect, DeclareOpInterfaceMethods]>,
Arguments<(ins NG_TensorType:$data, NG_TensorType:$axes)>
{
let summary = "Squeeze Op";
@@ -32,14 +33,988 @@ def NGSqueezeOp :
}];
let parser = [{ NGRAPH_CHECK(false, "No parser support"); return mlir::failure(); }];
+ let verifier = [{ return mlir::success(); /* TBD */ }];
+}
+
+// Unsqueeze Op
+def NGUnSqueezeOp :
+ NG_OneResult_Op<"unsqueeze", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$data, NG_TensorType:$axes)>
+{
+ let summary = "Unsqueeze Op";
+ let description = [{
+ Unsqueeze Op
+ }];
+
+ let parser = [{ NGRAPH_CHECK(false, "No parser support"); return mlir::failure(); }];
+ let verifier = [{ return mlir::success(); /* TBD */ }];
+}
+
+// Squared Difference Op
+def NGSquaredDiffOp :
+ NG_Binary_Op<"sqrdDiff", [DeclareOpInterfaceMethods]>
+{
+ let summary = "Squared Difference Op";
+ let description = [{
+ Squared Difference Op
+ }];
+
+ let parser = [{ NGRAPH_CHECK(false, "No parser support"); return mlir::failure(); }];
+ let verifier = [{ return mlir::success(); /* TBD */ }];
+}
+
+// Split Op
+def NGSplitOp :
+ NG_Variadic_Result_Op<"split", [DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$data, I64Attr:$axis, I64ArrayAttr:$numSplits)>
+{
+ let summary = "Split op";
+ let description = [{
+ Splits the input tensor into a list of smaller tensors ("pieces")
+ }];
+
+ let parser = [{ NGRAPH_CHECK(false, "No parser support"); return mlir::failure(); }];
+ let verifier = [{ return mlir::success(); /* TBD */ }];
+
+ let extraClassDeclaration = [{
+ void setAxis(const Attribute& attr) { this->setAttr("axis", attr); }
+ void setNumSplits(const ArrayAttr& arrayAttr) { this->setAttr("numSplits", arrayAttr); }
+ }];
+
+}
+
+// SpaceToDepth Op
+def NGSpaceToDepthOp :
+ NG_OneResult_Op<"spaceToDepth", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$data,
+ DefaultValuedAttr:$blockSize,
+ DepthSpaceModeEnumAttr:$mode)>
+{
+ let summary = "Space to depth op";
+ let description = [{
+ SpaceToDepth permutes input tensor blocks of spatial data into depth dimension.
+ Values from the height and width dimensions are moved to the depth dimension.
+ Output node produces a tensor with shape:
+ [N, C * blocksize * blocksize, H / blocksize, W / blocksize]
+
+ data Node producing the input tensor
+ blockSize The size of the block of values to be moved
+ }];
+
+ let parser = [{ NGRAPH_CHECK(false, "No parser support"); return mlir::failure(); }];
+ let verifier = [{ return mlir::success(); /* TBD */ }];
+
+ let extraClassDeclaration = [{
+ void setBlockSize(const Attribute& attr) { this->setAttr("blockSize", attr); }
+ void setMode(const Attribute& attr) { this->setAttr("mode", attr); }
+ }];
+}
+
+// ShuffleChannels Op
+def NGShuffleChannelsOp :
+ NG_OneResult_Op<"shuffleChannels", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$data, I64Attr:$axis, I64Attr:$groups)>
+{
+ let summary = "Shuffle Channels op";
+ let description = [{
+ Constructs a ShuffleChannels node.
+ data Node producing the input tensor
+ axis channel dimension index in the data tensor. A negative value means
+ that the index should be calculated from the back of the input data
+ shape.
+ groups number of groups the channel dimension specified by axis should be
+ split into
+ }];
+
+ let parser = [{ NGRAPH_CHECK(false, "No parser support"); return mlir::failure(); }];
+ let verifier = [{ return mlir::success(); /* TBD */ }];
+
+ let extraClassDeclaration = [{
+ void setAxis(const Attribute& axis) { this->setAttr("axis", axis); }
+ void setGroups(const Attribute& groups) { this->setAttr("groups", groups); }
+ }];
+}
+
+// ScaleShift Op
+def NGScaleShiftOp :
+ NG_Ternary_Op<"scaleShift", [DeclareOpInterfaceMethods]>
+{
+ let summary = "scaleShift op";
+ let description = [{
+ Operator performing Scale Shift transformation.
+ Y = Scale * Data + Shift
+ }];
+
+ let parser = [{ NGRAPH_CHECK(false, "No parser support"); return mlir::failure(); }];
+ let verifier = [{ return mlir::success(); /* TBD */ }];
+}
+
+// RNN Cell Op
+def NGRNNCellOp :
+ NG_OneResult_Op<"rnnCell", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$X, NG_TensorType:$W, NG_TensorType:$R, NG_TensorType:$H_t,
+ Variadic:$optionalArgs,
+ DefaultValuedAttr:$activations,
+ DefaultValuedAttr:$activationAlpha,
+ DefaultValuedAttr:$activationBeta,
+ DefaultValuedAttr:$clip,
+ I64Attr:$hiddenSize)>
+{
+ let summary = "RNN Cell";
+ let description = [{
+ RNN Cell
+ }];
+
+ let parser = [{ NGRAPH_CHECK(false, "No parser support"); return mlir::failure(); }];
+ let verifier = [{ return mlir::success(); /* TBD */ }];
+
+ let builders = [
+ OpBuilder<
+ "Builder *builder, OperationState &tblgen_state, Type res,"
+ "Value *X, Value* W, Value* R, Value* H_t, "
+ "Attribute hiddenSize, ArrayAttr activations,"
+ "ArrayAttr activationAlpha, ArrayAttr activationBeta, Attribute clip", [{
+ tblgen_state.addOperands({X, W, R, H_t});
+ tblgen_state.addAttribute("hiddenSize", hiddenSize);
+ tblgen_state.addAttribute("activations", activations);
+ tblgen_state.addAttribute("activationAlpha", activationAlpha);
+ tblgen_state.addAttribute("activationBeta", activationBeta);
+ tblgen_state.addAttribute("clip", clip);
+ tblgen_state.addTypes(res);
+ }]>
+ ];
+
+ let extraClassDeclaration = [{
+ void setHiddenSize(const Attribute& attr) { this->setAttr("hiddenSize", attr); }
+ void setActivations(const ArrayAttr& attr) { this->setAttr("activations", attr); }
+ void setActivationAlpha(const ArrayAttr& attr) { this->setAttr("activationAlpha", attr); }
+ void setActivationBeta(const ArrayAttr& attr) { this->setAttr("activationBeta", attr); }
+ void setClip(const Attribute& attr) { this->setAttr("clip", attr); }
+
+ // get bias operand if present
+ Value* B()
+ {
+ auto varArgs = optionalArgs();
+ return varArgs.begin() != varArgs.end() ? *varArgs.begin() : nullptr;
+ }
+ }];
+}
+
+// Prelu Op
+def NGPrelu :
+ NG_OneResult_Op<"prelu", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$data, NG_TensorType:$slope)>
+{
+ let summary = "Prelu op";
+ let description = [{
+ Prametrized Relu
+ x < 0 => f(x) = x * slope
+ x >= 0 => f(x) = x
+ }];
+
+ let parser = [{ NGRAPH_CHECK(false, "No parser support"); return mlir::failure(); }];
+ let verifier = [{ return mlir::success(); /* TBD */ }];
+}
+
+// Normalize L2 Op
+def NGNormalizeL2Op :
+ NG_OneResult_Op<"normalizeL2", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$data, NG_TensorType:$axis, F32Attr:$eps, EpsModeEnumAttr:$epsMode)>
+{
+ let summary = "NormalizeL2 op";
+ let description = [{
+ Constructs a Normalize operation.
+ data - Node producing the input tensor
+ axes - Node indicating axes along which reduction is
+ calculated
+ eps - The epsilon added to L2 norm.
+ eps_mode - Specifies how eps is combined with L2 value calculated
+ before division
+ }];
+
+ let parser = [{ NGRAPH_CHECK(false, "No parser support"); return mlir::failure(); }];
+ let verifier = [{ return mlir::success(); /* TBD */ }];
+
+ let extraClassDeclaration = [{
+ void setEpsMode(const Attribute& epsMode) { this->setAttr("epsMOde", epsMode); }
+ void setEps(const Attribute& eps) { this->setAttr("eps", eps); }
+ }];
+}
+
+// MVN Op
+def NGMVN :
+ NG_OneResult_Op<"mvn", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$data,
+ DefaultValuedAttr: $acrossChannels,
+ DefaultValuedAttr: $normalizeVariance,
+ DefaultValuedAttr : $eps)>
+{
+ let summary = "MVN op";
+ let description = [{
+ data Input tensor with data
+ normalize_variance flag that denotes whether to perform variance
+ normalization.
+ across_channels flag that denotes if mean values are shared across channels.
+ eps the number to be added to the variance to avoid division by zero when
+ normalizing the value
+ reduction_axes a list of axes, along which to reduce.
+ }];
+
+ let builders = [
+ OpBuilder<
+ "Builder *builder, OperationState &tblgen_state, Type res,"
+ "Value *data, ArrayAttr reductionAxes, Attribute normalizeVariance,"
+ "Attribute eps", [{
+ tblgen_state.addOperands(data);
+ tblgen_state.addAttribute("reductionAxes", reductionAxes);
+ tblgen_state.addAttribute("normalizeVariance", normalizeVariance);
+ tblgen_state.addAttribute("eps", eps);
+ tblgen_state.addTypes(res);
+ }]>
+ ];
+
+ let extraClassDeclaration = [{
+ void setAcrossChannels(const Attribute& attr) { this->setAttr("acrossChannels", attr); }
+ void setNormalizeVariance(const Attribute& attr) { this->setAttr("normalizeVariance", attr); }
+ void setEps(const Attribute& attr) { this->setAttr("eps", attr); }
+ void setReductionAxes(const ArrayAttr& attr) { this->setAttr("reductionAxes", attr); }
+ }];
+}
+
+// MatMul Op
+def NGMatMul :
+ NG_OneResult_Op<"matmul", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$A, NG_TensorType:$B,
+ DefaultValuedAttr:$transposeA,
+ DefaultValuedAttr:$transposeB)>
+{
+ let summary = "MatMul op";
+ let description = [{
+ A Matrix A
+ B Matrix B
+ transpose_a If matrix A should be transposed.
+ transpose_b If matrix B should be transposed.
+ }];
+
+ let extraClassDeclaration = [{
+ void setTransposeA(const Attribute& attr) { this->setAttr("transposeA", attr); }
+ void setTransposeB(const Attribute& attr) { this->setAttr("transposeB", attr); }
+ }];
+}
+
+// LSTM Cell Op
+//
+def NGLSTMCellOp :
+ NG_OneResult_Op<"lstmCell", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$X, NG_TensorType:$W, NG_TensorType:$R,
+ NG_TensorType:$H_t, NG_TensorType:$C_t,
+ Variadic:$optionalArgs,
+ I64Attr:$hiddenSize,
+ DefaultValuedAttr(MLIRLSTMWeightsFormat::IFCO)">:$weightFormat,
+ DefaultValuedAttr:$activations,
+ DefaultValuedAttr:$activationAlpha,
+ DefaultValuedAttr:$activationBeta,
+ DefaultValuedAttr:$clip,
+ DefaultValuedAttr:$inputForget)>
+{
+ let summary = "LSTM Cell";
+ let description = [{
+ LSTM Cell
+ X The input tensor with shape: [batch_size,
+
+ H_t The hidden state tensor at current time step with shape: [batch_size, hidden_size].
+
+ C_t The cell state tensor at current time step with shape: [batch_size, hidden_size].
+
+ W The weight tensor with shape: [4*hidden_size, input_size].
+
+ R The recurrence weight tensor with shape: [4*hidden_size, hidden_size].
+
+ B [Optional] The bias tensor for gates with shape: [4*hidden_size].
+
+ P [Optional] The weight tensor for peepholes with shape:
+ [3*hidden_size] - 3 equals to only iof gates.
+ The order is: input, output, forget gates.
+
+ hiddenSize The number of hidden units for recurrent cell.
+
+ weightsFormat The order of gates in weights tensors.
+ The default format is IFCO since it is used by DNNL.
+
+ activations The vector of activation functions used inside
+ recurrent cell.
+
+ activationsAlpha The vector of alpha parameters for activation
+ functions in order respective to activation list.
+
+ activationsBeta The vector of beta parameters for activation
+ functions in order respective to activation list.
+
+ clip The value defining clipping range [-clip, clip] on
+ input of activation functions.
+
+ inputForget Controls coupling input and forget gates.
+ }];
+
+ let parser = [{ NGRAPH_CHECK(false, "No parser support"); return mlir::failure(); }];
+ let verifier = [{
+ return mlir::success(); /* TBD */
+ }];
+
+ let builders = [
+ OpBuilder<
+ "Builder *builder, OperationState &tblgen_state, Type res,"
+ "Value *X, Value* W, Value* R, Value* H_t, Value* C_t,"
+ "Attribute hiddenSize, ArrayAttr activations,"
+ "ArrayAttr activationAlpha, ArrayAttr activationBeta,"
+ "Attribute clip, Attribute inputForget", [{
+ tblgen_state.addOperands({X, W, R, H_t, C_t});
+ tblgen_state.addAttribute("hiddenSize", hiddenSize);
+ tblgen_state.addAttribute("activations", activations);
+ tblgen_state.addAttribute("activationAlpha", activationAlpha);
+ tblgen_state.addAttribute("activationBeta", activationBeta);
+ tblgen_state.addAttribute("clip", clip);
+ tblgen_state.addAttribute("inputForget", inputForget);
+ tblgen_state.addTypes(res);
+ }]>,
+
+ OpBuilder<
+ "Builder *builder, OperationState &tblgen_state, Type res,"
+ "Value *X, Value* W, Value* R, Value* H_t, Value* C_t,"
+ "Attribute hiddenSize",
+ [{
+ tblgen_state.addOperands({X, W, R, H_t, C_t});
+ tblgen_state.addAttribute("hiddenSize", hiddenSize);
+ tblgen_state.addTypes(res);
+ }]>
+ ];
+
+ let extraClassDeclaration = [{
+ // get bias operand if present
+ Value* B()
+ {
+ auto varArgs = optionalArgs();
+ return varArgs.begin() != varArgs.end() ? *varArgs.begin() : nullptr;
+ }
+ // get peephole weights operand if present
+ Value* P()
+ {
+ auto varArgs = optionalArgs();
+ auto it = varArgs.begin();
+ it = std::next(it);
+ if (it == varArgs.end())
+ return nullptr;
+ it = std::next(it);
+ return it == varArgs.end() ? *it : nullptr;
+ }
+
+ void setHiddenSize (const Attribute& attr) { this->setAttr("hiddenSize", attr); }
+ void setActivations (const ArrayAttr& attr) { this->setAttr("activation", attr); }
+ void setActivationsAlpha (const ArrayAttr& attr) { this->setAttr("activatiAlpha", attr); }
+ void setActivationsBeta (const ArrayAttr& attr) { this->setAttr("activatiBeta", attr); }
+ void setClip(const Attribute& attr) { this->setAttr("clip", attr); }
+ }];
+}
+
+// LSTM Sequence Op
+def NGLSTMSequenceOp :
+ NG_OneResult_Op<"lstmSeq", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$X, NG_TensorType:$H_t, NG_TensorType:$C_t,
+ NG_TensorType:$S_l, NG_TensorType:$W, NG_TensorType:$R,
+ NG_TensorType:$B, Variadic:$optionalArgs,
+ I64Attr:$hiddenSize,
+ LSTMSeqDirectionsEnumAttr:$direction,
+ DefaultValuedAttr(MLIRLSTMWeightsFormat::IFCO)">:$weightFormat,
+ DefaultValuedAttr:$activations,
+ DefaultValuedAttr:$activationAlpha,
+ DefaultValuedAttr:$activationBeta,
+ DefaultValuedAttr:$clip,
+ DefaultValuedAttr:$inputForget)>
+{
+ let summary = "LSTM Sequence";
+ let description = [{
+
+ Class for lstm sequence node.
+
+ It follows notation and equations defined as in ONNX standard:
+ https://github.com/onnx/onnx/blob/master/docs/Operators.md#LSTM
+
+ See: LSTMCell, RNNCell, GRUCell
+ }];
+
+ let parser = [{ NGRAPH_CHECK(false, "No parser support"); return mlir::failure(); }];
+ let verifier = [{
+ return mlir::success(); /* TBD */
+ }];
- let verifier = [{ return verifyOp(this); }];
+ let extraClassDeclaration = [{
+ void setHiddenSize (const Attribute& attr) { this->setAttr("hiddenSize", attr); }
+ void setActivations (const ArrayAttr& attr) { this->setAttr("activation", attr); }
+ void setActivationsAlpha (const ArrayAttr& attr) { this->setAttr("activatiAlpha", attr); }
+ void setActivationsBeta (const ArrayAttr& attr) { this->setAttr("activatiBeta", attr); }
+ void setClip(const Attribute& attr) { this->setAttr("clip", attr); }
+
+ Value* P()
+ {
+ auto varArgs = optionalArgs();
+ return varArgs.begin() != varArgs.end() ? *varArgs.begin() : nullptr;
+ }
+ }];
+}
+
+// GRU Cell Op
+def NGGRUCellOp :
+ NG_OneResult_Op<"gruCell", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$X, NG_TensorType:$W, NG_TensorType:$R,
+ NG_TensorType:$H_t, Variadic:$optionalArgs,
+ I64Attr:$hiddenSize,
+ DefaultValuedAttr:$activations,
+ DefaultValuedAttr:$activationAlpha,
+ DefaultValuedAttr:$activationBeta,
+ DefaultValuedAttr:$clip,
+ DefaultValuedAttr:$linearBeforeReset)>
+{
+ let summary = "This class represents only single *cell* and not whole GRU *layer*";
+ let description = [{
+ X The input tensor with shape: [batch_size, input_size].
+ W The weight tensor with shape:
+ [gates_count * hidden_size, input_size].
+ R The recurrence weight tensor with shape:
+ [gates_count * hidden_size, hidden_size].
+ H_t The hidden state tensor at current time step with
+ shape: [batch_size, hidden_size].
+ hidden_size The number of hidden units for recurrent cell.
+ B[Optional] The bias tensor for input gate with shape:
+ [2 * gates_count * hidden_size].
+ activations The vector of activation functions used inside
+ recurrent cell.
+ activation_alpha The vector of alpha parameters for activation
+ functions in order respective to activation list.
+ activation_beta The vector of beta parameters for activation functions
+ in order respective to activation list.
+ clip The value defining clipping range [-clip, clip] on
+ input of activation functions.
+ }];
+
+ let parser = [{ NGRAPH_CHECK(false, "No parser support"); return mlir::failure(); }];
+ let verifier = [{ return mlir::success(); /* TBD */ }];
+
+ let builders = [
+ OpBuilder<
+ "Builder *builder, OperationState &tblgen_state, Type res,"
+ "Value *X, Value* W, Value* R, Value* H_t,"
+ "Attribute hiddenSize, ArrayAttr activations,"
+ "ArrayAttr activationAlpha, ArrayAttr activationBeta,"
+ "Attribute clip, Attribute linearBeforeReset", [{
+ tblgen_state.addOperands({X, W, R, H_t});
+ tblgen_state.addAttribute("hiddenSize", hiddenSize);
+ tblgen_state.addAttribute("activations", activations);
+ tblgen_state.addAttribute("activationAlpha", activationAlpha);
+ tblgen_state.addAttribute("activationBeta", activationBeta);
+ tblgen_state.addAttribute("linearBeforeReset", linearBeforeReset);
+ tblgen_state.addTypes(res);
+ }]>,
+
+ OpBuilder<
+ "Builder *builder, OperationState &tblgen_state, Type res,"
+ "Value *X, Value* W, Value* R, Value* H_t,"
+ "Attribute hiddenSize",
+ [{
+ tblgen_state.addOperands({X, W, R, H_t});
+ tblgen_state.addAttribute("hiddenSize", hiddenSize);
+ tblgen_state.addTypes(res);
+ }]>
+ ];
+
+ let extraClassDeclaration = [{
+ void setHiddenSize (const Attribute& attr) { this->setAttr("hiddenSize", attr); }
+ void setActivations (const ArrayAttr& attr) { this->setAttr("activation", attr); }
+ void setActivationsAlpha (const ArrayAttr& attr) { this->setAttr("activatiAlpha", attr); }
+ void setActivationsBeta (const ArrayAttr& attr) { this->setAttr("activatiBeta", attr); }
+ void setLinearBeforeReset(const Attribute& attr) { this->setAttr("linearBeforeReset", attr); }
+
+ // get Bias operand if present
+ Value* P()
+ {
+ auto varArgs = optionalArgs();
+ return varArgs.begin() != varArgs.end() ? *varArgs.begin() : nullptr;
+ }
+ }];
+}
+
+// LayerNorm Op
+// Op produces 3 results when keepStats is true
+// Op is defined with 3 results, 2 of which are invalid/dead if keepStats is false
+def NGLayerNormOp :
+ NG_Op<"layernorm", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Results<(outs NG_TensorType:$res, NG_TensorType:$mean, NG_TensorType:$var)>,
+ Arguments<(ins NG_TensorType:$data, Variadic:$optionalArgs,
+ DefaultValuedAttr:$keepStats,
+ DefaultValuedAttr :$beginNormAxis,
+ DefaultValuedAttr :$epsilon)>
+{
+ let summary = "LayerNorm Op";
+ let description = "Constructs a LayerNorm operation.";
+
+ let builders = [
+ OpBuilder<
+ "Builder *builder, OperationState &tblgen_state, ArrayRef res,"
+ "Value *data, Attribute keepStats, Attribute beginNormAxis, Attribute epsilon", [{
+ tblgen_state.addOperands(data);
+ tblgen_state.addAttribute("keepStats", keepStats);
+ tblgen_state.addAttribute("beginNormAxis", beginNormAxis);
+ tblgen_state.addAttribute("epsilon", epsilon);
+ tblgen_state.addTypes(res);
+ }]>
+ ];
let extraClassDeclaration = [{
- void decompose() {
- //TODO: Call a templatized helper: decompose(this) to do the actual decomposition
+ // get Scale operand if present
+ Value* Scale()
+ {
+ auto varArgs = optionalArgs();
+ return varArgs.begin() != varArgs.end() ? *varArgs.begin() : nullptr;
+ }
+ // get Bias operand if present
+ Value* Bias()
+ {
+ auto varArgs = optionalArgs();
+ auto it = varArgs.begin();
+ it = std::next(it);
+ if (it == varArgs.end())
+ return nullptr;
+ it = std::next(it);
+ return it == varArgs.end() ? *it : nullptr;
}
+
+ void setKeepstats(const Attribute& attr) { this->setAttr("keepStats", attr); }
+ void setBeginNormAxis(const Attribute& attr) { this->setAttr("beginNormAxis", attr);}
+ void setEpsilonAxis(const Attribute& attr) { this->setAttr("epsilon", attr); }
+ }];
+}
+
+
+// LayerNormBackprop Op
+// Scale can be optional, in which case use a constant op of 0
+def NGLayerNormBackpropOp :
+ NG_Op<"layernormBackprop", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Results<(outs NG_TensorType:$d_data, NG_TensorType:$d_scale, NG_TensorType:$d_bias)>,
+ Arguments<(ins NG_TensorType:$data, NG_TensorType:$delta, NG_TensorType:$scale,
+ Variadic:$optionalArgs,
+ DefaultValuedAttr:$beginNormAxis,
+ DefaultValuedAttr:$epsilon)>
+{
+ let summary = "LayerNorm Op";
+ let description = "Constructs an LayerNorm operation.";
+ let builders = [
+ OpBuilder<
+ "Builder *builder, OperationState &tblgen_state, ArrayRef res,"
+ "Value *data, Value *delta, Value *mean, Value *variance,"
+ "Attribute beginNormAxis, Attribute epsilon", [{
+ tblgen_state.addOperands({data, delta, mean, variance});
+ tblgen_state.addAttribute("beginNormAxis", beginNormAxis);
+ tblgen_state.addAttribute("epsilon", epsilon);
+ tblgen_state.addTypes(res);
+ }]>,
+
+ OpBuilder<
+ "Builder *builder, OperationState &tblgen_state, ArrayRef res,"
+ "Value *data, Value *delta, Value *scale,"
+ "Attribute beginNormAxis, Attribute epsilon", [{
+ tblgen_state.addOperands({data, delta, scale});
+ tblgen_state.addAttribute("beginNormAxis", beginNormAxis);
+ tblgen_state.addAttribute("epsilon", epsilon);
+ tblgen_state.addTypes(res);
+ }]>,
+
+ OpBuilder<
+ "Builder *builder, OperationState &tblgen_state, ArrayRef res,"
+ "Value *data, Value *delta,"
+ "Attribute beginNormAxis, Attribute epsilon", [{
+ tblgen_state.addOperands({data, delta});
+ tblgen_state.addAttribute("beginNormAxis", beginNormAxis);
+ tblgen_state.addAttribute("epsilon", epsilon);
+ tblgen_state.addTypes(res);
+ }]>,
+ ];
+
+ let extraClassDeclaration = [{
+ // get Mean operand if present
+ Value* Mean()
+ {
+ auto varArgs = optionalArgs();
+ return varArgs.begin() != varArgs.end() ? *varArgs.begin() : nullptr;
+ }
+ // get Variance operand if present
+ Value* Variance()
+ {
+ auto varArgs = optionalArgs();
+ auto it = varArgs.begin();
+ it = std::next(it);
+ if (it == varArgs.end())
+ return nullptr;
+ it = std::next(it);
+ return it == varArgs.end() ? *it : nullptr;
+ }
+
+ void setBeginNormAxis(const Attribute& attr) { this->setAttr("beginNormAxis", attr);}
+ void setEpsilonAxis(const Attribute& attr) { this->setAttr("epsilon", attr); }
+ }];
+}
+
+// HardSigmoid Op
+def NGHardSigmoid :
+ NG_OneResult_Op<"hardSigmoid", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$data,
+ F32Attr:$alpha, F32Attr:$beta)>
+{
+ let summary = "Hard sigmoid op";
+ let description = [{
+ Parameterized, bounded sigmoid-like, piecewise linear
+ function. min(max(alpha*x + beta, 0), 1)
+ }];
+
+ let extraClassDeclaration = [{
+ void setAlpha(const Attribute& attr) { this->setAttr("alpha", attr); }
+ void setBeta(const Attribute& attr) { this->setAttr("beta", attr); }
+ }];
+}
+
+// Gemm Op
+def NGGemmOp :
+ NG_OneResult_Op<"gemm", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$A, NG_TensorType:$B, NG_TensorType:$C,
+ DefaultValuedAttr:$alpha,
+ DefaultValuedAttr:$beta,
+ DefaultValuedAttr:$transA,
+ DefaultValuedAttr:$transB)>
+{
+ let summary = "Gemm Op";
+ let description = [{
+ A' = transpose(A) if transA else A
+ B' = transpose(B) if transB else B
+ Compute Y = alpha * A' * B' + beta * C
+ }];
+
+ let extraClassDeclaration = [{
+ void setAlpha(const Attribute& attr) { this->setAttr("alpha", attr);}
+ void setBeta(const Attribute& attr) { this->setAttr("beta", attr); }
+
+ void setTransA(const Attribute& attr) { this->setAttr("transA", attr); }
+ void setTransB(const Attribute& attr) { this->setAttr("transB", attr); }
+ }];
+}
+
+// GroupConv Op
+def NGGroupConvOp :
+ NG_OneResult_Op<"groupConv", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$images, NG_TensorType:$filters,
+ I64ArrayAttr:$strides,
+ I64ArrayAttr:$padBelow,
+ I64ArrayAttr:$padAbove,
+ I64Attr:$groups,
+ DefaultValuedAttr(MLIRPadType::EXPLICIT)">:$padType)>
+{
+ let summary = "Group Convolution Op";
+ let description = [{
+ Group Convolution
+ }];
+
+ let builders = [
+ // Builder without padType
+ OpBuilder<
+ "Builder *builder, OperationState &tblgen_state, Type res, Value *images,"
+ "Value *filters, ArrayAttr strides, ArrayAttr padBelow, ArrayAttr padAbove,"
+ "Attribute groups",
+ [{
+ tblgen_state.addOperands({images, filters});
+ tblgen_state.addAttribute("strides", strides);
+ tblgen_state.addAttribute("padBelow", padBelow);
+ tblgen_state.addAttribute("padAbove", padAbove);
+ tblgen_state.addAttribute("groups", groups);
+ tblgen_state.addTypes(res);
+ }]>
+ ];
+
+ let extraClassDeclaration = [{
+ void setStrides(const ArrayAttr& attr) { this->setAttr("strides", attr); }
+ void setPadAbove(const ArrayAttr& attr) { this->setAttr("padAbove", attr); }
+ void setPadBelow(const ArrayAttr& attr) { this->setAttr("padBelow", attr); }
+ void setPadType(const Attribute& attr) { this->setAttr("padType", attr); }
+ }];
+}
+
+// GroupConvTranspose Op
+def NGGroupConvTransposeOp :
+ NG_OneResult_Op<"groupConvTranspose", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$images, NG_TensorType:$filters,
+ I64ArrayAttr:$strides, I64ArrayAttr:$padBelow, I64ArrayAttr:$padAbove,
+ I64ArrayAttr:$outputPad,
+ DefaultValuedAttr:$groups,
+ DefaultValuedAttr(MLIRPadType::EXPLICIT)">:$padType,
+ I64ArrayAttr:$outputShape)>
+{
+ let summary = "Group Transpose Convolution (Deconvolution)";
+ let description = [{
+ images The node producing input images data.
+ filters The node producing filters data.
+ strides The strides along each feature axis.
+ padBelow The padding added at the beggining of each feature axis.
+ padAbove The padding added at the end of each feature axis.
+ outputPad The zero-padding (adjustment) added to one side of the
+ output.
+ groups The number of groups the input channels and output
+ channels are divided into.
+ padType The provided padding type.
+ outputShape The output shape. When provided padding values are
+ automatically inferred.
+ }];
+
+ let builders = [
+ OpBuilder<"Builder *builder, OperationState &tblgen_state, Type res,"
+ "Value *images, Value *filters, Attribute groups", [{
+ tblgen_state.addOperands({images, filters});
+ tblgen_state.addAttribute("groups", groups);
+ tblgen_state.addTypes(res);
+ }]>,
+ OpBuilder<"Builder *builder, OperationState &tblgen_state, Type res,"
+ "Value *images, Value *filters", [{
+ tblgen_state.addOperands({images, filters});
+ tblgen_state.addTypes(res);
+ }]>,
+ OpBuilder<"Builder *builder, OperationState &tblgen_state, Type res,"
+ "Value *images, Value *filters, ArrayAttr strides,"
+ "ArrayAttr outputPad, ArrayAttr outputShape,"
+ "Attribute groups", [{
+ tblgen_state.addOperands({images, filters});
+ tblgen_state.addAttribute("strides", strides);
+ tblgen_state.addAttribute("outputPad", outputPad);
+ tblgen_state.addAttribute("outputShape", outputShape);
+ tblgen_state.addAttribute("groups", groups);
+ }]>,
+ OpBuilder<"Builder *builder, OperationState &tblgen_state, Type res,"
+ "Value *images, Value *filters,"
+ "ArrayAttr outputShape, Attribute groups", [{
+ tblgen_state.addOperands({images, filters});
+ tblgen_state.addAttribute("outputShape", outputShape);
+ tblgen_state.addAttribute("groups", groups);
+ }]>
+ ];
+
+ let extraClassDeclaration = [{
+ void setStrides(const ArrayAttr& attr) { this->setAttr("strides", attr); }
+ void setPadAbove(const ArrayAttr& attr) { this->setAttr("padAbove", attr); }
+ void setPadBelow(const ArrayAttr& attr) { this->setAttr("padBelow", attr); }
+ void setPadType(const Attribute& attr) { this->setAttr("padType", attr); }
+ void setOutputPad(const ArrayAttr& attr) { this->setAttr("outputPad", attr);}
+ void setOutputShape(const ArrayAttr& attr){ this->setAttr("outputShape", attr);}
+ }];
+}
+
+
+// GRN Op
+def NGGRNOp :
+ NG_OneResult_Op<"grn", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$data,
+ DefaultValuedAttr:$bias)>
+{
+ let summary = "GRN Op";
+ let description = [{
+ Global Response Normalization with L2 norm (across channels only)
+ data - Node producing the input tensor
+ bias - The bias added to the variance.
+ }];
+
+ let extraClassDeclaration = [{
+ void setBias(const Attribute& attr) { this->setAttr("bias", attr); }
}];
}
+
+// Clamp Op
+def NGClampOp :
+ NG_OneResult_Op<"clamp", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$data, F64Attr:$min, F64Attr:$max)>
+{
+ let summary = "Clamp Op";
+ let description = [{
+ Performs a clipping operation on all elements of the input node
+
+ All input values that are outside of the range are set to 'min' or 'max'
+ depending on which side of the range they are. The values that fall into
+ this range remain unchanged.
+ }];
+
+ let extraClassDeclaration = [{
+ void setMin(const Attribute& attr) { this->setAttr("min", attr); }
+ void setMax(const Attribute& attr) { this->setAttr("max", attr); }
+ }];
+}
+
+// Gelu Op
+def NGGeluOp :
+ NG_OneResult_Op<"gelu", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$data)>
+{
+ let summary = "Gelu Op";
+ let description = [{
+ Gaussian Error Linear Unit
+ f(x) = 0.5 * x * (1 + erf( x / sqrt(2) )
+ }];
+}
+
+// GeluBackpropFactor Op
+def NGGeluBackpropFactorOp :
+ NG_OneResult_Op<"geluBackpropFactor", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$data)>
+{
+ let summary = "Gelu Backprop Op";
+ let description = [{
+ Backprop for Gelu(x) is GeluBackprop(x) * delta
+ }];
+}
+
+// Elu Op
+def NGEluOp :
+ NG_OneResult_Op<"elu", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$data, F64Attr:$alpha)>
+{
+ let summary = "Elu Op";
+ let description = [{
+ Exponential Linear Unit
+ x < 0 => f(x) = alpha * (exp(x) - 1.)
+ x >= 0 => f(x) = x
+ }];
+
+ let extraClassDeclaration = [{
+ void setAlpha(const Attribute& attr) { this->setAttr("alpha", attr); }
+ }];
+}
+
+// FakeQuant Op
+def NGFakeQuantOp :
+ NG_OneResult_Op<"fakeQuant", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$data, NG_TensorType:$inputLow, NG_TensorType:$inputHigh,
+ NG_TensorType:$outputLow, NG_TensorType:$outputHigh,
+ I64Attr:$levels,
+ DefaultValuedAttr(MLIRPadType::EXPLICIT)">:$autoBroadcast)>
+{
+ let summary = "Op performing element-wise linear quantization.";
+ let description = [{
+ Input floating point values are quantized into a discrete
+ set of floating point values.
+
+ Implementation This class creates a node which performs the following
+ operation:
+ round((data - input_low) / (input_high - input_low) * (levels-1)) /
+ (levels-1) * (output_high - output_low) + output_low
+ }];
+
+ let extraClassDeclaration = [{
+ void setLevels(const Attribute& attr) { this->setAttr("levels", attr); }
+ void setAutoBroadcast(const Attribute& attr) { this->setAttr("autoBroadcast", attr); }
+ }];
+}
+
+// DepthToSpace Op
+def NGDepthToSpaceOp :
+ NG_OneResult_Op<"depthToSpace", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$data,
+ DefaultValuedAttr:$blockSize,
+ DepthSpaceModeEnumAttr:$mode)>
+{
+ let summary = "DepthToSpace Op";
+ let description = [{
+ DepthToSpace permutes data from the depth dimension of the input blob into
+ spatial dimensions.
+ Values from the depth dimension (assuming NCHW layout) are moved in
+ spatial blocks to the height and width dimensions.
+ Output node produces a tensor with shape:
+ [N, C/(blocksize * blocksize), H * blocksize, W * blocksize]
+ }];
+
+ let extraClassDeclaration = [{
+ void setBlockSize(const Attribute& attr) { this->setAttr("blockSize", attr);}
+ void setMode(const Attribute& attr) { this->setAttr("mode", attr); }
+ }];
+}
+
+// ConvolutionBias Op
+def NGConvBiasOp :
+ NG_OneResult_Op<"convBias", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$images, NG_TensorType:$filters, NG_TensorType:$bias,
+ I64ArrayAttr:$strides, I64ArrayAttr:$padBelow, I64ArrayAttr:$padAbove,
+ DefaultValuedAttr:$withRelu)>
+{
+ let summary = "Convolution Bias Op";
+ let description = "Convolution + bias forward prop for batched convolution operation.";
+
+ let builders = [
+ OpBuilder<
+ "Builder *builder, OperationState &tblgen_state, Type res,"
+ "Value *images, Value *filters, Value *bias, Attribute withRelu", [{
+ tblgen_state.addOperands({images, filters, bias});
+ tblgen_state.addAttribute("withRelu", withRelu);
+ tblgen_state.addTypes(res);
+ }]>,
+
+ OpBuilder<
+ "Builder *builder, OperationState &tblgen_state, Type res,"
+ "Value *images, Value *filters, Value *bias", [{
+ tblgen_state.addOperands({images, filters, bias});
+ tblgen_state.addTypes(res);
+ }]>
+ ];
+
+ let extraClassDeclaration = [{
+ void setStrides(const ArrayAttr& attr) { this->setAttr("strides", attr); }
+ void setPadAbove(const ArrayAttr& attr) { this->setAttr("padAbove", attr); }
+ void setPadBelow(const ArrayAttr& attr) { this->setAttr("padBelow", attr); }
+ void setWithRelu(const Attribute& attr) {this->setAttr("withRelu", attr); }
+ }];
+}
+
+// ConvBiasBackpropFiltersBias Op
+def NGConvBiasBackpropFiltersBias :
+ NG_Op<"convBiasBackpropFiltersBias", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Results<(outs NG_TensorType:$filter, NG_TensorType:$bias)>,
+ Arguments<(ins NG_TensorType:$images, NG_TensorType:$outputDelta,
+ I64ArrayAttr:$filtersShape, I64ArrayAttr:$biasShape,
+ I64ArrayAttr:$strides, I64ArrayAttr:$padBelow, I64ArrayAttr:$padAbove)>
+{
+ let extraClassDeclaration = [{
+ void setFiltersShape(const ArrayAttr& attr) { this->setAttr("filtersShape", attr); }
+ void setBiasShape(const ArrayAttr& attr) { this->setAttr("biasShape", attr); }
+
+ void setStrides(const ArrayAttr& attr) { this->setAttr("strides", attr); }
+ void setPadAbove(const ArrayAttr& attr) { this->setAttr("padAbove", attr); }
+ void setPadBelow(const ArrayAttr& attr) { this->setAttr("padBelow", attr); }
+ }];
+}
+
+// ConvBiasAdd Op
+def NGConvBiasAddOp :
+ NG_OneResult_Op<"convBiasAdd", [NoSideEffect, DeclareOpInterfaceMethods]>,
+ Arguments<(ins NG_TensorType:$images, NG_TensorType:$filters,
+ NG_TensorType:$bias, NG_TensorType:$sumInput,
+ I64ArrayAttr:$strides, I64ArrayAttr:$padBelow, I64ArrayAttr:$padAbove,
+ DefaultValuedAttr:$withRelu)>
+{
+ let summary = "Convolution Bias Add Op";
+ let description = "Convolution + bias + add forward prop for batched convolution operation.";
+
+ let extraClassDeclaration = [{
+ void setStrides(const ArrayAttr& attr) { this->setAttr("strides", attr); }
+ void setPadAbove(const ArrayAttr& attr) { this->setAttr("padAbove", attr); }
+ void setPadBelow(const ArrayAttr& attr) { this->setAttr("padBelow", attr); }
+ void setWithRelu(const Attribute& attr) {this->setAttr("withRelu", attr); }
+ }];
+}
+
+
#endif //NG_FUSED_OPS
diff --git a/src/contrib/mlir/core/ngraph_dialect/ops.cpp b/src/contrib/mlir/core/ngraph_dialect/ops.cpp
index a0b5e76e52e..690efd01f08 100644
--- a/src/contrib/mlir/core/ngraph_dialect/ops.cpp
+++ b/src/contrib/mlir/core/ngraph_dialect/ops.cpp
@@ -335,3 +335,100 @@ namespace mlir
#define GET_OP_CLASSES
#include "ops.cpp.inc"
}
+
+// Fused Ops decompose
+// Stubs for now
+// TODO: Implement and move to another file
+void mlir::NGSpaceToDepthOp::decompose()
+{
+}
+void mlir::NGSplitOp::decompose()
+{
+}
+void mlir::NGScaleShiftOp::decompose()
+{
+}
+void mlir::NGUnSqueezeOp::decompose()
+{
+}
+void mlir::NGSquaredDiffOp::decompose()
+{
+}
+void mlir::NGSqueezeOp::decompose()
+{
+}
+void mlir::NGShuffleChannelsOp::decompose()
+{
+}
+void mlir::NGRNNCellOp::decompose()
+{
+}
+void mlir::NGFakeQuantOp::decompose()
+{
+}
+void mlir::NGMVN::decompose()
+{
+}
+void mlir::NGHardSigmoid::decompose()
+{
+}
+void mlir::NGGRNOp::decompose()
+{
+}
+void mlir::NGNormalizeL2Op::decompose()
+{
+}
+void mlir::NGConvBiasBackpropFiltersBias::decompose()
+{
+}
+void mlir::NGPrelu::decompose()
+{
+}
+void mlir::NGLayerNormBackpropOp::decompose()
+{
+}
+void mlir::NGGemmOp::decompose()
+{
+}
+void mlir::NGClampOp::decompose()
+{
+}
+void mlir::NGGroupConvTransposeOp::decompose()
+{
+}
+void mlir::NGConvBiasOp::decompose()
+{
+}
+void mlir::NGConvBiasAddOp::decompose()
+{
+}
+void mlir::NGGRUCellOp::decompose()
+{
+}
+void mlir::NGGroupConvOp::decompose()
+{
+}
+void mlir::NGGeluOp::decompose()
+{
+}
+void mlir::NGGeluBackpropFactorOp::decompose()
+{
+}
+void mlir::NGLSTMCellOp::decompose()
+{
+}
+void mlir::NGLSTMSequenceOp::decompose()
+{
+}
+void mlir::NGMatMul::decompose()
+{
+}
+void mlir::NGLayerNormOp::decompose()
+{
+}
+void mlir::NGDepthToSpaceOp::decompose()
+{
+}
+void mlir::NGEluOp::decompose()
+{
+}
diff --git a/src/contrib/mlir/core/ngraph_dialect/ops.td b/src/contrib/mlir/core/ngraph_dialect/ops.td
index cb6a729e13d..78e3adb890d 100644
--- a/src/contrib/mlir/core/ngraph_dialect/ops.td
+++ b/src/contrib/mlir/core/ngraph_dialect/ops.td
@@ -140,7 +140,9 @@ class NG_Terminator_Op traits = []> :
NG_Op,
Arguments<(ins Variadic:$args)>, Results<(outs)> {}
-
+class NG_Variadic_Result_Op traits = []> :
+ NG_Op,
+ Results<(outs Variadic:$args)> {}
// Terminator Ops
def NGReturnOp : NG_Terminator_Op<"return">;
diff --git a/src/contrib/mlir/core/ngraph_dialect/ops_attributes.td b/src/contrib/mlir/core/ngraph_dialect/ops_attributes.td
index 10fe1d00c51..b5e20cbc3ca 100644
--- a/src/contrib/mlir/core/ngraph_dialect/ops_attributes.td
+++ b/src/contrib/mlir/core/ngraph_dialect/ops_attributes.td
@@ -56,7 +56,8 @@ def PadModeEdge : I32EnumAttrCase<"EDGE", 1> ;
def PadModeReflect : I32EnumAttrCase<"REFLECT", 2> ;
def PadModeSymmetric: I32EnumAttrCase<"SYMMETRIC", 3> ;
-def PadModeEnumAttr : I32EnumAttr<"MLIRPadMode", "Padding modes for pad operator",
+def PadModeEnumAttr : I32EnumAttr<"MLIRPadMode",
+ "Padding modes for pad operator",
[PadModeConstant, PadModeEdge, PadModeReflect, PadModeSymmetric]>;
// Sort Types for TopK
@@ -67,4 +68,51 @@ def SortTypeValues : I32EnumAttrCase<"VALUES", 2>;
def SortTypeEnumAttr : I32EnumAttr<"MLIRSortType", "Sort types for topk operator",
[SortTypeNone, SortTypeIndices, SortTypeValues]>;
+// Modes for normalizeL2
+def EpsModeAdd : I32EnumAttrCase<"ADD", 0>;
+def EpsModeMax : I32EnumAttrCase<"MAX", 1>;
+
+def EpsModeEnumAttr : I32EnumAttr<"MLIREpsMode",
+ "Specifies how eps is combined with L2 value",
+ [EpsModeAdd, EpsModeMax]>;
+
+
+def AutoBroadcastNone : I32EnumAttrCase<"NONE", 0>;
+def AutoBroadcastExplicit : I32EnumAttrCase<"EXPLICIT", 1>;
+def AutoBroadcastNumPy : I32EnumAttrCase<"NUMPY", 2>;
+def AutoBroadcastPDPD : I32EnumAttrCase<"PDPD", 3>;
+
+def AutoBroadcastEnumAttr : I32EnumAttr<"MLIRAutoBroadcastMode",
+ "Specifies auto-broadcast for an op",
+ [AutoBroadcastNone, AutoBroadcastExplicit,
+ AutoBroadcastNumPy, AutoBroadcastPDPD]>;
+
+
+def DepthSpaceModeBlocks : I32EnumAttrCase<"BLOCKS_FIRST", 0>;
+def DepthSpaceModeDepth : I32EnumAttrCase<"DEPTH_FIRST", 1>;
+
+def DepthSpaceModeEnumAttr: I32EnumAttr<"MLIRDepthToSpaceMode",
+ "Specifies how the input depth dimension is split to block coordinates",
+ [DepthSpaceModeBlocks, DepthSpaceModeDepth]>;
+
+def LSTMWeightsFormatFICO : I32EnumAttrCase<"FICO", 0>; // IE
+def LSTMWeightsFormatICOF : I32EnumAttrCase<"ICOF", 1>; // PyTorch
+def LSTMWeightsFormatIFCO : I32EnumAttrCase<"IFCO", 2>; // DNNL, TF, MxNet
+def LSTMWeightsFormatIFOC : I32EnumAttrCase<"IFOC", 3>; // Caffe
+def LSTMWeightsFormatIOFC : I32EnumAttrCase<"IOFC", 4>; // ONNX
+
+def LSTMWeightsFormatEnumAttr: I32EnumAttr<"MLIRLSTMWeightsFormat",
+ "LSTM Cell Weights Format",
+ [LSTMWeightsFormatFICO, LSTMWeightsFormatICOF,
+ LSTMWeightsFormatIFCO, LSTMWeightsFormatIFOC,
+ LSTMWeightsFormatIOFC]>;
+
+def LSTMSeqDirectionFWD : I32EnumAttrCase<"FORWARD", 0>;
+def LSTMSeqDirectionRVS : I32EnumAttrCase<"REVERSE", 1>;
+def LSTMSeqDirectionBID : I32EnumAttrCase<"BIDIRECTIONAL", 2>;
+
+def LSTMSeqDirectionsEnumAttr: I32EnumAttr<"MLIRLSTMSeqDirection",
+ "LSTM Sequence Direction",
+ [LSTMSeqDirectionFWD, LSTMSeqDirectionRVS,
+ LSTMSeqDirectionBID]>;
#endif // NG_OP_ATTRIBUTES
diff --git a/src/contrib/mlir/core/ngraph_dialect/ops_v0.td b/src/contrib/mlir/core/ngraph_dialect/ops_v0.td
index 81f409b0338..6ed1fb11413 100644
--- a/src/contrib/mlir/core/ngraph_dialect/ops_v0.td
+++ b/src/contrib/mlir/core/ngraph_dialect/ops_v0.td
@@ -500,7 +500,7 @@ def NGMaxPoolBackPropOp :
}
// OneHot
-def NGOneHOtOp :
+def NGOneHotOp :
NG_OneResult_Op<"oneHot", [NoSideEffect, OpVersion0]>,
Arguments<(ins NG_TensorType :$arg,
I64ArrayAttr :$shape,
@@ -552,7 +552,7 @@ def NGPadOp :
}
// ReplaceSlice
-def NGReplaceSlice :
+def NGReplaceSliceOp :
NG_OneResult_Op<"replaceSlice", [NoSideEffect, OpVersion0]>,
Arguments<(ins NG_TensorType:$arg0,
NG_TensorType :$arg1,
@@ -583,7 +583,7 @@ def NGReplaceSlice :
}
// slice
-def NGSlice :
+def NGSliceOp :
NG_OneResult_Op<"slice", [NoSideEffect, OpVersion0]>,
Arguments<(ins NG_TensorType:$arg,
I64ArrayAttr :$lowerBounds,
@@ -611,7 +611,7 @@ def NGSlice :
}
// reshape
-def NGReshape :
+def NGReshapeOp :
NG_OneResult_Op<"reshape", [NoSideEffect, OpVersion0]>,
Arguments<(ins NG_TensorType:$arg,
I64ArrayAttr :$axisOrder,
@@ -636,7 +636,7 @@ def NGReshape :
}
// softmax
-def NGSoftMax :
+def NGSoftMaxOp :
NG_OneResult_Op<"softmax", [NoSideEffect, OpVersion0]>,
Arguments<(ins NG_TensorType :$arg,
I64ArrayAttr :$axes)>
@@ -655,7 +655,7 @@ def NGSoftMax :
}
// topk
-def NGTopK :
+def NGTopKOp :
NG_OneResult_Op<"topk", [NoSideEffect, OpVersion0]>,
Arguments<(ins NG_TensorType :$arg,
NG_TensorType :$k,
diff --git a/src/contrib/mlir/core/pass/ng_dialect_builder.cpp b/src/contrib/mlir/core/pass/ng_dialect_builder.cpp
index d5855520857..4e731b0bacb 100644
--- a/src/contrib/mlir/core/pass/ng_dialect_builder.cpp
+++ b/src/contrib/mlir/core/pass/ng_dialect_builder.cpp
@@ -46,32 +46,6 @@
#include "ngraph/op/util/index_reduction.hpp"
#include "ngraph/type/element_type.hpp"
-#include "contrib/mlir/utils.hpp"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
// Defines a new LLVM debug type for this file to be used by LLVM_DEBUG macro.
#define DEBUG_TYPE "mlir-compiler"
@@ -264,6 +238,7 @@ mlir::Type NgDialectConversionPass::getMlirType(const element::Type& type)
{
case ngraph::element::Type_t::undefined:
case ngraph::element::Type_t::dynamic:
+ case ngraph::element::Type_t::u1:
default: NGRAPH_CHECK(false, "MLIR: Unsupported NGraph types"); break;
case ngraph::element::Type_t::bf16: return mlir::NGFloatType::getBF16(m_context);
case ngraph::element::Type_t::f16: return mlir::NGFloatType::getF16(m_context);
diff --git a/src/contrib/mlir/core/pass/ng_dialect_builder.hpp b/src/contrib/mlir/core/pass/ng_dialect_builder.hpp
index 6883be4ed53..ce2e9d34625 100644
--- a/src/contrib/mlir/core/pass/ng_dialect_builder.hpp
+++ b/src/contrib/mlir/core/pass/ng_dialect_builder.hpp
@@ -20,21 +20,13 @@
#pragma once
#include "contrib/mlir/core/compiler.hpp"
-#include "contrib/mlir/runtime/cpu/memory_manager.hpp"
+
#include "ngraph/check.hpp"
#include "ngraph/descriptor/tensor.hpp"
#include "ngraph/node.hpp"
-#include
-#include
-#include
-#include
#include
-#include
-#include
-#include
-
using namespace ngraph::runtime::ngmlir;
namespace ngraph
diff --git a/src/contrib/mlir/runtime/cpu/cpu_runtime.cpp b/src/contrib/mlir/runtime/cpu/cpu_runtime.cpp
index 8598ad2f6e5..7723f7e11c6 100644
--- a/src/contrib/mlir/runtime/cpu/cpu_runtime.cpp
+++ b/src/contrib/mlir/runtime/cpu/cpu_runtime.cpp
@@ -30,8 +30,8 @@
#include
#include
#include
+#include
#include
-#include
#include
#include
@@ -81,7 +81,7 @@ void MLIRCPURuntime::bindArguments(std::vector& externalTensors)
{
NGRAPH_CHECK(m_module, "MLIR module is not ready.");
- mlir::FuncOp func = m_module->lookupSymbol("main");
+ auto func = m_module->lookupSymbol("main");
NGRAPH_CHECK(func && !func.getBlocks().empty(), "Function not found");
// Set external arguments
@@ -90,7 +90,7 @@ void MLIRCPURuntime::bindArguments(std::vector& externalTensors)
// Create list with a type-erased double pointer for each invocation arguments.
// We currently use 'allocateMemrefArgs', which creates the arguments list per call ABI (see
// comment below).
- // StaticFloatMemref is just a struct with the actual pointer to the data.
+ // StaticMemRef is just a struct with the actual pointer to the data.
auto expectedArguments = allocateMemrefArgs();
NGRAPH_CHECK(expectedArguments.size(), "Arguments can't be created");
@@ -102,7 +102,7 @@ void MLIRCPURuntime::bindArguments(std::vector& externalTensors)
// Assign external tensor pointers to invocation arguments.
for (size_t i = 0, numArgs = m_invokeArgs.size(); i < numArgs; ++i)
{
- auto* memRefArg = *(reinterpret_cast(m_invokeArgs[i]));
+ auto* memRefArg = *(reinterpret_cast(m_invokeArgs[i]));
memRefArg->data = reinterpret_cast((*m_externalTensors)[i]);
}
}
@@ -129,18 +129,18 @@ void MLIRCPURuntime::cleanup()
// Free void double pointer arguments without freeing external tensor data.
for (auto* arg : m_invokeArgs)
{
- auto* memRefArg = *(reinterpret_cast(arg));
+ auto* memRefArg = *(reinterpret_cast(arg));
free(memRefArg);
free(arg);
}
}
// The current call ABI takes a single arg pointer (argPtr) pointing to a list of args.
-// Each arg is a pointer to a StaticFloatMemRef which contains a data pointer
+// Each arg is a pointer to a StaticMemRef which contains a data pointer
//
// The args are laid out as follows
-// argPtr-> arg[0]-> StaticFloatMemRef ->
-// arg[1]-> StaticFloatMemRef ->
+// argPtr-> arg[0]-> StaticMemRef ->
+// arg[1]-> StaticMemRef ->
// ...
SmallVector MLIRCPURuntime::allocateMemrefArgs()
{
@@ -148,20 +148,18 @@ SmallVector MLIRCPURuntime::allocateMemrefArgs()
for (auto i = 0; i < m_externalTensors->size(); i++)
{
auto descriptor = allocateMemrefDescriptor();
- mlir::StaticFloatMemRef** arg =
- reinterpret_cast(malloc(sizeof(mlir::StaticFloatMemRef*)));
+ StaticMemRef** arg = reinterpret_cast(malloc(sizeof(StaticMemRef*)));
*arg = descriptor;
args.push_back(arg);
}
return args;
}
-mlir::StaticFloatMemRef* MLIRCPURuntime::allocateMemrefDescriptor()
+StaticMemRef* MLIRCPURuntime::allocateMemrefDescriptor()
{
- // We only use StaticFloatMemRef because that's what MLIR currently offers.
+ // We only use StaticMemRef because that's what MLIR currently offers.
// We should expand this with different types and dynamic MemRefs
- auto* descriptor =
- reinterpret_cast(malloc(sizeof(mlir::StaticFloatMemRef)));
+ auto* descriptor = reinterpret_cast(malloc(sizeof(StaticMemRef)));
NGRAPH_CHECK(descriptor != nullptr, "NULL MemRef descriptor");
descriptor->data = nullptr;
return descriptor;
diff --git a/src/contrib/mlir/runtime/cpu/cpu_runtime.hpp b/src/contrib/mlir/runtime/cpu/cpu_runtime.hpp
index 65b123d022b..07f9e231f80 100644
--- a/src/contrib/mlir/runtime/cpu/cpu_runtime.hpp
+++ b/src/contrib/mlir/runtime/cpu/cpu_runtime.hpp
@@ -21,7 +21,6 @@
#include
#include
-#include
#include
#include
#include
@@ -34,6 +33,10 @@ namespace ngraph
{
namespace ngmlir
{
+ struct StaticMemRef
+ {
+ void* data;
+ };
/// A CPU Runtime is an MLIR runtime that owns an MLIR context and a module
/// The module should be in LLVM dialect and ready to be lowered via an MLIR
/// ExecutionEngine. The runtime owns the context and must out-live any MLIR
@@ -57,7 +60,7 @@ namespace ngraph
llvm::SmallVector allocateMemrefArgs();
/// Helper to allocate a mem ref object. Handles static shapes only for now.
- mlir::StaticFloatMemRef* allocateMemrefDescriptor();
+ StaticMemRef* allocateMemrefDescriptor();
private:
// Pointers to externally allocated memory for sub-graph's input and output tensors.
diff --git a/src/contrib/mlir/runtime/runtime.hpp b/src/contrib/mlir/runtime/runtime.hpp
index 67e039fb54e..2326202558e 100644
--- a/src/contrib/mlir/runtime/runtime.hpp
+++ b/src/contrib/mlir/runtime/runtime.hpp
@@ -23,7 +23,6 @@
#include
#include
-#include
#include
#include
#include
diff --git a/src/ngraph/CMakeLists.txt b/src/ngraph/CMakeLists.txt
index 0c3db4e4b89..c0bb7b890a8 100644
--- a/src/ngraph/CMakeLists.txt
+++ b/src/ngraph/CMakeLists.txt
@@ -16,6 +16,9 @@
set (SRC
assertion.hpp
+ attribute_adapter.cpp
+ attribute_adapter.hpp
+ attribute_visitor.hpp
autodiff/adjoints.cpp
autodiff/adjoints.hpp
axis_set.cpp
@@ -77,7 +80,10 @@ set (SRC
dimension.hpp
distributed.cpp
distributed.hpp
+ enum_names.hpp
except.hpp
+ factory.cpp
+ factory.hpp
file_util.cpp
file_util.hpp
function.cpp
@@ -132,12 +138,20 @@ set (SRC
op/constant.hpp
op/convert.cpp
op/convert.hpp
+ op/convert_like.cpp
+ op/convert_like.hpp
op/convolution.cpp
op/convolution.hpp
op/cos.cpp
op/cos.hpp
op/cosh.cpp
op/cosh.hpp
+ op/cum_sum.cpp
+ op/cum_sum.hpp
+ op/crop_and_resize.cpp
+ op/crop_and_resize.hpp
+ op/deformable_psroi_pooling.cpp
+ op/deformable_psroi_pooling.hpp
op/dequantize.cpp
op/dequantize.hpp
op/divide.cpp
@@ -207,10 +221,14 @@ set (SRC
op/strided_slice.hpp
op/floor.cpp
op/floor.hpp
+ op/floor_mod.cpp
+ op/floor_mod.hpp
op/gather.cpp
op/gather.hpp
op/gather_nd.cpp
op/gather_nd.hpp
+ op/gather_tree.cpp
+ op/gather_tree.hpp
op/get_output_element.cpp
op/get_output_element.hpp
op/greater.cpp
@@ -259,6 +277,10 @@ set (SRC
op/power.hpp
op/product.cpp
op/product.hpp
+ op/reduce_logical_and.cpp
+ op/reduce_logical_and.hpp
+ op/reduce_logical_or.cpp
+ op/reduce_logical_or.hpp
op/reduce_prod.cpp
op/reduce_prod.hpp
op/reduce_mean.cpp
@@ -315,6 +337,8 @@ set (SRC
op/subtract.hpp
op/sum.cpp
op/sum.hpp
+ op/variadic_split.cpp
+ op/variadic_split.hpp
op/tan.cpp
op/tan.hpp
op/tanh.cpp
@@ -325,10 +349,14 @@ set (SRC
op/topk.hpp
op/xor.cpp
op/xor.hpp
+ op/fused/batch_mat_mul_transpose.cpp
+ op/fused/batch_mat_mul_transpose.hpp
op/fused/clamp.cpp
op/fused/clamp.hpp
op/fused/conv_fused.cpp
op/fused/conv_fused.hpp
+ op/fused/crossentropy.cpp
+ op/fused/crossentropy.hpp
op/fused/hard_sigmoid.cpp
op/fused/hard_sigmoid.hpp
op/fused/depth_to_space.cpp
@@ -351,12 +379,16 @@ set (SRC
op/fused/gru_cell.hpp
op/fused/layer_norm.cpp
op/fused/layer_norm.hpp
+ op/fused/log_softmax.cpp
+ op/fused/log_softmax.hpp
op/fused/lstm_cell.cpp
op/fused/lstm_cell.hpp
op/fused/lstm_sequence.cpp
op/fused/lstm_sequence.hpp
op/fused/matmul.cpp
op/fused/matmul.hpp
+ op/fused/mod.cpp
+ op/fused/mod.hpp
op/fused/mvn.cpp
op/fused/mvn.hpp
op/fused/normalize_l2.cpp
@@ -365,6 +397,8 @@ set (SRC
op/fused/partial_slice.hpp
op/fused/prelu.cpp
op/fused/prelu.hpp
+ op/fused/reciprocal.cpp
+ op/fused/reciprocal.hpp
op/fused/rnn_cell.cpp
op/fused/rnn_cell.hpp
op/fused/scale_shift.cpp
@@ -405,12 +439,16 @@ set (SRC
op/util/fused_op.hpp
op/util/index_reduction.cpp
op/util/index_reduction.hpp
+ op/util/logical_reduction_keep_dims.hpp
+ op/util/logical_reduction_keep_dims.cpp
op/util/logical_reduction.cpp
op/util/logical_reduction.hpp
op/util/rnn_cell_base.cpp
op/util/rnn_cell_base.hpp
op/util/unary_elementwise_arithmetic.cpp
op/util/unary_elementwise_arithmetic.hpp
+ ops.hpp
+ opsets/opset.cpp
partial_shape.cpp
partial_shape.hpp
pass/algebraic_simplification.cpp
@@ -443,6 +481,7 @@ set (SRC
pass/constant_folding_unsqueeze.cpp
pass/constant_folding_shape_of.cpp
pass/constant_folding_slice.cpp
+ pass/constant_folding_strided_slice.cpp
pass/constant_folding_transpose.cpp
pass/constant_folding_unary.cpp
pass/constant_folding.cpp
@@ -555,6 +594,7 @@ set (SRC
type/float16.cpp
type/float16.hpp
type/element_type.cpp
+ type.hpp
util.cpp
util.hpp
validation_util.cpp
@@ -626,7 +666,6 @@ target_compile_definitions(ngraph
PRIVATE
SHARED_LIB_PREFIX="${CMAKE_SHARED_LIBRARY_PREFIX}"
SHARED_LIB_SUFFIX="${CMAKE_SHARED_LIBRARY_SUFFIX}"
- NGRAPH_DLL_EXPORTS
)
if(NGRAPH_LIB_VERSIONING_ENABLE)
set_target_properties(ngraph PROPERTIES
diff --git a/src/ngraph/attribute_adapter.cpp b/src/ngraph/attribute_adapter.cpp
new file mode 100644
index 00000000000..ea7a2a8721f
--- /dev/null
+++ b/src/ngraph/attribute_adapter.cpp
@@ -0,0 +1,225 @@
+//*****************************************************************************
+// Copyright 2017-2019 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//*****************************************************************************
+
+#include
+
+#include "ngraph/attribute_adapter.hpp"
+#include "ngraph/axis_set.hpp"
+#include "ngraph/coordinate.hpp"
+#include "ngraph/coordinate_diff.hpp"
+#include "ngraph/partial_shape.hpp"
+#include "ngraph/shape.hpp"
+#include "ngraph/strides.hpp"
+#include "ngraph/type.hpp"
+#include "ngraph/type/element_type.hpp"
+
+using namespace std;
+using namespace ngraph;
+
+namespace ngraph
+{
+ constexpr DiscreteTypeInfo AttributeAdapter::type_info;
+ const double& AttributeAdapter::get()
+ {
+ if (!m_buffer_valid)
+ {
+ m_buffer = m_value;
+ m_buffer_valid = true;
+ }
+ return m_buffer;
+ }
+
+ void AttributeAdapter::set(const double& value)
+ {
+ m_value = value;
+ m_buffer_valid = false;
+ }
+
+ constexpr DiscreteTypeInfo AttributeAdapter::type_info;
+ const double& AttributeAdapter::get()
+ {
+ if (!m_buffer_valid)
+ {
+ m_buffer = m_value;
+ m_buffer_valid = true;
+ }
+ return m_buffer;
+ }
+
+ void AttributeAdapter::set(const double& value)
+ {
+ m_value = value;
+ m_buffer_valid = false;
+ }
+
+ constexpr DiscreteTypeInfo AttributeAdapter::type_info;
+ const int64_t& AttributeAdapter::get()
+ {
+ if (!m_buffer_valid)
+ {
+ m_buffer = m_value;
+ m_buffer_valid = true;
+ }
+ return m_buffer;
+ }
+
+ void AttributeAdapter::set(const int64_t& value)
+ {
+ m_value = value;
+ m_buffer_valid = false;
+ }
+
+ constexpr DiscreteTypeInfo AttributeAdapter::type_info;
+ const int64_t& AttributeAdapter::get()
+ {
+ if (!m_buffer_valid)
+ {
+ m_buffer = m_value;
+ m_buffer_valid = true;
+ }
+ return m_buffer;
+ }
+
+ void AttributeAdapter::set(const int64_t& value)
+ {
+ m_value = value;
+ m_buffer_valid = false;
+ }
+
+ constexpr DiscreteTypeInfo AttributeAdapter::type_info;
+ const int64_t& AttributeAdapter::get()
+ {
+ if (!m_buffer_valid)
+ {
+ m_buffer = m_value;
+ m_buffer_valid = true;
+ }
+ return m_buffer;
+ }
+
+ void AttributeAdapter::set(const int64_t& value)
+ {
+ m_value = value;
+ m_buffer_valid = false;
+ }
+
+ constexpr DiscreteTypeInfo AttributeAdapter::type_info;
+ const int64_t& AttributeAdapter::get()
+ {
+ if (!m_buffer_valid)
+ {
+ m_buffer = m_value;
+ m_buffer_valid = true;
+ }
+ return m_buffer;
+ }
+
+ void AttributeAdapter::set(const int64_t& value)
+ {
+ m_value = value;
+ m_buffer_valid = false;
+ }
+
+ constexpr DiscreteTypeInfo AttributeAdapter::type_info;
+ const int64_t& AttributeAdapter::get()
+ {
+ if (!m_buffer_valid)
+ {
+ m_buffer = m_value;
+ m_buffer_valid = true;
+ }
+ return m_buffer;
+ }
+
+ void AttributeAdapter::set(const int64_t& value)
+ {
+ m_value = value;
+ m_buffer_valid = false;
+ }
+
+ constexpr DiscreteTypeInfo AttributeAdapter::type_info;
+ const int64_t& AttributeAdapter::get()
+ {
+ if (!m_buffer_valid)
+ {
+ m_buffer = m_value;
+ m_buffer_valid = true;
+ }
+ return m_buffer;
+ }
+
+ void AttributeAdapter::set(const int64_t& value)
+ {
+ m_value = value;
+ m_buffer_valid = false;
+ }
+
+ constexpr DiscreteTypeInfo AttributeAdapter