Commit d3032021 authored by fenglei's avatar fenglei

merge with master

parents 880b8e74 22c4f3fb
......@@ -19,10 +19,15 @@
/doc/ @indie
/doc/examples/mnist_mlp/dist_* @wenzhe-nrv @indie
/README.md @indie
/doc/*/*/frameworks/tensorflow_connect.rst @shresthamalik @avijit-nervana @sayantan-nervana
/doc/*/*/backends/plaidml-ng-api/ @flaub @brianretford @dgkutnic
/doc/*/*/inspection/ @aproctor
/doc/examples/onnx/ @arogowie-intel @tsocha
/README.md @adstraw
project/introduction.rst @adstraw
project/governance.rst @adstraw
/changes.md @indie @diyessi
/INSTALL.md @indie
/CONTRIB.md @indie
project/doc-contributor-README.rst @indie
/licenses/ @diyessi @raramer01 @aslepko
/LICENSE @diyessi @raramer01 @aslepko
......
......@@ -28,3 +28,16 @@ index f10feb20..05f47961 100644
set_property(TARGET ${LIB_NAME} PROPERTY PUBLIC_HEADER ${HEADERS})
target_include_directories(${LIB_NAME} PUBLIC
diff --git a/src/cpu/jit_avx512_common_conv_kernel.cpp b/src/cpu/jit_avx512_common_conv_kernel.cpp
index 1bb98fa43..b8b54401f 100644
--- a/src/cpu/jit_avx512_common_conv_kernel.cpp
+++ b/src/cpu/jit_avx512_common_conv_kernel.cpp
@@ -3055,7 +3055,7 @@ void jit_avx512_common_conv_bwd_weights_kernel_f32::bias_kernel_3d() {
void jit_avx512_common_conv_bwd_weights_kernel_f32
::compute_oh_loop_common()
{
- assert(jcp.harness == harness_mb_reduction);
+ assert(one_of(jcp.harness, harness_mb_reduction, harness_3d_reduction));
int b_pad = jcp.b_pad;
int t_pad = jcp.t_pad;
bool is_dilated = jcp.dilate_h != 0;
......@@ -73,11 +73,13 @@ author = 'Intel Corporation'
# built documents.
#
# The short X.Y version.
version = '0.20'
version = '0.22'
# The Documentation full version, including alpha/beta/rc tags. Some features
# available in the latest code will not necessarily be documented first
release = '0.20.0'
# available in the latest code will not necessarily be documented first.
# rc syntax may be tagged; this documentation supports various rc-naming conventions
release = '0.22.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
......@@ -121,14 +123,15 @@ else:
# borrow this from the zephyr docs theme
html_context = {
# 'show_license': html_show_license, we have a custom footer to attribute
# 'show_license': html_show_license, we have custom footers to attribute
# RTD, WTD, and Sphinx contributors; so we do not enable this
'docs_title': docs_title,
'is_release': is_release,
'theme_logo_only': False,
'current_version': version,
'versions': ( ("latest", "../"),
("0.19.0", "/0.19.0/"), #not yet sure how we'll do this
("0.20.0", "/0.20.0/"), #not yet sure how we'll do this
("0.19.0", "/0.19.0/"),
("0.18.0", "/0.18.0/"),
("0.17.0", "/0.17.0/"),
("0.16.0", "/0.16.0/"),
......@@ -167,7 +170,7 @@ html_sidebars = {
# list of tuples (old_url, new_url) for pages to redirect
# (URLs should be relative to document root, only)
html_redirect_pages = [
('backends', 'backend-support/index'),
('backend-support', 'backends/index'),
('core/core', 'core/overview.rst'),
('core/fusion', 'core/fusion/index'),
('frameworks/mxnet', 'frameworks/mxnet_intg.rst'),
......@@ -177,6 +180,7 @@ html_redirect_pages = [
('inspection/inspection', 'inspection/index'),
('releases/release-notes', 'releases/index'),
# ('getting_started/getting_starting', 'getting_started/index'),
# mv to framework-specific helper directory
('project/project', 'project/index'),
('python_api/', 'python_api/index'),
]
......
......@@ -6,9 +6,10 @@
</span>
<div class="rst-other-versions">
<dl>
<dt>{{ _('Previous Verified Versions') }}</dt>
<dt>{{ _('Previous Versions') }}</dt>
<dd><!-- Until our https://docs.ngraph.ai/ publishing is set up, we link to GitHub -->
<ul>
<li><a href="https://github.com/NervanaSystems/ngraph/releases/tag/v0.20.0">0.20.0-rc.0</a></li>
<li><a href="https://github.com/NervanaSystems/ngraph/releases/tag/v0.19.0-rc.2">0.19.0-rc.2</a></li>
<li><a href="https://github.com/NervanaSystems/ngraph/releases/tag/v0.18.1">0.18.1</a></li>
<li><a href="https://github.com/NervanaSystems/ngraph/releases/tag/v0.17.0-rc.1">0.17.0-rc.1</a></li>
......
......@@ -2407,9 +2407,10 @@ div[class^='highlight'] pre {
}
.rst-content h1 .headerlink:after, .rst-content h2 .headerlink:after, .rst-content .toctree-wrapper p.caption .headerlink:after, .rst-content h3 .headerlink:after, .rst-content h4 .headerlink:after, .rst-content h5 .headerlink:after, .rst-content h6 .headerlink:after, .rst-content dl dt .headerlink:after, .rst-content p.caption .headerlink:after {
visibility: visible;
content: "";
font-family: "NeoSansIntel";
display: inline-block;
background-color: #27ae41;
font-size: 0.93em;
}
.rst-content h1:hover .headerlink, .rst-content h2:hover .headerlink, .rst-content .toctree-wrapper p.caption:hover .headerlink, .rst-content h3:hover .headerlink, .rst-content h4:hover .headerlink, .rst-content h5:hover .headerlink, .rst-content h6:hover .headerlink, .rst-content dl dt:hover .headerlink, .rst-content p.caption:hover .headerlink {
display: inline-block;
......@@ -2727,7 +2728,6 @@ span[id*='MathJax-Span'] {
}
.wy-menu-horiz:before, .wy-menu-horiz:after {
display: table;
content: "";
}
.wy-menu-horiz:after {
clear: both;
......
format_release_notes.rst
Release Notes
#############
This is the `Release Notes` template for latest nGraph Compiler stack
release versioning.
We are pleased to announce the release of version |version|.
What's new?
-----------
Additional functionality included with this release:
What's updated?
---------------
The following sections provide detailed lists of major updates/removals
by component:
Core
~~~~
Frameworks
~~~~~~~~~~
Backends
~~~~~~~~
Visualization Tools
~~~~~~~~~~~~~~~~~~~
Other
~~~~~
.. backend-support/tensor-api/index.rst:
Tensor
======
.. doxygenclass:: ngraph::runtime::Tensor
:project: ngraph
:members:
.. backend-support/backend-api/index.rst:
.. backends/backend-api/index.rst:
Backend
......
.. backend-support/cpp-api.rst:
.. backends/cpp-api.rst:
Backend APIs
############
......@@ -10,14 +10,13 @@ Backend APIs
executable-api/index
hosttensor-api/index
plaidml-ng-api/index
tensor-api/index
As of version ``0.15``, there is a new backend API to work with functions that
can be compiled as a runtime ``Executable``. Where previously ``Backend`` used a
``shared_ptr<Function>`` as the handle passed to the ``call`` method to execute
a compiled object, the addition of the ``shared_ptr<Executable>`` object has
more direct methods to actions such as ``validate``, ``call``, ``get_performance_data``, and so on. This new API permits any executable to be saved or loaded *into* or
more direct methods to actions such as ``validate``, ``call``, ``get_performance_data``,
and so on. This new API permits any executable to be saved or loaded *into* or
*out of* storage and makes it easier to distinguish when a Function is compiled,
thus making the internals of the ``Backend`` and ``Executable`` easier to
implement.
.. backend-support/executable-api/index.rst:
.. backends/executable-api/index.rst:
Executable
......
.. backend-support/hosttensor-api/index.rst:
.. backends/hosttensor-api/index.rst:
HostTensor
......
.. backend-support/index.rst
.. backends/index.rst
About backends
##############
#################################
Developer Resources for Backends
#################################
* :ref:`what_is_backend`
* :ref:`how_to_use`
......
.. plaidml-ng-api/index.rst:
.. backends/plaidml-ng-api/index.rst:
PlaidML from nGraph
......
......@@ -73,11 +73,11 @@ author = 'Intel Corporation'
# built documents.
#
# The short X.Y version.
version = '0.20'
version = '0.21'
# The Documentation full version, including alpha/beta/rc tags. Some features
# available in the latest code will not necessarily be documented first
release = '0.20.0'
release = '0.21.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
......@@ -105,6 +105,8 @@ todo_include_todos = True
# -- Options for HTML output ----------------------------------------------
html_title = "Documentation for the nGraph Library and Compiler stack"
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
......@@ -114,7 +116,7 @@ html_theme = 'ngraph_theme'
# further. For a list of options available for each theme, see the
# documentation.
# html_theme_options = {}
html_logo = '../ngraph_theme/static/favicon.ico'
html_logo = '../ngraph_theme/static/logo.png'
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
......@@ -152,11 +154,11 @@ htmlhelp_basename = 'IntelnGraphlibrarydoc'
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
......@@ -171,11 +173,10 @@ latex_elements = {
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'nGraphCompilerStack.tex', 'nGraph Compiler Stack Documentation',
'Intel Corporation', 'manual'),
(master_doc, 'nGraphCompilerStack.tex', u'nGraph Compiler Stack Documentation',
u'Intel Corporation', 'manual'),
]
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
......@@ -201,23 +202,7 @@ breathe_projects = {
}
rst_epilog = u"""
.. |codename| replace:: Intel nGraph
.. |project| replace:: Intel nGraph Library
.. |InG| replace:: Intel® nGraph
.. |nGl| replace:: nGraph library
.. |copy| unicode:: U+000A9 .. COPYRIGHT SIGN
:ltrim:
.. |deg| unicode:: U+000B0 .. DEGREE SIGN
:ltrim:
.. |plusminus| unicode:: U+000B1 .. PLUS-MINUS SIGN
:rtrim:
.. |micro| unicode:: U+000B5 .. MICRO SIGN
:rtrim:
.. |trade| unicode:: U+02122 .. TRADEMARK SIGN
:ltrim:
.. |reg| unicode:: U+000AE .. REGISTERED TRADEMARK SIGN
:ltrim:
.. include:: /replacements.txt
"""
# -- autodoc Extension configuration --------------------------------------
......
......@@ -143,7 +143,7 @@ update computation for ``N`` will be given by the node
The different update nodes will share intermediate computations. So to
get the updated values for the weights as computed with the specified
:doc:`backend <../../backend-support/index>`:
:doc:`backend <../../backends/index>`:
.. literalinclude:: ../../../../examples/mnist_mlp/mnist_mlp.cpp
:language: cpp
......
......@@ -126,7 +126,7 @@ There are two backends for the CPU: the optimized ``"CPU"`` backend, which uses
the `Intel MKL-DNN`_, 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 <../../backend-support/index>`
See the documentation on :doc:`runtime options for various backends <../../backends/index>`
for additional details.
To continue with our original example and select the ``"CPU_Backend"``:
......@@ -175,7 +175,7 @@ the three parameters and the return value.
Each tensor is a shared pointer to a :term:`Tensorview`, which is the interface
backends implement for tensor use. When there are no more references to the
tensor view, it will be freed when convenient for the backend. See the
:doc:`../../backend-support/cpp-api` documentation for details on how to work
:doc:`../../backends/cpp-api` documentation for details on how to work
with ``Tensor``.
......
......@@ -45,7 +45,7 @@ everything at once; if an `ngraph_dist` is already installed on your system,
skip ahead to the next section, :ref:`install_ngonnx`.
#. Install prerequisites for the system and install nGraph as ``ngraph_dist``:
#. Install prerequisites for the system and install nGraph as ``ngraph_dist``.
.. code-block:: console
......@@ -54,7 +54,7 @@ skip ahead to the next section, :ref:`install_ngonnx`.
$ apt install build-essential cmake curl clang-3.9 git zlib1g zlib1g-dev libtinfo-dev
$ git clone https://github.com/NervanaSystems/ngraph.git
$ cd ngraph && mkdir build
$ cd build && cmake ../ -DCMAKE_INSTALL_PREFIX=~/ngraph_dist -DNGRAPH_USE_PREBUILT_LLVM=TRUE
$ cd build && cmake ../ -DCMAKE_INSTALL_PREFIX=~/ngraph_dist
$ make install
#. Build the Python package (binary wheel) for ngraph and set up an env for ONNX;
......@@ -77,8 +77,10 @@ skip ahead to the next section, :ref:`install_ngonnx`.
.. code-block:: console
(onnx)$ pip install -U python/dist/ngraph-0.9.0-cp36-cp36m-linux_x86_64.whl
(onnx)$ pip install -U python/dist/ngraph-[version]-cp36-cp36m-linux_x86_64.whl
Where ``[version]`` is the version number of the nGraph Python module
you see in that directory.
#. Confirm ``ngraph`` is properly installed through a Python interpreter:
......
......@@ -12,7 +12,7 @@ Pattern matcher
The nGraph Compiler is an optimizing compiler. As such, it provides a way to
capture a given :term:`function graph` and perform a series of optimization
passes over that graph. The result is a semantically-equivalent graph that, when
executed using any :doc:`backend <../../backend-support/index>`, has optimizations
executed using any :doc:`backend <../../backends/index>`, has optimizations
inherent at the hardware level: superior runtime characteristics to increase
training performance or reduce inference latency.
......
......@@ -6,7 +6,7 @@ Overview: Optimize graphs with nGraph Compiler fusions
The nGraph Compiler is an optimizing compiler. As such, it provides a way to
capture a given :term:`function graph` and perform a series of optimization
passes over that graph. The result is a semantically-equivalent graph that, when
executed using any :doc:`backend <../../backend-support/index>`, has
executed using any :doc:`backend <../../backends/index>`, has
hardware-agnostic *and* hardware-specific optimizations, providing superior
runtime characteristics to increase training performance or reduce inference
latency.
......
......@@ -15,8 +15,9 @@ each of these briefly to get started.
A framework bridge interfaces with the "frontend" Core API. A framework bridge
is a component that sits between a framework like TensorFlow or MXNet, and the
nGraph Core frontend API. A framework bridge does two things: first, it
translates a framework's operations into graphs in nGraph’s in-memory :abbr:`Intermediary Representation (IR)`. Second, it executes the nGraph IR graphs via
the backend execution interface.
translates a framework's operations into graphs in nGraph’s in-memory
:abbr:`Intermediary Representation (IR)`. Second, it executes the nGraph IR
graphs via the backend execution interface.
The details of bridge implementation vary from framework to framework, but there
are some common patterns: a fairly typical example for a graph-based framework
......@@ -59,16 +60,14 @@ descriptions:
.. csv-table::
:header: "Namespace", "Description", "Location in Repo", "Docs"
:widths: 23, 53, 13, 23
:escape: ~
``ngraph``, The Intel nGraph C++ API, `ngraph`_, Implicit namespace omitted from most API documentation
``ngraph``, The Intel nGraph C++ API, ngraph, Implicit namespace omitted from most API documentation
``builder``, "Convenience functions that create additional graph nodes to implement commonly-used recipes; for example, auto-broadcast", `builder`_, Coming Soon
``descriptor``, Descriptors are compile-time representations of objects that will appear at run-time, `descriptor`_, Coming Soon
``op``, Ops used in graph construction, `op`_, :doc:`../ops/index`
``runtime``, The objects and methods used for executing the graph, `runtime`_, :doc:`../backend-support/cpp-api`
``runtime``, The objects and methods used for executing the graph, `runtime`_, :doc:`../backends/cpp-api`
.. _ngraph: https://github.com/NervanaSystems/ngraph/tree/master/src/ngraph
.. _builder: https://github.com/NervanaSystems/ngraph/tree/master/src/ngraph/builder
.. _descriptor: https://github.com/NervanaSystems/ngraph/tree/master/src/ngraph/descriptor
.. _op: https://github.com/NervanaSystems/ngraph/tree/master/src/ngraph/op
......
......@@ -19,6 +19,15 @@ something like:
export LD_LIBRARY_PATH=path/to/ngraph_dist/lib/
Find or display nGraph Version
-------------------------------
.. code-block:: console
python3 -c "import ngraph as ng; print('nGraph version: ',ng.__version__)";
FMV
---
......
.. frameworks/index.rst:
Current framework integrations
==============================
Connect a framework
===================
.. toctree::
:maxdepth: 1
......@@ -12,7 +12,6 @@ Current framework integrations
paddle_integ.rst
validated/testing-latency.rst
A framework is "supported" when there is a framework :term:`bridge` that can be
cloned from one of our GitHub repos and built to connect to nGraph device
backends while maintaining the framework's programmatic or user interface. Bridges
......
......@@ -13,33 +13,39 @@
.. limitations under the License.
.. ---------------------------------------------------------------------------
.. This documentation is available online at
.. https://ngraph.nervanasys.com/docs/latest
######################
nGraph Compiler stack
######################
nGraph is an open-source graph compiler for :abbr:`Artificial Neural Networks (ANNs)`.
The nGraph Compiler stack provides an inherently efficient graph-based compilation
infrastructure designed to be compatible with many upcoming
:abbr:`Application-Specific Integrated Circuits (ASICs)`, like the Intel® Nervana™
Neural Network Processor (Intel® Nervana™ NNP), while also unlocking a massive
performance boost on any existing hardware targets for your neural network: both
GPUs and CPUs. Using its flexible infrastructure, you will find it becomes much
easier to create Deep Learning (DL) models that can adhere to the "write once,
run anywhere" mantra that enables your AI solutions to easily go from concept to
production to scale.
.. _ngraph_home:
.. only:: release
nGraph Compiler stack documentation for version |version|.
Documentation for the latest (master) development branch can be found
at https://ngraph.nervanasys.com/docs/latest
.. https://docs.ngraph.ai/
.. only:: (development or daily)
nGraph Compiler stack documentation for the master tree under development
(version |version|).
For information about the releases, see the :doc:`../project/release-notes`.
The nGraph Library and Compiler stack are provided under the `Apache 2.0 license`_
(found in the LICENSE file in the project's `GitHub repo`_). It may also import
or reference packages, scripts, and other files that use licensing.
.. _Apache 2.0 license: https://github.com/NervanaSystems/ngraph/blob/master/LICENSE
.. _GitHub repo: https://github.com/NervanaSystems/ngraph
Frameworks using nGraph to execute workloads have shown `up to 45X`_ performance
boost compared to native implementations. For a high-level overview, see the
:doc:`project/introduction` and our latest :doc:`project/release-notes`.
.. toctree::
:maxdepth: 1
:caption: Connecting Frameworks
:caption: Getting Started
frameworks/index.rst
frameworks/validated/list.rst
......@@ -56,6 +62,7 @@ boost compared to native implementations. For a high-level overview, see the
nGraph Core Ops <ops/index.rst>
core/constructing-graphs/index.rst
core/passes/passes.rst
.. toctree::
:maxdepth: 1
......@@ -66,10 +73,10 @@ boost compared to native implementations. For a high-level overview, see the
.. toctree::
:maxdepth: 1
:caption: Backend Support
:caption: Backend Developers
backend-support/index.rst
backend-support/cpp-api.rst
backends/index.rst
backends/cpp-api.rst
.. toctree::
......@@ -91,14 +98,10 @@ boost compared to native implementations. For a high-level overview, see the
project/extras.rst
glossary.rst
.. only:: html
Indices and tables
==================
* :ref:`search`
* :ref:`genindex`
.. nGraph: https://www.ngraph.ai
.. _up to 45X: https://ai.intel.com/ngraph-compiler-stack-beta-release/
\ No newline at end of file
......@@ -20,22 +20,26 @@ Contributing to documentation
.. important:: Read this for changes affecting **anything** in ``ngraph/doc``
For updates to the Intel® nGraph Library ``/doc`` repo, please submit a PR with
For updates to the nGraph Library ``/doc`` repo, please submit a PR with
any changes or ideas you'd like integrated. This helps us maintain trackability
with respect to additions or feature requests.
with respect to changes made, additions, deletions, and feature requests.
If you prefer to use a containerized application, like Jupyter\* notebooks,
Google Docs\*, or MS Word\* to explain, write, or share documentation contributions,
you can convert the ``doc/sphinx/source/*.rst`` files to another format with a tool
like ``pypandoc`` and share a link to your docs on our `wiki`_.
Google Docs\*, the GitHub* GUI, or MS Word\* to explain, write, or share
documentation contributions, you can convert the ``doc/sphinx/source/*.rst``
files to another format with a tool like ``pypandoc`` and share a link
to your efforts on our `wiki`_.
Another option is to fork the `ngraph repo`_, essentially snapshotting it at
that point in time, and to build a Jupyter\* notebook or other set of docs around
it for a specific use case; then share a link with the community on our wiki.
it for a specific use case. Add a note on our wiki to show us what you
did; new and novel applications may have their projects highlighted on an
upcoming `ngraph.ai`_ release.
.. note:: Please do not submit Jupyter* notebook code to the Intel nGraph library
.. note:: Please do not submit Jupyter* notebook code to the nGraph Library
or core repos; best practice is to maintain any project-specific examples,
tests, or walk-throughs separately.
tests, or walk-throughs in a separate repository.
Documenting source code examples
......@@ -43,7 +47,7 @@ Documenting source code examples
When **verbosely** documenting functionality of specific sections of code -- whether
they are entire code blocks within a file, or code strings that are **outside**
the Intel nGraph `documentation repo`_, here is an example of best practice:
the nGraph Library's `documentation repo`_, here is an example of best practice:
Say a file has some interesting functionality that could benefit from more
explanation about one or more of the pieces in context. To keep the "in context"
......@@ -68,7 +72,6 @@ the code. The trick here is to add the file you want to reference relative to
the folder where the ``Makefile`` is that generates the documentation you're
writing.
See the **note** at the bottom of this page for more detail about how
this works in the current |version| version of Intel nGraph library
documentation.
......@@ -136,7 +139,7 @@ To build documentation locally, run:
Then point your browser at ``localhost:8000``.
To build documentation in a python3 virtualenv, run:
To build documentation in a python3 virtualenv, try:
.. code-block:: console
......@@ -151,7 +154,7 @@ To build documentation in a python3 virtualenv, run:
Then point your browser at ``localhost:8000``.
.. note:: For docs built in a virtual env, Sphinx latest changes may break
documentation; try building with a specific version of Sphinx.
documentation; try building with a specific version of Sphinx.
......@@ -159,6 +162,7 @@ For tips on writing reStructuredText-formatted documentation, see the `sphinx`_
stable reST documentation.
.. _ngraph repo: https://github.com/NervanaSystems/ngraph/
.. _ngraph.ai: https://www.ngraph.ai
.. _documentation repo: https://github.com/NervanaSystems/ngraph/tree/master/doc
.. _sphinx: http://www.sphinx-doc.org/en/stable/rest.html
.. _wiki: https://github.com/NervanaSystems/ngraph/wiki/
......
.. introduction:
.. project/introduction.rst:
############
Introduction
############
#######
Summary
#######
nGraph is an open-source graph compiler for :abbr:`Artificial Neural Networks (ANNs)`.
The nGraph Compiler stack provides an inherently efficient graph-based compilation
infrastructure designed to be compatible with many upcoming
:abbr:`Application-Specific Integrated Circuits (ASICs)`, like the Intel® Nervana™
Neural Network Processor (Intel® Nervana™ NNP), while also unlocking a massive
performance boost on any existing hardware targets for your neural network: both
GPUs and CPUs. Using its flexible infrastructure, you will find it becomes much
easier to create Deep Learning (DL) models that can adhere to the "write once,
run anywhere" mantra that enables your AI solutions to easily go from concept to
production to scale.
Frameworks using nGraph to execute workloads have shown `up to 45X`_ performance
boost compared to native implementations.
For a detailed overview, see below; for a more historical perspective, see
our `arXiv`_ paper.
Motivations
===========
Developers working to craft solutions with :abbr:`Artificial Intelligence (AI)`
face a steep learning curve in taking their concepts from design to
......@@ -49,10 +68,6 @@ larger datasets, data that must be encrypted, and data-in-motion. Our solution
also addresses the scalability issue with kernel libraries, the current
popular solution to accelerating deep learning performance.
Motivations
===========
The current state-of-the-art software solution for speeding up deep learning
computation is to integrate kernel libraries like Intel® Math Kernel Library
for Deep Neural Networks (Intel® MKL DNN) and Nvidia\*'s CuDNN into deep
......@@ -151,7 +166,7 @@ final product of required kernels is increasing exponentially.
PlaidML addresses the kernel explosion problem in a manner that lifts a heavy
burden off kernel developers. It automatically lowers networks from nGraph
into Tile, a :abbr:Domain-Specific Language (DSL) designed for deep learning
into Tile, a :abbr:`Domain-Specific Language (DSL)` designed for deep learning
that allows developers to express how an operation should calculate tensors in
an intuitive, mathematical form via `Stripe`_. Integration of PlaidML with
nGraph means extra flexibility to support newer deep learning models in the
......@@ -187,6 +202,7 @@ will make life easier for many kinds of developers:
#. New DL accelerator developers creating an end-to-end software stack from
a deep learning framework to their silicon.
.. _arXiv: https://arxiv.org/abs/1801.08058
.. _up to 45X: https://ai.intel.com/ngraph-compiler-stack-beta-release/
.. _more transistors on denser and denser circuits: https://www.intel.com/content/www/us/en/silicon-innovations/moores-law-technology.html
.. _Stripe: https://arxiv.org/abs/1903.06498
\ No newline at end of file
.. _Stripe: https://arxiv.org/abs/1903.06498
.. ngraph/release-notes:
.. project/release-notes.rst:
Release Notes
#############
|version|
nGraph is provided as source code, APIs, build scripts, and some binary formats
for various Compiler stack configurations and use cases.
This page includes additional documentation updates.
We are pleased to announce the release of version |version|-doc.
0.21-doc
--------
Documentation updates
~~~~~~~~~~~~~~~~~~~~~
Summary of documentation-related changes:
+ Update :doc:`doc-contributor-README` for new community-based contributions.
+ Added instructions on how to test or display the installed nGraph version.
+ Added instructions on building nGraph bridge (ngraph-bridge).
+ Updated Backend Developer Guides and ToC structure.
+ Tested documentation build on Clear Linux OS; it works.
+ Fixed a few links and redirs affected by filename changes.
+ Some coding adjustments for options to render math symbols, so they can be
documented more clearly and without excessive JS (see replacements.txt).
+ Consistent filenaming on all BE indexes.
+ Remove deprecated TensorAPI.
+
Core updates for |version|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ The offset argument in tensor reads and writes has been removed
+ Save/load API
+ More ONNX ops
+ Better tensor creation
+ More shape support
+ Provenance improvements
+ offset arg for tensor creation is deprecated
+ static linking support
For downloads formatted as ``.zip`` and ``tar.gz``, see https://github.com/NervanaSystems/ngraph/releases;
.. important:: Pre-releases (``-rc-0.*``) have newer features, and are less stable.
Changelog
=========
Changelog on Previous Releases
==============================
For downloads formatted as ``.zip`` and ``tar.gz``, see
https://github.com/NervanaSystems/ngraph/releases.
0.20
----
+ Save/load API
+ More ONNX ops
+ Better tensor creation
+ More shape support
+ Provenance improvements
0.19
----
......@@ -58,7 +109,8 @@ Changelog
+ 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.
+ Pad op takes CoordinateDiff instead of Shape pad values to allow for negative
padding.
0.16
......@@ -77,6 +129,7 @@ Changelog
+ Concat optimization
+ Doc updates
.. _0.20.0-rc.0: https://github.com/NervanaSystems/ngraph/releases/tag/v0.20.0-rc.0_
.. _0.19.0-rc.2: https://github.com/NervanaSystems/ngraph/releases/tag/v0.19.0-rc.2_
.. _0.18.1: https://github.com/NervanaSystems/ngraph/releases/tag/v0.18.1_
.. _0.17.0-rc.1: `https://github.com/NervanaSystems/ngraph/releases/tag/v0.17.0-rc.1
......
.. |codename| replace:: nGraph
.. |project| replace:: nGraph Compiler stack
.. |Intel| replace:: Intel®
.. Replacement strings for commonly-used math symbols; renders in default font
.. |lcsigma| unicode:: U+03C3 .. sigma σ
.. |sigma| unicode:: U+03A3 .. Sigma Σ
.. |lcdelta| unicode:: U+03B4 .. delta δ
.. |delta| unicode:: U+0394 .. Delta Δ
.. |lcgamma| unicode:: U+03B3 .. gamma γ
.. |gamma| unicode:: U+0393 .. Gamma Γ
.. |lcphi| unicode:: U+03C6 .. phi φ
.. |sphi| unicode:: U+03D5 .. ϕ
.. |phi| unicode:: U+03A6 .. Phi Φ
.. |lcpi| unicode:: U+03C0 .. pi π
.. |pi| unicode:: U+03A0 .. Pi Π
.. |lctheta| unicode:: U+03B8 .. theta θ
.. |theta| unicode:: U+03F4 .. Theta ϴ
.. |lclambda| unicode:: U+03BB .. lambda λ
.. |lambda| unicode:: U+039B .. Lambda Λ
.. |vmlt| unicode:: U+22D8 .. very much less than ⋘
.. |vmgt| unicode:: U+22D9 .. very much greater than ⋙
.. Miscellaneous IP-related substitutions
.. |trade| unicode:: U+02122 .. TRADEMARK SIGN
:ltrim:
.. |reg| unicode:: U+000AE .. REGISTERED TRADEMARK SIGN
:ltrim:
.. |copy| unicode:: U+000A9 .. COPYRIGHT SIGN
:ltrim:
.. Default substitutions
.. |bullet| unicode:: U+2022 .. BULLET
.. |bulletop| unicode:: U+2219 .. BULLET OPERATOR
.. |micro| unicode:: U+000B5 .. MICRO SIGN
:rtrim:
.. |sup2| unicode:: U+00B2 .. SUPERSCRIPT TWO
:ltrim:
.. |deg| unicode:: U+000B0 .. DEGREE SIGN
:ltrim:
.. |plusminus| unicode:: U+000B1 .. PLUS-MINUS SIGN
:rtrim:
\ No newline at end of file
:orphan:
.. _sitemap.rst:
.. toctree::
:includehidden:
index.rst
.. toctree::
:caption: Sitemap
:maxdepth: 1
frameworks/index
python_api/index
inspection/index
core/overview
backends/index
project/index
......@@ -2,26 +2,27 @@
## Building nGraph Python Wheels
[nGraph's build instructions][ngraph_build] give detailed instructions on building nGraph on different operating systems. Please make sure you specify the options `-DNGRAPH_PYTHON_BUILD_ENABLE=ON` and `-DNGRAPH_ONNX_IMPORT_ENABLE=ON` when building nGraph. Use the `make python_wheel` command to build nGraph and create Python packages.
Basic build procedure on an Ubuntu system:
# apt-get install build-essential cmake clang-3.9 clang-format-3.9 git curl zlib1g zlib1g-dev libtinfo-dev unzip autoconf automake libtool
# apt-get install python3 python3-dev python python-dev python-virtualenv
$ git clone https://github.com/NervanaSystems/ngraph.git
$ cd ngraph/
$ mkdir build
$ cd build/
$ cmake ../ -DNGRAPH_PYTHON_BUILD_ENABLE=ON -DNGRAPH_ONNX_IMPORT_ENABLE=ON -DNGRAPH_USE_PREBUILT_LLVM=ON
$ make python_wheel
After this procedure completes, the `ngraph/build/python/dist` directory should contain Python packages.
If you want to try a newer version of nGraph's Python API than is available from
PyPI, you can build your own latest version from the source code. This
process is very similar to what is outlined in our [ngraph_build] instructions
with two important differences:
1. You must specify: `-DNGRAPH_PYTHON_BUILD_ENABLE=ON` and `-DNGRAPH_ONNX_IMPORT_ENABLE=ON`
when running `cmake`.
2. Instead of running `make`, use the command `make python_wheel`.
`$ cmake ../ -DNGRAPH_PYTHON_BUILD_ENABLE=ON -DNGRAPH_ONNX_IMPORT_ENABLE=ON -DNGRAPH_USE_PREBUILT_LLVM=ON`
`$ make python_wheel`
After this procedure completes, the `ngraph/build/python/dist` directory should
contain the Python packages of the version you cloned. For example, if you
checked out and built `0.21`, you may see something like:
$ ls python/dist/
ngraph-core-0.10.0.tar.gz
ngraph_core-0.10.0-cp27-cp27mu-linux_x86_64.whl
ngraph_core-0.10.0-cp35-cp35m-linux_x86_64.whl
ngraph-core-0.21.0rc0.tar.gz
ngraph_core-0.21.0rc0-cp37-cp37m-linux_x86_64.whl
### Using a virtualenv (optional)
......@@ -35,7 +36,7 @@ You may wish to use a virutualenv for your installation.
You may wish to use a virutualenv for your installation.
(venv) $ pip install ngraph/build/python/dist/ngraph_core-0.10.0-cp35-cp35m-linux_x86_64.whl
(venv) $ pip install ngraph/build/python/dist/ngraph_core-0.21.0rc0-cp37-cp37m-linux_x86_64.whl
## Running tests
......
......@@ -160,6 +160,8 @@ set (SRC
op/experimental/quantized_conv_relu.hpp
op/experimental/quantized_max_pool.cpp
op/experimental/quantized_max_pool.hpp
op/experimental/range.cpp
op/experimental/range.hpp
op/experimental/shape_of.cpp
op/experimental/shape_of.hpp
op/experimental/tile.cpp
......
......@@ -121,6 +121,8 @@ add_library(onnx_import STATIC
op/max.hpp
op/mean.cpp
op/mean.hpp
op/mean_variance_normalization.cpp
op/mean_variance_normalization.hpp
op/min.hpp
op/mul.hpp
op/neg.hpp
......
//*****************************************************************************
// 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 <cstdint>
#include <memory>
#include "mean_variance_normalization.hpp"
#include "ngraph/axis_set.hpp"
#include "ngraph/op/fused/mvn.hpp"
namespace ngraph
{
namespace onnx_import
{
namespace op
{
namespace set_1
{
NodeVector mean_variance_normalization(const Node& node)
{
auto data = node.get_ng_inputs().at(0);
bool across_channels =
node.get_attribute_value<std::int64_t>("across_channels", 0);
bool normalize_variance =
node.get_attribute_value<std::int64_t>("normalize_variance", 1);
return {std::make_shared<ngraph::op::MVN>(
data, across_channels, normalize_variance)};
}
} // namespace set_1
namespace set_9
{
NodeVector mean_variance_normalization(const Node& node)
{
auto data = node.get_ng_inputs().at(0);
auto axes = node.get_attribute_value<std::vector<size_t>>("axes", {0, 2, 3});
return {std::make_shared<ngraph::op::MVN>(data, AxisSet(axes))};
}
} // namespace set_9
} //namespace op
} // namespace onnx_import
} // namespace ngraph
//*****************************************************************************
// 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.
//*****************************************************************************
#pragma once
#include <memory>
#include "core/node.hpp"
#include "ngraph/node.hpp"
namespace ngraph
{
namespace onnx_import
{
namespace op
{
namespace set_1
{
NodeVector mean_variance_normalization(const Node& node);
} // namespace set_1
namespace set_9
{
NodeVector mean_variance_normalization(const Node& node);
} // namespace set_9
} //namespace op
} // namespace onnx_import
} // namespace ngraph
......@@ -75,6 +75,7 @@
#include "op/max.hpp"
#include "op/max_pool.hpp"
#include "op/mean.hpp"
#include "op/mean_variance_normalization.hpp"
#include "op/min.hpp"
#include "op/mul.hpp"
#include "op/neg.hpp"
......@@ -283,6 +284,8 @@ namespace ngraph
REGISTER_OPERATOR("Max", 8, max);
REGISTER_OPERATOR("Mean", 1, mean);
REGISTER_OPERATOR("Mean", 8, mean);
REGISTER_OPERATOR("MeanVarianceNormalization", 1, mean_variance_normalization);
REGISTER_OPERATOR("MeanVarianceNormalization", 9, mean_variance_normalization);
REGISTER_OPERATOR("Min", 1, min);
REGISTER_OPERATOR("Min", 8, min);
REGISTER_OPERATOR("Mul", 1, mul);
......
......@@ -91,6 +91,7 @@
#include "ngraph/op/experimental/dyn_pad.hpp"
#include "ngraph/op/experimental/dyn_reshape.hpp"
#include "ngraph/op/experimental/dyn_slice.hpp"
#include "ngraph/op/experimental/range.hpp"
#include "ngraph/op/experimental/shape_of.hpp"
#include "ngraph/op/experimental/tile.hpp"
#include "ngraph/op/experimental/transpose.hpp"
......
......@@ -22,7 +22,8 @@ using namespace ngraph;
op::DynPad::DynPad(const std::shared_ptr<Node>& arg,
const std::shared_ptr<Node>& padding_below,
const std::shared_ptr<Node>& padding_above,
const std::shared_ptr<Node>& padding_value)
const std::shared_ptr<Node>& padding_value,
op::PadMode pad_mode)
: Op("DynPad", check_single_output_args({arg, padding_below, padding_above, padding_value}))
{
constructor_validate_and_infer_types();
......@@ -102,7 +103,8 @@ void op::DynPad::validate_and_infer_types()
shared_ptr<Node> op::DynPad::copy_with_new_args(const NodeVector& new_args) const
{
check_new_args_count(this, new_args);
return make_shared<DynPad>(new_args.at(0), new_args.at(1), new_args.at(2), new_args.at(3));
return make_shared<DynPad>(
new_args.at(0), new_args.at(1), new_args.at(2), new_args.at(3), m_pad_mode);
}
// TODO: This function is not implemented!
......
......@@ -33,11 +33,14 @@ namespace ngraph
/// \param padding_below The node producing the padding-below widths.
/// \param padding_above The node producing the padding-above widths.
/// \param padding_value The value to be used for padding. Must be scalar.
/// \param pad_mode The padding mode: CONSTANT(default), EDGE or REFLECT.
DynPad(const std::shared_ptr<Node>& arg,
const std::shared_ptr<Node>& padding_below,
const std::shared_ptr<Node>& padding_above,
const std::shared_ptr<Node>& padding_value);
const std::shared_ptr<Node>& padding_value,
PadMode pad_mode = PadMode::CONSTANT);
PadMode get_pad_mode() const { return m_pad_mode; }
void validate_and_infer_types() override;
virtual std::shared_ptr<Node>
......@@ -46,6 +49,9 @@ namespace ngraph
protected:
virtual void generate_adjoints(autodiff::Adjoints& adjoints,
const NodeVector& deltas) override;
private:
PadMode m_pad_mode;
};
}
}
//*****************************************************************************
// 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 <algorithm>
#include "ngraph/op/constant.hpp"
#include "ngraph/op/experimental/range.hpp"
using namespace std;
using namespace ngraph;
const string op::Range::type_name = "Range";
op::Range::Range()
{
}
op::Range::Range(const Output<Node>& start, const Output<Node>& stop, const Output<Node>& step)
: Op({start, stop, step})
{
constructor_validate_and_infer_types();
}
template <typename T>
static typename std::enable_if<std::is_integral<T>::value, void>::type
check_start(const op::Range* node, T start)
{
// Nothing to check for integral types.
}
template <typename T>
static typename std::enable_if<std::is_integral<T>::value, void>::type
check_stop(const op::Range* node, T stop)
{
// Nothing to check for integral types.
}
template <typename T>
static typename std::enable_if<std::is_integral<T>::value, void>::type
check_step(const op::Range* node, T step)
{
NODE_VALIDATION_CHECK(node, step != 0, "'step' cannot be zero.");
}
//
// The code in the following three functions is a bit awkward, to work around some compiler
// warnings and the need to support our custom float16/bfloat16 type:
//
// (1) We can't use STL things like isnan, because our custom float16/bfloat16 types don't always
// support them.
// (2) We check whether (x - x) == (x - x) to check for "is_finite".
// (3) We have to break (x - x) out into a temporary because otherwise the compiler throws a
// warning about == on floats.
// (4) We check <0 || >0 to check for != 0, because otherwise the compiler throws a warning about
// == on floats.
//
template <typename T>
static
typename std::enable_if<std::is_floating_point<T>::value || std::is_same<T, float16>::value ||
std::is_same<T, bfloat16>::value,
void>::type
check_start(const op::Range* node, T start)
{
T start_minus_start = start - start;
NODE_VALIDATION_CHECK(node,
start == start && start_minus_start == start_minus_start,
"'start' cannot be nan or infinite.");
}
template <typename T>
static
typename std::enable_if<std::is_floating_point<T>::value || std::is_same<T, float16>::value ||
std::is_same<T, bfloat16>::value,
void>::type
check_stop(const op::Range* node, T stop)
{
T stop_minus_stop = stop - stop;
NODE_VALIDATION_CHECK(node,
stop == stop && stop_minus_stop == stop_minus_stop,
"'stop' cannot be nan or infinite.");
}
template <typename T>
static
typename std::enable_if<std::is_floating_point<T>::value || std::is_same<T, float16>::value ||
std::is_same<T, bfloat16>::value,
void>::type
check_step(const op::Range* node, T step)
{
T step_minus_step = step - step;
NODE_VALIDATION_CHECK(node,
step == step && step_minus_step == step_minus_step &&
(step > static_cast<T>(0) || step < static_cast<T>(0)),
"'step' cannot be zero, nan, or infinite.");
}
template <typename T>
static typename std::enable_if<std::is_integral<T>::value, T>::type adjust_for_step_and_sign(T span,
T step)
{
return ceil_div(span < 0 ? -span : span, step < 0 ? -step : step);
}
template <typename T>
static
typename std::enable_if<std::is_floating_point<T>::value || std::is_same<T, float16>::value ||
std::is_same<T, bfloat16>::value,
T>::type
adjust_for_step_and_sign(T span, T step)
{
return ceil(fabs(span) / fabs(step));
}
template <typename T>
static PartialShape infer_output_shape(const op::Range* node, const element::Type& et)
{
auto const_start = dynamic_pointer_cast<op::Constant>(node->get_argument(0));
auto const_stop = dynamic_pointer_cast<op::Constant>(node->get_argument(1));
auto const_step = dynamic_pointer_cast<op::Constant>(node->get_argument(2));
T start = static_cast<T>(0);
T stop = static_cast<T>(0);
T step = static_cast<T>(0);
if (const_start != nullptr)
{
std::vector<T> start_val = const_start->get_vector<T>();
NODE_VALIDATION_CHECK(node, start_val.size() == 1);
start = start_val[0];
check_start<T>(node, start);
}
if (const_stop != nullptr)
{
std::vector<T> stop_val = const_stop->get_vector<T>();
NODE_VALIDATION_CHECK(node, stop_val.size() == 1);
stop = stop_val[0];
check_stop<T>(node, stop);
}
if (const_step != nullptr)
{
std::vector<T> step_val = const_step->get_vector<T>();
NODE_VALIDATION_CHECK(node, step_val.size() == 1);
step = step_val[0];
check_step<T>(node, step);
}
PartialShape result{PartialShape::dynamic(1)};
if (const_start != nullptr && const_stop != nullptr && const_step != nullptr)
{
T span;
if (step > static_cast<T>(0) && start >= stop)
{
span = static_cast<T>(0);
}
else if (step < static_cast<T>(0) && start <= stop)
{
span = static_cast<T>(0);
}
else
{
span = stop - start;
}
T strided = adjust_for_step_and_sign<T>(span, step);
result = PartialShape{Dimension(static_cast<int64_t>(strided))};
}
return result;
}
void op::Range::validate_and_infer_types()
{
set_input_is_relevant_to_shape(0);
set_input_is_relevant_to_shape(1);
set_input_is_relevant_to_shape(2);
auto result_et = element::dynamic;
NODE_VALIDATION_CHECK(
this,
element::Type::merge(result_et, result_et, get_input_element_type(0)) &&
element::Type::merge(result_et, result_et, get_input_element_type(1)) &&
element::Type::merge(result_et, result_et, get_input_element_type(2)),
"Element types for start, stop, and step do not match.");
NODE_VALIDATION_CHECK(this,
result_et != element::boolean,
"Element type for start, stop, and step, must not be boolean.");
NODE_VALIDATION_CHECK(
this, get_input_partial_shape(0).compatible(Shape{}), "'start' input is not a scalar");
NODE_VALIDATION_CHECK(
this, get_input_partial_shape(0).compatible(Shape{}), "'stop' input is not a scalar");
NODE_VALIDATION_CHECK(
this, get_input_partial_shape(0).compatible(Shape{}), "'step' input is not a scalar");
PartialShape result_shape;
#if !(defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ == 8))
#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wswitch"
#pragma GCC diagnostic error "-Wswitch-enum"
#endif
switch (result_et.get_type_enum())
{
case element::Type_t::bf16: result_shape = infer_output_shape<bfloat16>(this, result_et); break;
case element::Type_t::f16: result_shape = infer_output_shape<float16>(this, result_et); break;
case element::Type_t::f32: result_shape = infer_output_shape<float>(this, result_et); break;
case element::Type_t::f64: result_shape = infer_output_shape<double>(this, result_et); break;
case element::Type_t::i8: result_shape = infer_output_shape<int8_t>(this, result_et); break;
case element::Type_t::i16: result_shape = infer_output_shape<int16_t>(this, result_et); break;
case element::Type_t::i32: result_shape = infer_output_shape<int32_t>(this, result_et); break;
case element::Type_t::i64: result_shape = infer_output_shape<int64_t>(this, result_et); break;
case element::Type_t::u8: result_shape = infer_output_shape<uint8_t>(this, result_et); break;
case element::Type_t::u16: result_shape = infer_output_shape<uint16_t>(this, result_et); break;
case element::Type_t::u32: result_shape = infer_output_shape<uint32_t>(this, result_et); break;
case element::Type_t::u64: result_shape = infer_output_shape<uint64_t>(this, result_et); break;
case element::Type_t::dynamic: result_shape = PartialShape::dynamic(1); break;
case element::Type_t::undefined:
case element::Type_t::boolean:
NODE_VALIDATION_CHECK(
this, false, "Internal nGraph error: unsupported element type: ", result_et);
break;
}
#if !(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 8)
#pragma GCC diagnostic pop
#endif
set_output_type(0, result_et, result_shape);
}
shared_ptr<Node> op::Range::copy_with_new_args(const NodeVector& new_args) const
{
check_new_args_count(this, new_args);
return make_shared<Range>(new_args.at(0), new_args.at(1), new_args.at(2));
}
//*****************************************************************************
// 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.
//*****************************************************************************
#pragma once
#include "ngraph/node.hpp"
#include "ngraph/op/op.hpp"
namespace ngraph
{
namespace op
{
/// \brief Range operation, analogous to `range()` in Python.
class Range : public Op
{
public:
NGRAPH_API
static const std::string type_name;
const std::string& description() const override { return type_name; }
/// \brief Constructs an unitialized range operation.
Range();
/// \brief Constructs a range operation.
///
/// \param start The tensor producing the start value. Must be a scalar of integer
/// element type, and same element type as `stop` and `step`.
/// \param stop The tensor producing the stop value. Must be a scalar of integer
/// element type, and same element type as `start` and `step`.
/// \param step The tensor producing the step value. Must be a scalar of integer
/// element type, and same element type as `start` and `stop`.
Range(const Output<Node>& start, const Output<Node>& stop, const Output<Node>& step);
void validate_and_infer_types() override;
virtual std::shared_ptr<Node>
copy_with_new_args(const NodeVector& new_args) const override;
};
}
}
......@@ -37,25 +37,38 @@ op::MVN::MVN(const std::shared_ptr<Node>& data,
, m_normalize_variance{normalize_variance}
{
constructor_validate_and_infer_types();
}
NodeVector op::MVN::decompose_op() const
{
auto data = get_argument(0);
auto data_shape = data->get_shape(); // assume that data has n and c channels.
// if m_across_channels is true we should calculate mean and variance per batch
// else we calculate these per channel
AxisSet reduction_axes;
m_reduction_axes.insert(0);
size_t start_axis = m_across_channels ? 1 : 2;
for (size_t i = start_axis; i < data_shape.size(); ++i)
for (size_t i = start_axis; i < data->get_shape().size(); ++i)
{
reduction_axes.insert(i);
m_reduction_axes.insert(i);
}
}
op::MVN::MVN(const std::shared_ptr<Node>& data,
AxisSet reduction_axes,
bool normalize_variance,
double eps)
: FusedOp("MVN", {data})
, m_eps{eps}
, m_across_channels{false}
, m_normalize_variance{normalize_variance}
, m_reduction_axes{reduction_axes}
{
constructor_validate_and_infer_types();
}
NodeVector op::MVN::decompose_op() const
{
auto data = get_argument(0);
auto data_shape = data->get_shape(); // assume that data has n and c channels.
// calculate mean normalization
auto mean = builder::mean(data, reduction_axes);
mean = legacy_style_broadcast_for_binary_operation(data, mean, 0).at(1);
auto mean = builder::mean(data, m_reduction_axes);
mean = std::make_shared<op::Broadcast>(mean, data_shape, m_reduction_axes);
auto mean_normalization = data - mean;
if (!m_normalize_variance)
......@@ -65,14 +78,13 @@ NodeVector op::MVN::decompose_op() const
else
{
// calculate variance
auto variance = builder::variance(mean_normalization, reduction_axes);
auto variance = builder::variance(data, m_reduction_axes);
variance = make_shared<op::Sqrt>(variance);
// add epsilon
auto eps_node = op::Constant::create(
data->get_element_type(), variance->get_shape(), vector<double>{m_eps});
variance = variance + eps_node;
variance =
legacy_style_broadcast_for_binary_operation(mean_normalization, variance, 0).at(1);
variance = std::make_shared<op::Broadcast>(variance, data_shape, m_reduction_axes);
return {mean_normalization / variance};
}
......@@ -84,5 +96,5 @@ shared_ptr<Node> op::MVN::copy_with_new_args(const NodeVector& new_args) const
new_args.size() == 1,
"Expected 1 element in new_args for the MVN op but got ",
new_args.size());
return make_shared<MVN>(new_args.at(0), m_across_channels, m_normalize_variance, m_eps);
return make_shared<MVN>(new_args.at(0), m_reduction_axes, m_normalize_variance, m_eps);
}
......@@ -41,18 +41,31 @@ namespace ngraph
bool normalize_variance = true,
double eps = 1e-9);
/// \brief Constructs an MVN operation.
///
/// \param data Input tensor with data
/// \param reduction_axes A list of axes, along which to reduce.
/// \param normalize_variance flag that denotes whether to perform variance normalization.
/// \param eps the number to be added to the variance to avoid division by zero when normalizing the value
///
MVN(const std::shared_ptr<ngraph::Node>& data,
AxisSet reduction_axes,
bool normalize_variance = true,
double eps = 1e-9);
virtual NodeVector decompose_op() const override;
virtual std::shared_ptr<Node>
copy_with_new_args(const NodeVector& new_args) const override;
double get_eps() const { return m_eps; }
bool get_across_channels() const { return m_across_channels; }
bool get_normalize_variance() const { return m_normalize_variance; }
AxisSet get_reduction_axes() const { return m_reduction_axes; }
private:
const double m_eps;
const bool m_across_channels;
const bool m_normalize_variance;
AxisSet m_reduction_axes;
};
} // namespace op
} // namespace ngraph
......@@ -128,6 +128,7 @@ NGRAPH_OP(QuantizedDotBias, ngraph::op)
NGRAPH_OP(QuantizedDot, ngraph::op)
NGRAPH_OP(QuantizedMaxPool, ngraph::op)
NGRAPH_OP(Recv, ngraph::op)
NGRAPH_OP(Range, ngraph::op)
NGRAPH_OP(Relu, ngraph::op)
NGRAPH_OP(ReluBackprop, ngraph::op)
NGRAPH_OP(ReplaceSlice, ngraph::op)
......
......@@ -34,11 +34,13 @@ op::TopK::TopK(const Output<Node>& arg,
size_t top_k_axis,
const element::Type& index_element_type,
size_t k,
bool compute_max)
bool compute_max,
SortType sort)
: Op({arg, op::Constant::create(element::i64, Shape{1}, {k})->output(0)})
, m_top_k_axis(top_k_axis)
, m_index_element_type(index_element_type)
, m_compute_max(compute_max)
, m_sort(sort)
{
constructor_validate_and_infer_types();
}
......@@ -47,11 +49,13 @@ op::TopK::TopK(const Output<Node>& arg,
const Output<Node>& k,
size_t top_k_axis,
const element::Type& index_element_type,
bool compute_max)
bool compute_max,
SortType sort)
: Op({arg, k})
, m_top_k_axis(top_k_axis)
, m_index_element_type(index_element_type)
, m_compute_max(compute_max)
, m_sort(sort)
{
constructor_validate_and_infer_types();
}
......@@ -130,7 +134,7 @@ shared_ptr<Node> op::TopK::copy_with_new_args(const NodeVector& new_args) const
{
check_new_args_count(this, new_args);
return make_shared<TopK>(
new_args.at(0), new_args.at(1), m_top_k_axis, m_index_element_type, m_compute_max);
new_args.at(0), new_args.at(1), m_top_k_axis, m_index_element_type, m_compute_max, m_sort);
}
void op::TopK::generate_adjoints(autodiff::Adjoints& adjoints, const NodeVector& deltas)
......
......@@ -30,6 +30,16 @@ namespace ngraph
class TopK : public Op
{
public:
enum class SortType
{
// Returned values are not sorted
NONE,
// Sort result based on element indices
SORT_INDICES,
// Sort result based on element values
SORT_VALUES,
};
NGRAPH_API
static const std::string type_name;
const std::string& description() const override { return type_name; }
......@@ -42,11 +52,13 @@ namespace ngraph
/// \param index_element_type produce indices. Currently, only int64 or int32 are supported
/// \param k Number of top indices to compute. Compute all indices if k = 0
/// \param compute_max Compute top k max or top k min?
/// \param sort SortType for sorting results, default - NONE
TopK(const Output<Node>& arg,
size_t top_k_axis,
const element::Type& index_element_type,
size_t k = 0,
bool compute_max = true);
bool compute_max = true,
SortType sort = SortType::NONE);
/// \brief Constructs a TopK operation.
///
/// \param arg The input tensor
......@@ -54,11 +66,13 @@ namespace ngraph
/// \param top_k_axis The axis along which to compute top k indices
/// \param index_element_type produce indices. Currently, only int64 or int32 are supported
/// \param compute_max Compute top k max or top k min?
/// \param sort SortType for sorting results, default - NONE
TopK(const Output<Node>& arg,
const Output<Node>& k,
size_t top_k_axis,
const element::Type& index_element_type,
bool compute_max = true);
bool compute_max = true,
SortType sort = SortType::NONE);
void validate_and_infer_types() override;
......@@ -71,10 +85,12 @@ namespace ngraph
size_t get_top_k_axis() const { return m_top_k_axis; }
element::Type get_index_element_type() const { return m_index_element_type; }
bool get_compute_max() const { return m_compute_max; }
SortType get_sort() const { return m_sort; }
protected:
size_t m_top_k_axis{0};
element::Type m_index_element_type;
bool m_compute_max{false};
SortType m_sort;
virtual void generate_adjoints(autodiff::Adjoints& adjoints,
const NodeVector& deltas) override;
};
......
......@@ -27,7 +27,8 @@ namespace ngraph
{
CONSTANT = 0,
EDGE,
REFLECT
REFLECT,
SYMMETRIC
};
/// \brief Padding Type used for `Convolution` and `Pooling`
......
......@@ -18,6 +18,7 @@
#include "ngraph/op/broadcast.hpp"
#include "ngraph/op/experimental/dyn_broadcast.hpp"
#include "ngraph/op/experimental/dyn_slice.hpp"
#include "ngraph/op/experimental/range.hpp"
#include "ngraph/op/experimental/transpose.hpp"
#include "ngraph/op/reshape.hpp"
#include "ngraph/op/reverse.hpp"
......@@ -34,6 +35,7 @@ pass::DynElimination::DynElimination()
construct_transpose();
construct_broadcast();
construct_dyn_reshape();
construct_range();
}
void pass::DynElimination::construct_transpose()
......@@ -437,3 +439,141 @@ void pass::DynElimination::construct_dyn_reshape()
make_shared<pattern::Matcher>(dyn_slice_pat, "DynElimination.DynShape");
add_matcher(dyn_slice_matcher, dyn_slice_callback, all_pass_property_off);
}
template <typename T>
std::shared_ptr<op::Constant>
make_range_replacement_integral(const element::Type& et,
const Shape& shape,
const std::shared_ptr<op::Constant>& start_arg,
const std::shared_ptr<op::Constant>& step_arg)
{
std::vector<T> elements(shape_size(shape));
std::vector<T> start_vec = start_arg->get_vector<T>();
std::vector<T> step_vec = step_arg->get_vector<T>();
NGRAPH_CHECK(start_vec.size() == 1 && step_vec.size() == 1);
T start = start_vec[0];
T step = step_vec[0];
T val = start;
for (size_t i = 0; i < elements.size(); i++)
{
elements[i] = val;
val = val + step;
}
return make_shared<op::Constant>(et, shape, elements);
}
template <typename T>
std::shared_ptr<op::Constant>
make_range_replacement_floating(const element::Type& et,
const Shape& shape,
const std::shared_ptr<op::Constant>& start_arg,
const std::shared_ptr<op::Constant>& step_arg)
{
std::vector<T> elements(shape_size(shape));
std::vector<T> start_vec = start_arg->get_vector<T>();
std::vector<T> step_vec = step_arg->get_vector<T>();
NGRAPH_CHECK(start_vec.size() == 1 && step_vec.size() == 1);
T start = start_vec[0];
T step = step_vec[0];
for (size_t i = 0; i < elements.size(); i++)
{
elements[i] = start + (static_cast<T>(i) * step);
}
return make_shared<op::Constant>(et, shape, elements);
}
void pass::DynElimination::construct_range()
{
auto start_arg_label =
make_shared<pattern::op::Label>(element::f32, Shape{}, pattern::has_class<op::Constant>());
auto stop_arg_label =
make_shared<pattern::op::Label>(element::f32, Shape{}, pattern::has_class<op::Constant>());
auto step_arg_label =
make_shared<pattern::op::Label>(element::f32, Shape{}, pattern::has_class<op::Constant>());
auto range_pat = make_shared<op::Range>(start_arg_label, stop_arg_label, step_arg_label);
auto range_callback = [start_arg_label, stop_arg_label, step_arg_label](pattern::Matcher& m) {
auto pattern_map = m.get_pattern_map();
auto start_arg = static_pointer_cast<op::Constant>(pattern_map[start_arg_label]);
auto step_arg = static_pointer_cast<op::Constant>(pattern_map[step_arg_label]);
auto range_node = static_pointer_cast<op::Range>(m.get_match_root());
NGRAPH_CHECK(start_arg->get_output_partial_shape(0).rank().compatible(0) &&
step_arg->get_output_partial_shape(0).rank().compatible(0));
auto et = range_node->get_output_element_type(0);
auto shape = range_node->get_output_shape(0);
std::shared_ptr<op::Constant> replacement;
#if !(defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ == 8))
#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wswitch"
#pragma GCC diagnostic error "-Wswitch-enum"
#endif
switch (et.get_type_enum())
{
case element::Type_t::bf16:
replacement = make_range_replacement_floating<bfloat16>(et, shape, start_arg, step_arg);
break;
case element::Type_t::f16:
replacement = make_range_replacement_floating<float16>(et, shape, start_arg, step_arg);
break;
case element::Type_t::f32:
replacement = make_range_replacement_floating<float>(et, shape, start_arg, step_arg);
break;
case element::Type_t::f64:
replacement = make_range_replacement_floating<double>(et, shape, start_arg, step_arg);
break;
case element::Type_t::i8:
replacement = make_range_replacement_integral<int8_t>(et, shape, start_arg, step_arg);
break;
case element::Type_t::i16:
replacement = make_range_replacement_integral<int16_t>(et, shape, start_arg, step_arg);
break;
case element::Type_t::i32:
replacement = make_range_replacement_integral<int32_t>(et, shape, start_arg, step_arg);
break;
case element::Type_t::i64:
replacement = make_range_replacement_integral<int64_t>(et, shape, start_arg, step_arg);
break;
case element::Type_t::u8:
replacement = make_range_replacement_integral<uint8_t>(et, shape, start_arg, step_arg);
break;
case element::Type_t::u16:
replacement = make_range_replacement_integral<uint16_t>(et, shape, start_arg, step_arg);
break;
case element::Type_t::u32:
replacement = make_range_replacement_integral<uint32_t>(et, shape, start_arg, step_arg);
break;
case element::Type_t::u64:
replacement = make_range_replacement_integral<uint64_t>(et, shape, start_arg, step_arg);
break;
case element::Type_t::undefined:
case element::Type_t::dynamic:
case element::Type_t::boolean:
NGRAPH_CHECK(false, "Internal nGraph error: unsupported element type: ", et);
break;
}
#if !(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 8)
#pragma GCC diagnostic pop
#endif
replace_node(range_node, replacement);
return true;
};
auto range_matcher = make_shared<pattern::Matcher>(range_pat, "DynElimination.Range");
add_matcher(range_matcher, range_callback, all_pass_property_off);
}
......@@ -32,6 +32,7 @@ namespace ngraph
void construct_transpose();
void construct_broadcast();
void construct_dyn_reshape();
void construct_range();
};
}
}
......@@ -231,7 +231,8 @@ bool runtime::gpu::GPU_Backend::is_supported(const Node& op) const
"EmbeddingLookup",
"GenerateMask",
"DynBroadcast",
"Transpose"};
"Transpose",
"Range"};
set<string> float_only = {"MaxPoolBackprop", "AvgPoolBackprop", "MaxPool", "Dot"};
......
......@@ -72,6 +72,7 @@
#include "ngraph/op/experimental/quantized_dot.hpp"
#include "ngraph/op/experimental/quantized_dot_bias.hpp"
#include "ngraph/op/experimental/quantized_max_pool.hpp"
#include "ngraph/op/experimental/range.hpp"
#include "ngraph/op/experimental/shape_of.hpp"
#include "ngraph/op/experimental/tile.hpp"
#include "ngraph/op/experimental/transpose.hpp"
......@@ -999,6 +1000,11 @@ std::string runtime::gpu::GPU_Emitter::emit_Recv(EMIT_ARGS)
throw unsupported_op("Unsupported op '" + node->description() + "'");
}
std::string runtime::gpu::GPU_Emitter::emit_Range(EMIT_ARGS)
{
throw unsupported_op("Unsupported op '" + node->description() + "'");
}
std::string runtime::gpu::GPU_Emitter::emit_Relu(EMIT_ARGS)
{
return emit_elementwise<ngraph::op::Relu>(compiled_function, function_name, node, args, out);
......
......@@ -2087,6 +2087,7 @@ shared_ptr<runtime::Executable>
case OP_TYPEID::QuantizedDotBias:
case OP_TYPEID::QuantizedMaxPool:
case OP_TYPEID::Recv:
case OP_TYPEID::Range:
case OP_TYPEID::ReplaceSlice:
case OP_TYPEID::ScalarConstantLike:
case OP_TYPEID::ScaleShift:
......
......@@ -1197,6 +1197,11 @@ private:
memcpy(out[0]->get_data_ptr<T>(), args[0]->get_data_ptr<T>(), memSize);
break;
}
case OP_TYPEID::Range:
{
throw unsupported_op("Unsupported op '" + node.description() + "'");
break;
}
case OP_TYPEID::Relu:
{
size_t element_count = shape_size(node.get_output_shape(0));
......
......@@ -162,6 +162,11 @@ namespace ngraph
v = arg0[input_transform.index(c)];
break;
}
case op::PadMode::SYMMETRIC:
{
// TODO: Add support for Symmetric mode
throw ngraph_error("Symmetric mode padding not supported");
}
}
out[output_transform.index(out_coord)] = v;
......
......@@ -64,6 +64,7 @@
#include "ngraph/op/experimental/quantized_dot.hpp"
#include "ngraph/op/experimental/quantized_dot_bias.hpp"
#include "ngraph/op/experimental/quantized_max_pool.hpp"
#include "ngraph/op/experimental/range.hpp"
#include "ngraph/op/experimental/shape_of.hpp"
#include "ngraph/op/experimental/tile.hpp"
#include "ngraph/op/experimental/transpose.hpp"
......@@ -1383,9 +1384,9 @@ shared_ptr<Node> JSONDeserializer::deserialize_node(json& node_js)
case OP_TYPEID::MVN:
{
auto normalize_variance = node_js.at("normalize_variance").get<bool>();
auto across_channels = node_js.at("across_channels").get<bool>();
auto reduction_axes = node_js.at("reduction_axes").get<set<size_t>>();
auto eps = node_js.at("eps").get<double>();
node = make_shared<op::MVN>(args[0], normalize_variance, across_channels, eps);
node = make_shared<op::MVN>(args[0], normalize_variance, normalize_variance, eps);
break;
}
case OP_TYPEID::Negative:
......@@ -1565,6 +1566,11 @@ shared_ptr<Node> JSONDeserializer::deserialize_node(json& node_js)
node = make_shared<op::Recv>(args[0], src_id);
break;
}
case OP_TYPEID::Range:
{
node = make_shared<op::Range>(args[0], args[1], args[2]);
break;
}
case OP_TYPEID::Relu:
{
node = make_shared<op::Relu>(args[0]);
......@@ -2395,8 +2401,8 @@ json JSONSerializer::serialize_node(const Node& n)
case OP_TYPEID::MVN:
{
auto tmp = dynamic_cast<const op::MVN*>(&n);
node["reduction_axes"] = tmp->get_reduction_axes();
node["normalize_variance"] = tmp->get_normalize_variance();
node["across_channels"] = tmp->get_across_channels();
node["eps"] = tmp->get_eps();
break;
}
......@@ -2542,6 +2548,8 @@ json JSONSerializer::serialize_node(const Node& n)
node["source_id"] = tmp->get_src_id();
break;
}
case OP_TYPEID::Range: { break;
}
case OP_TYPEID::Relu: { break;
}
case OP_TYPEID::ReluBackprop: { break;
......
......@@ -240,6 +240,12 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "^(Apple)?Clang$")
target_compile_options(unit-test PRIVATE -Wno-undef -Wno-reserved-id-macro)
endif()
# So many type_prop tests these days that we need to set /bigobj flag for MSVS.
# We should probably split up type_prop.cpp.
if (MSVS)
target_compile_options(unit-test PRIVATE "/bigobj")
endif()
if (NGRAPH_CPU_ENABLE)
# The INTERPRETER backend is required for convolution, and backwards unit tests
target_link_libraries(unit-test PRIVATE cpu_backend interpreter_backend)
......
......@@ -131,3 +131,66 @@ TEST(dyn_elimination, slice)
ASSERT_EQ(f->get_results().at(0)->get_element_type(), element::f32);
ASSERT_EQ(f->get_results().at(0)->get_shape(), (Shape{2, 4, 2, 2, 1, 2, 2}));
}
TEST(dyn_elimination, range)
{
auto constant_start = make_shared<op::Constant>(element::i64, Shape{}, vector<int64_t>{0});
auto constant_stop = make_shared<op::Constant>(element::i64, Shape{}, vector<int64_t>{5});
auto constant_step = make_shared<op::Constant>(element::i64, Shape{}, vector<int64_t>{2});
auto range = make_shared<op::Range>(constant_start, constant_stop, constant_step);
ASSERT_EQ(range->get_element_type(), element::i64);
ASSERT_EQ(range->get_shape(), (Shape{3}));
auto f = make_shared<Function>(range, ParameterVector{});
pass::Manager pass_manager;
pass_manager.register_pass<pass::DynElimination>();
pass_manager.run_passes(f);
ASSERT_EQ(count_ops_of_type<op::Range>(f), 0);
ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
auto replacement = dynamic_pointer_cast<op::Constant>(f->get_results().at(0)->get_argument(0));
ASSERT_NE(replacement, nullptr);
ASSERT_EQ(replacement->get_element_type(), element::i64);
ASSERT_EQ(replacement->get_shape(), (Shape{3}));
auto vals = replacement->get_vector<int64_t>();
ASSERT_EQ(vals, (vector<int64_t>{0, 2, 4}));
}
TEST(dyn_elimination, range_f64)
{
auto constant_start = make_shared<op::Constant>(element::f64, Shape{}, vector<double>{-0.5});
auto constant_stop = make_shared<op::Constant>(element::f64, Shape{}, vector<double>{2});
auto constant_step = make_shared<op::Constant>(element::f64, Shape{}, vector<double>{0.25});
auto range = make_shared<op::Range>(constant_start, constant_stop, constant_step);
ASSERT_EQ(range->get_element_type(), element::f64);
ASSERT_EQ(range->get_shape(), (Shape{10}));
auto f = make_shared<Function>(range, ParameterVector{});
pass::Manager pass_manager;
pass_manager.register_pass<pass::DynElimination>();
pass_manager.run_passes(f);
ASSERT_EQ(count_ops_of_type<op::Range>(f), 0);
ASSERT_EQ(count_ops_of_type<op::Constant>(f), 1);
auto replacement = dynamic_pointer_cast<op::Constant>(f->get_results().at(0)->get_argument(0));
ASSERT_NE(replacement, nullptr);
ASSERT_EQ(replacement->get_element_type(), element::f64);
ASSERT_EQ(replacement->get_shape(), (Shape{10}));
auto vals = replacement->get_vector<double>();
ASSERT_TRUE(test::all_close_f(
vals, vector<double>{-0.5, -0.25, 0, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75}));
}
......@@ -308,3 +308,60 @@ NGRAPH_TEST(dynamic_${BACKEND_NAME}, all)
ASSERT_EQ(results, expected_results[i]);
}
}
template <typename T>
struct RangeTest
{
T start;
T stop;
T step;
Shape expected_result_shape;
std::vector<T> expected_result;
};
// TODO(amprocte): We should test this with more than just int32, but there is a bug in the
// handling of element type-changing that is currently blocking doing that easily.
NGRAPH_TEST(dynamic_${BACKEND_NAME}, range)
{
// Create a graph for f(start,stop,step) = Range(start,stop,step).
auto start = make_shared<op::Parameter>(element::i32, Shape{});
auto stop = make_shared<op::Parameter>(element::i32, Shape{});
auto step = make_shared<op::Parameter>(element::i32, Shape{});
auto range = make_shared<op::Range>(start, stop, step);
ASSERT_TRUE(range->get_output_partial_shape(0).same_scheme(PartialShape::dynamic(1)));
auto f = make_shared<Function>(NodeVector{range}, ParameterVector{start, stop, step});
auto backend = runtime::Backend::create("${BACKEND_NAME}", true);
auto ex = backend->compile(f);
auto t_r = backend->create_dynamic_tensor(element::i32, PartialShape::dynamic());
std::vector<RangeTest<int32_t>> int32_tests = {
RangeTest<int32_t>{0, 10, 1, Shape{10}, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}},
RangeTest<int32_t>{-5, 6, 3, Shape{4}, {-5, -2, 1, 4}},
RangeTest<int32_t>{10, 0, 1, Shape{0}, {}},
RangeTest<int32_t>{10, 5, -3, Shape{2}, {10, 7}}};
for (auto& test : int32_tests)
{
auto t_start = backend->create_tensor(element::i32, Shape{});
auto t_stop = backend->create_tensor(element::i32, Shape{});
auto t_step = backend->create_tensor(element::i32, Shape{});
copy_data(t_start, std::vector<int32_t>{test.start});
copy_data(t_stop, std::vector<int32_t>{test.stop});
copy_data(t_step, std::vector<int32_t>{test.step});
ex->call_with_validate({t_r}, {t_start, t_stop, t_step});
ASSERT_EQ(t_r->get_element_type(), element::i32);
ASSERT_EQ(t_r->get_shape(), test.expected_result_shape);
auto results = read_vector<int32_t>(t_r);
ASSERT_EQ(results, test.expected_result);
}
}
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment