Commit 7fe7bf50 authored by pthoreho's avatar pthoreho

Merge remote-tracking branch 'origin/master' into pruthvi/max_pooling

parents 9cd828bd 9348da6d
......@@ -26,20 +26,24 @@ endif()
project (ngraph)
SET( GCC_MIN_VERSION 4.8)
SET( CLANG_MIN_VERSION 3.8)
SET(GCC_MIN_VERSION 4.8)
SET(CLANG_MIN_VERSION 3.8)
SET(APPLE_CLANG_MIN_VERSION 9.0)
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS GCC_MIN_VERSION)
message(FATAL_ERROR "GCC version must be at least ${GCC_MIN_VERSION}!")
endif()
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# require at least clang 3.8
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS CLANG_MIN_VERSION)
message(FATAL_ERROR "Clang version must be at least ${CLANG_MIN_VERSION}!")
endif()
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS APPLE_CLANG_MIN_VERSION)
message(FATAL_ERROR "Apple Clang version must be at least ${APPLE_CLANG_MIN_VERSION}!")
endif()
else()
message(WARNING "You are using an unsupported compiler! Compilation has only been tested with Clang ( ${CLANG_MIN_VERSION} and up) and GCC ( ${GCC_MIN_VERSION} and up). ")
message(WARNING "You are using an unsupported compiler. Compilation has only been tested with Clang (${CLANG_MIN_VERSION} and up), Apple Clang (${APPLE_CLANG_MIN_VERSION} and up), and GCC (${GCC_MIN_VERSION} and up).")
endif()
if($ENV{NGRAPH_USE_PREBUILT_LLVM})
......
# Intel® nGraph™ library project
# Intel® nGraph™ library
Welcome to the Intel nGraph project, an open source C++ library for developers
of Deep Learning (DL) systems. Here you will find a suite of components, APIs,
and documentation that can be used to compile and run Deep Neural Network (DNN)
Welcome to Intel nGraph, an open source C++ library for developers of Deep
Learning (DL) systems. Here you will find a suite of components, APIs, and
documentation that can be used to compile and run Deep Neural Network (DNN)
models defined in a variety of frameworks.
The nGraph library translates a framework’s representation of computations into
......@@ -14,7 +14,8 @@ and data layout abstraction.
See our [install] docs for how to get started.
For this early release, we provide framework integration guides to compile
For this early release, we provide [framework integration guides] to compile
MXNet and TensorFlow-based projects.
[install]: http://ngraph.nervanasys.com/docs/cpp/installation.html
\ No newline at end of file
[install]: http://ngraph.nervanasys.com/docs/cpp/installation.html
[framework integration guides]:http://ngraph.nervanasys.com/docs/cpp/framework-integration-guides.html
......@@ -16,8 +16,7 @@
include(ExternalProject)
if((NGRAPH_CPU_ENABLE OR NGRAPH_GPU_ENABLE) AND (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") AND
(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Windows"))
if((NGRAPH_CPU_ENABLE OR NGRAPH_GPU_ENABLE) AND (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Windows"))
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
......@@ -97,82 +96,163 @@ if((NGRAPH_CPU_ENABLE OR NGRAPH_GPU_ENABLE) AND (NOT ${CMAKE_SYSTEM_NAME} MATCHE
set(LLVM_INCLUDE_DIR "${EXTERNAL_PROJECTS_ROOT}/llvm/include") # used by other external projects in current scope
set(LLVM_LIB_DIR "${EXTERNAL_PROJECTS_ROOT}/llvm/lib" PARENT_SCOPE)
set(LLVM_LINK_LIBS
clangTooling
clangFrontendTool
clangFrontend
clangDriver
clangSerialization
clangCodeGen
clangParse
clangSema
clangStaticAnalyzerFrontend
clangStaticAnalyzerCheckers
clangStaticAnalyzerCore
clangAnalysis
clangARCMigrate
clangRewriteFrontend
clangEdit
clangAST
clangLex
clangBasic
LLVMLTO
LLVMPasses
LLVMObjCARCOpts
LLVMSymbolize
LLVMDebugInfoPDB
LLVMDebugInfoDWARF
LLVMMIRParser
LLVMCoverage
LLVMTableGen
LLVMDlltoolDriver
LLVMOrcJIT
LLVMObjectYAML
LLVMLibDriver
LLVMOption
LLVMX86Disassembler
LLVMX86AsmParser
LLVMX86CodeGen
LLVMGlobalISel
LLVMSelectionDAG
LLVMAsmPrinter
LLVMDebugInfoCodeView
LLVMDebugInfoMSF
LLVMX86Desc
LLVMMCDisassembler
LLVMX86Info
LLVMX86AsmPrinter
LLVMX86Utils
LLVMMCJIT
LLVMLineEditor
LLVMInterpreter
LLVMExecutionEngine
LLVMRuntimeDyld
LLVMCodeGen
LLVMTarget
LLVMCoroutines
LLVMipo
LLVMInstrumentation
LLVMVectorize
LLVMScalarOpts
LLVMLinker
LLVMIRReader
LLVMAsmParser
LLVMInstCombine
LLVMTransformUtils
LLVMBitWriter
LLVMAnalysis
LLVMProfileData
LLVMObject
LLVMMCParser
LLVMMC
LLVMBitReader
LLVMCore
LLVMBinaryFormat
LLVMSupport
LLVMDemangle
tinfo
z
m
PARENT_SCOPE)
if(APPLE)
set(LLVM_LINK_LIBS
clangTooling
clangFrontendTool
clangFrontend
clangDriver
clangSerialization
clangCodeGen
clangParse
clangSema
clangStaticAnalyzerFrontend
clangStaticAnalyzerCheckers
clangStaticAnalyzerCore
clangAnalysis
clangARCMigrate
clangRewriteFrontend
clangEdit
clangAST
clangLex
clangBasic
LLVMLTO
LLVMPasses
LLVMObjCARCOpts
LLVMSymbolize
LLVMDebugInfoPDB
LLVMDebugInfoDWARF
LLVMMIRParser
LLVMCoverage
LLVMTableGen
LLVMDlltoolDriver
LLVMOrcJIT
LLVMObjectYAML
LLVMLibDriver
LLVMOption
LLVMX86Disassembler
LLVMX86AsmParser
LLVMX86CodeGen
LLVMGlobalISel
LLVMSelectionDAG
LLVMAsmPrinter
LLVMDebugInfoCodeView
LLVMDebugInfoMSF
LLVMX86Desc
LLVMMCDisassembler
LLVMX86Info
LLVMX86AsmPrinter
LLVMX86Utils
LLVMMCJIT
LLVMLineEditor
LLVMInterpreter
LLVMExecutionEngine
LLVMRuntimeDyld
LLVMCodeGen
LLVMTarget
LLVMCoroutines
LLVMipo
LLVMInstrumentation
LLVMVectorize
LLVMScalarOpts
LLVMLinker
LLVMIRReader
LLVMAsmParser
LLVMInstCombine
LLVMTransformUtils
LLVMBitWriter
LLVMAnalysis
LLVMProfileData
LLVMObject
LLVMMCParser
LLVMMC
LLVMBitReader
LLVMCore
LLVMBinaryFormat
LLVMSupport
LLVMDemangle
curses
z
m
PARENT_SCOPE)
else()
set(LLVM_LINK_LIBS
clangTooling
clangFrontendTool
clangFrontend
clangDriver
clangSerialization
clangCodeGen
clangParse
clangSema
clangStaticAnalyzerFrontend
clangStaticAnalyzerCheckers
clangStaticAnalyzerCore
clangAnalysis
clangARCMigrate
clangRewriteFrontend
clangEdit
clangAST
clangLex
clangBasic
LLVMLTO
LLVMPasses
LLVMObjCARCOpts
LLVMSymbolize
LLVMDebugInfoPDB
LLVMDebugInfoDWARF
LLVMMIRParser
LLVMCoverage
LLVMTableGen
LLVMDlltoolDriver
LLVMOrcJIT
LLVMObjectYAML
LLVMLibDriver
LLVMOption
LLVMX86Disassembler
LLVMX86AsmParser
LLVMX86CodeGen
LLVMGlobalISel
LLVMSelectionDAG
LLVMAsmPrinter
LLVMDebugInfoCodeView
LLVMDebugInfoMSF
LLVMX86Desc
LLVMMCDisassembler
LLVMX86Info
LLVMX86AsmPrinter
LLVMX86Utils
LLVMMCJIT
LLVMLineEditor
LLVMInterpreter
LLVMExecutionEngine
LLVMRuntimeDyld
LLVMCodeGen
LLVMTarget
LLVMCoroutines
LLVMipo
LLVMInstrumentation
LLVMVectorize
LLVMScalarOpts
LLVMLinker
LLVMIRReader
LLVMAsmParser
LLVMInstCombine
LLVMTransformUtils
LLVMBitWriter
LLVMAnalysis
LLVMProfileData
LLVMObject
LLVMMCParser
LLVMMC
LLVMBitReader
LLVMCore
LLVMBinaryFormat
LLVMSupport
LLVMDemangle
tinfo
z
m
PARENT_SCOPE)
endif()
endif()
......@@ -20,7 +20,7 @@ include(ExternalProject)
# Fetch and install MKL-DNN
#----------------------------------------------------------------------------------------------------------
if(NGRAPH_CPU_ENABLE AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
if(NGRAPH_CPU_ENABLE)
set(MKLDNN_GIT_REPO_URL https://github.com/intel/mkl-dnn)
set(MKLDNN_GIT_TAG "3e1f8f5")
......
......@@ -22,13 +22,11 @@ if(NGRAPH_TBB_ENABLE)
set(TBB_GIT_REPO_URL https://github.com/01org/tbb)
set(TBB_GIT_TAG "tbb_2018")
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
configure_file(${CMAKE_SOURCE_DIR}/cmake/tbb_fetch.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/tbb/CMakeLists.txt)
execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/tbb")
execute_process(COMMAND "${CMAKE_COMMAND}" --build .
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/tbb")
configure_file(${CMAKE_SOURCE_DIR}/cmake/tbb_fetch.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/tbb/CMakeLists.txt)
execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/tbb")
execute_process(COMMAND "${CMAKE_COMMAND}" --build .
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/tbb")
set(TBB_ROOT ${CMAKE_CURRENT_BINARY_DIR}/tbb/tbb-src PARENT_SCOPE)
endif()
set(TBB_ROOT ${CMAKE_CURRENT_BINARY_DIR}/tbb/tbb-src PARENT_SCOPE)
endif()
......@@ -79,19 +79,9 @@ build_docker_image: expand_dockerfile_templates
build_docker: build_docker_image
# Build docs
docs: sphinx_doc doxygen_doc
docs: sphinx_doc
doxygen_doc:
# doxygen html docs build
docker run --rm --tty \
${VOLUME} \
${DOCKER_RUN_ENV} \
--env RUN_UID="$(shell id -u)" \
--env RUN_CMD="set -e ; set -o pipefail ; cd ${DOCKUSER_HOME}/ngraph-cpp-test/doc/doxygen; env VERBOSE=1 make html 2>&1 | tee make_sphinx_html.log" \
"build_ngraph_cpp:${DBUILD_VERSION}" \
sh -c "${DOCKUSER_HOME}/ngraph-cpp-test/contrib/docker/run_as_user.sh"
sphinx_doc:
sphinx_doc: build_docker_image
# sphinx html docs build
docker run --rm --tty \
${VOLUME} \
......
......@@ -19,12 +19,6 @@ help:
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
doxy-code:
$(Q)(cat ngraph.doxyfile ; echo "STRIP_FROM_PATH=${NGRAPH_BASE}" ) | doxygen - 2>&1 | tee doc.log
doxy: doxy-code
clean:
@rm -rf $(BUILDDIR)/*
@rm -rf html
......@@ -32,7 +26,10 @@ clean:
@rm -rf doxygen
@rm -rf latex
htmldocs: doxy html
doxy-code:
$(Q)(cat ngraph.doxyfile ; echo "STRIP_FROM_PATH=${NGRAPH_BASE}" ) | doxygen - 2>&1 | tee doc.log
html: doxy-code
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
......@@ -41,8 +38,6 @@ pickle:
json: prep
$(SPHINXBUILD) -t $(DOC_TAG) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@rm -rf samples
@rm -rf boards
@echo
@echo "Build finished; now you can process the JSON files."
......
......@@ -17,10 +17,11 @@
Intel nGraph library project
#############################
Welcome to the Intel nGraph project, an open source C++ library for developers
of :abbr:`Deep Learning (DL)` (DL) systems. Here you will find a suite of
components, APIs, and documentation that can be used to compile and run
:abbr:`Deep Neural Network (DNN)` (DNN) models defined in a variety of frameworks.
Welcome to Intel nGraph, an open source C++ library for developers of
:abbr:`Deep Learning (DL)` (DL) systems. Here you will find a suite
of components, APIs, and documentation that can be used to compile
and run :abbr:`Deep Neural Network (DNN)` (DNN) models defined in a
variety of frameworks.
.. figure:: graphics/ngraph-hub.png
......
......@@ -7,24 +7,23 @@ Install the Intel® nGraph™ library
Build Environments
==================
The |release| version of |project| supports Linux\* or UNIX-based
systems which have recent updates of the following packages and
prerequisites:
The |release| version of |project| supports Linux\*-based systems which
have recent updates of the following packages and prerequisites:
.. csv-table::
:header: "Operating System", "Compiler", "Build System", "Status", "Additional Packages"
:widths: 25, 15, 25, 20, 25
:escape: ~
CentOS 7.4 64-bit, CLang 3.4, GCC 4.8 + CMake 2.8, supported, ``patch diffutils zlib1g-dev libtinfo-dev``
CentOS 7.4 64-bit, GCC 4.8, CMake 3.2, supported, ``patch diffutils zlib1g-dev libtinfo-dev``
Ubuntu 16.04 (LTS) 64-bit, CLang 3.9, CMake 3.5.1 + GNU Make, supported, ``build-essential cmake clang-3.9 git libtinfo-dev``
Ubuntu 16.04 (LTS) 64-bit, CLang 4.0, CMake 3.5.1 + GNU Make, officially unsupported, ``build-essential cmake clang-4.0 git libtinfo-dev``
Clear Linux\* OS for Intel Architecture, CLang 5.0.1, CMake 3.10.2, experimental, bundles ``machine-learning-basic dev-utils python3-basic python-basic-dev``
On Ubuntu 16.04 with ``gcc-5.4.0`` or ``clang-3.9``, the recommended option
is to add ``-DNGRAPH_USE_PREBUILT_LLVM=TRUE`` to the :command:`cmake` command.
This gets a pre-built tarball of LLVM+Clang from `llvm.org`_, and substantially
reduces build times.
Other configurations may work, but aren't tested; on Ubuntu 16.04 with
``gcc-5.4.0`` or ``clang-3.9``, for example, we recommend adding
``-DNGRAPH_USE_PREBUILT_LLVM=TRUE`` to the :command:`cmake` command in step 4
below. This gets a pre-built tarball of LLVM+Clang from `llvm.org`_, and will
substantially reduce build time.
If using ``gcc-4.8``, it may be necessary to add symlinksfrom ``gcc`` to
``gcc-4.8``, and from ``g++`` to ``g++-4.8``, in your :envvar:`PATH`, even
......@@ -33,7 +32,7 @@ flags when building. (You should NOT supply the `-DNGRAPH_USE_PREBUILT_LLVM`
flag in this case, because the prebuilt tarball supplied on llvm.org is not
compatible with a gcc-4.8 based build.)
Support for macOS is limited; see the macOS development prerequisites
Support for macOS is limited; see the `macOS development prerequisites`_
section at the end of this page for details.
......@@ -95,6 +94,7 @@ information about how to change or customize this location.
the ``doc/sphinx`` directory to build HTML API docs inside the
``/docs/doxygen/`` directory.
.. macos_development_prerequisites:
macOS Development Prerequisites
-------------------------------
......
......@@ -125,3 +125,4 @@ C++ Interface
.. doxygenclass:: ngraph::op::Convolution
:members:
\ No newline at end of file
......@@ -17,6 +17,30 @@ Architecture CPUs, the Intel® Nervana Neural Network Processor™ (NNP),
and NVIDIA\* GPUs. Currently-supported compiler optimizations include efficient
memory management and data layout abstraction.
Why is this needed?
--------------------
When Deep Learning (DL) frameworks first emerged as the vehicle for training
and inference models, they were designed around kernels optimized for a
particular platform. As a result, many backend details were being exposed in
the model definitions, making the adaptability and portability of DL models
to other or more advanced backends inherently complex and expensive.
The traditional approach means that an algorithm developer cannot easily adapt
his or her model to different backends. Making a model run on a different
framework is also problematic because the user must separate the essence of
the model from the performance adjustments made for the backend, translate
to similar ops in the new framework, and finally make the necessary changes
for the preferred backend configuration on the new framework.
We designed the Intel nGraph project to substantially reduce these kinds of
engineering complexities. While optimized kernels for deep-learning primitives
are provided through the project and via libraries like Intel® Math Kernel
Library (Intel® MKL) for Deep Neural Networks (Intel® MKL-DNN), there are
several compiler-inspired ways in which performance can be further optimized.
=======
The *nGraph core* uses a strongly-typed and platform-neutral stateless graph
representation for computations. Each node, or *op*, in the graph corresponds
to one step in a computation, where each step produces zero or more tensor
......@@ -39,4 +63,7 @@ read more about design decisions and what is tentatively in the pipeline
for development in our `SysML conference paper`_.
.. _frontend: http://neon.nervanasys.com/index.html/
.. _SysML conference paper: https://arxiv.org/pdf/1801.08058.pdf
\ No newline at end of file
.. _SysML conference paper: https://arxiv.org/pdf/1801.08058.pdf
.. _MXNet: http://mxnet.incubator.apache.org/
.. _TensorFlow: https://www.tensorflow.org/
......@@ -31,14 +31,12 @@ training/inference model with one of the backends that are now enabled.
For this early |release| release, we're providing :doc:`framework-integration-guides`,
for:
* :doc:`framework-integration-guides` framework,
* :doc:`framework-integration-guides` framework, and
* :doc:`MXNet<framework-integration-guides>` framework,
* :doc:`Tensorflow<framework-integration-guides>` framework, and
* neon™ `frontend framework`_.
Integration guides for other frameworks are tentatively forthcoming.
.. _GTest framework: https://github.com/google/googletest.git
.. _MXNet: http://mxnet.incubator.apache.org/
.. _TensorFlow: https://www.tensorflow.org/
.. _frontend framework: http://neon.nervanasys.com/index.html/
......@@ -36,6 +36,7 @@ set (SRC
ops/abs.cpp
ops/add.cpp
ops/avg_pool.cpp
ops/batch_norm.cpp
ops/binary_elementwise_arithmetic.cpp
ops/binary_elementwise_comparison.cpp
ops/binary_elementwise.cpp
......@@ -328,35 +329,33 @@ install(DIRECTORY
FILES_MATCHING PATTERN "*.hpp"
)
if (NOT APPLE)
install(DIRECTORY
${MKLDNN_LIB_DIR}/
DESTINATION "${NGRAPH_INSTALL_LIB}"
)
install(DIRECTORY
${MKLDNN_LIB_DIR}/
DESTINATION "${NGRAPH_INSTALL_LIB}"
)
if (NGRAPH_TBB_ENABLE)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tbb_build/tbb_release/
DESTINATION ${NGRAPH_INSTALL_LIB}
FILES_MATCHING PATTERN "libtbb.so.*"
)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tbb_build/tbb_debug/
DESTINATION ${NGRAPH_INSTALL_LIB}
FILES_MATCHING PATTERN "libtbb_debug.so.*"
)
endif()
if (NGRAPH_TBB_ENABLE)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tbb_build/tbb_release/
DESTINATION ${NGRAPH_INSTALL_LIB}
FILES_MATCHING PATTERN "libtbb.so.*"
)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/tbb_build/tbb_debug/
DESTINATION ${NGRAPH_INSTALL_LIB}
FILES_MATCHING PATTERN "libtbb_debug.so.*"
)
endif()
if (NGRAPH_ARGON_ENABLE)
install(DIRECTORY ${ARGON_TRANSFORMER_LIB_DIR}/
DESTINATION ${NGRAPH_INSTALL_LIB}
FILES_MATCHING PATTERN "*.so"
)
install(DIRECTORY ${ARGON_TRANSFORMER_INCLUDE_DIR}/
DESTINATION ${NGRAPH_INSTALL_INCLUDE}
FILES_MATCHING PATTERN "*.hpp"
)
install(DIRECTORY ${ARGON_TRANSFORMER_INCLUDE_DIR}/
DESTINATION ${NGRAPH_INSTALL_INCLUDE}
FILES_MATCHING PATTERN "*.h"
)
endif()
if (NGRAPH_ARGON_ENABLE)
install(DIRECTORY ${ARGON_TRANSFORMER_LIB_DIR}/
DESTINATION ${NGRAPH_INSTALL_LIB}
FILES_MATCHING PATTERN "*.so"
)
install(DIRECTORY ${ARGON_TRANSFORMER_INCLUDE_DIR}/
DESTINATION ${NGRAPH_INSTALL_INCLUDE}
FILES_MATCHING PATTERN "*.hpp"
)
install(DIRECTORY ${ARGON_TRANSFORMER_INCLUDE_DIR}/
DESTINATION ${NGRAPH_INSTALL_INCLUDE}
FILES_MATCHING PATTERN "*.h"
)
endif()
......@@ -151,6 +151,8 @@ void codegen::StaticCompiler::initialize()
// Prepare DiagnosticEngine
IntrusiveRefCntPtr<DiagnosticOptions> diag_options = new DiagnosticOptions();
diag_options->ErrorLimit = 20;
diag_options->ShowCarets = false;
diag_options->ShowFixits = false;
IntrusiveRefCntPtr<DiagnosticIDs> diag_id(new DiagnosticIDs());
DiagnosticsEngine diag_engine(diag_id, &*diag_options);
......@@ -351,6 +353,15 @@ void codegen::StaticCompiler::configure_search_path()
{
#ifdef USE_BUILTIN
load_headers_from_resource();
#elif defined(__APPLE__)
add_header_search_path(EIGEN_HEADERS_PATH);
add_header_search_path(MKLDNN_HEADERS_PATH);
add_header_search_path(TBB_HEADERS_PATH);
add_header_search_path(NGRAPH_HEADERS_PATH);
add_header_search_path(INSTALLED_HEADERS_PATH);
add_header_search_path(CLANG_BUILTIN_HEADERS_PATH);
add_header_search_path("/Library/Developer/CommandLineTools/usr/include/c++/v1");
#else
// Add base toolchain-supplied header paths
// Ideally one would use the Linux toolchain definition in clang/lib/Driver/ToolChains.h
......
......@@ -78,6 +78,13 @@ void codegen::ExecutionEngine::finalize()
void* codegen::ExecutionEngine::get_pointer_to_named_function(const std::string& func_name)
{
// For whatever reason, macOS seems to expect that we prefix this with an underscore.
#ifdef __APPLE__
std::string fname = "_" + func_name;
#else
const std::string& fname = func_name;
#endif
// set AbortOnFailure flag to false so call fails by returning nullptr
return m_execution_engine->getPointerToNamedFunction(func_name, false);
return m_execution_engine->getPointerToNamedFunction(fname, false);
}
......@@ -45,7 +45,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Abs>(new_args.at(0));
}
......
......@@ -45,7 +45,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Acos>(new_args.at(0));
}
};
......
......@@ -47,7 +47,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Add>(new_args.at(0), new_args.at(1));
}
......
......@@ -32,7 +32,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<AllReduce>(new_args.at(0));
}
};
......
......@@ -45,7 +45,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Asin>(new_args.at(0));
}
};
......
......@@ -45,7 +45,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Atan>(new_args.at(0));
}
};
......
......@@ -69,7 +69,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<AvgPool>(new_args.at(0),
m_window_shape,
......@@ -110,7 +112,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
AvgPoolBackprop* avpn = new AvgPoolBackprop(m_forward_arg_shape,
new_args.at(0),
......
/*******************************************************************************
* Copyright 2017-2018 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 "ngraph/ops/batch_norm.hpp"
#include "ngraph/ops/constant.hpp"
ngraph::op::BatchNorm::BatchNorm(double eps,
std::shared_ptr<ngraph::Node> gamma,
std::shared_ptr<ngraph::Node> beta,
std::shared_ptr<ngraph::Node> input,
std::shared_ptr<ngraph::Node> mean,
std::shared_ptr<ngraph::Node> variance)
: RequiresTensorViewArgs("BatchNorm", {gamma, beta, input, mean, variance})
, m_bn_input_shape(input->get_shape())
, m_bn_variance_shape(variance->get_shape())
, m_bn_mean_shape(mean->get_shape())
, m_epsilon(eps)
{
add_output(input->get_element_type(), m_bn_input_shape);
if (m_bn_input_shape.size() < 2)
{
throw ngraph_error("input tensor to batchnorm much have tensor of atleast rank 2");
}
if (m_bn_input_shape[1] == 0)
{
throw ngraph_error(
"input tensor must have atleast one channel axis for batch normalization");
}
if ((m_bn_mean_shape.size() != 1) && (m_bn_variance_shape.size() != 1) &&
(gamma->get_shape().size() != 1) && (beta->get_shape().size() != 1))
{
throw ngraph_error("gamma, beta, mean, variance shoud have all rank 1");
}
// assuming input shape (N, C, H, W), check if the size of mean and
// variance are equal to channel axis
if (mean->get_shape()[0] != m_bn_input_shape[1])
{
throw ngraph_error("mean size is not equal to input channel size");
}
if (variance->get_shape()[0] != m_bn_input_shape[1])
{
throw ngraph_error("variance size is not equal to input channel size");
}
if (variance->get_shape().size() != mean->get_shape().size())
{
throw ngraph_error("mean and variance rank does not match");
}
if (gamma->get_shape().size() != beta->get_shape().size())
{
throw ngraph_error("gamma and beta rank does not match");
}
if (input->get_element_type() != mean->get_element_type())
{
throw ngraph_error("input tensor and mean element type does not match");
}
if (input->get_element_type() != variance->get_element_type())
{
throw ngraph_error("input tensor and variance element type does not match");
}
if (gamma->get_element_type() != beta->get_element_type())
{
throw ngraph_error("gamma and beta element type does not match");
}
}
std::shared_ptr<ngraph::Node> ngraph::op::BatchNorm::copy_with_new_args(
const std::vector<std::shared_ptr<ngraph::Node>>& new_args) const
{
if (new_args.size() != 5)
throw ngraph_error("Incorrect number of new arguments");
return std::make_shared<BatchNorm>(
m_epsilon, new_args.at(0), new_args.at(1), new_args.at(2), new_args.at(3), new_args.at(4));
}
/*******************************************************************************
* Copyright 2017-2018 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 "ngraph/node.hpp"
#include "ngraph/ops/op.hpp"
#include "ngraph/util.hpp"
namespace ngraph
{
namespace op
{
class BatchNorm : public RequiresTensorViewArgs
{
public:
BatchNorm(double eps,
std::shared_ptr<Node> gamma,
std::shared_ptr<Node> beta,
std::shared_ptr<Node> input,
std::shared_ptr<Node> mean,
std::shared_ptr<Node> variance);
const Shape& get_inputs_shape() const { return m_bn_input_shape; }
const Shape& get_variance_shape() const { return m_bn_variance_shape; }
const Shape& get_mean_shape() const { return m_bn_mean_shape; }
double get_eps_value() const { return m_epsilon; }
virtual std::shared_ptr<Node> copy_with_new_args(
const std::vector<std::shared_ptr<Node>>& new_args) const override;
private:
Shape m_bn_input_shape;
Shape m_bn_variance_shape;
Shape m_bn_mean_shape;
double m_epsilon;
};
}
}
......@@ -40,7 +40,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Broadcast>(new_args.at(0), m_shape, m_broadcast_axes);
}
......
......@@ -38,7 +38,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Ceiling>(new_args.at(0));
}
};
......
......@@ -58,7 +58,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Convert>(new_args.at(0), m_element_type);
}
......
......@@ -50,7 +50,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Cos>(new_args.at(0));
}
......
......@@ -50,7 +50,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Cosh>(new_args.at(0));
}
......
......@@ -52,7 +52,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Divide>(new_args.at(0), new_args.at(1));
}
......
......@@ -83,7 +83,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Dot>(
new_args.at(0), new_args.at(1), m_reduction_axes_count);
}
......
......@@ -52,7 +52,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Equal>(new_args.at(0), new_args.at(1));
}
};
......
......@@ -50,7 +50,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Exp>(new_args.at(0));
}
......
......@@ -50,7 +50,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Floor>(new_args.at(0));
}
};
......
......@@ -54,7 +54,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<GetOutputElement>(new_args.at(0), m_n);
}
......
......@@ -52,7 +52,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Greater>(new_args.at(0), new_args.at(1));
}
};
......
......@@ -52,7 +52,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<GreaterEq>(new_args.at(0), new_args.at(1));
}
};
......
......@@ -52,7 +52,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Less>(new_args.at(0), new_args.at(1));
}
};
......
......@@ -52,7 +52,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<LessEq>(new_args.at(0), new_args.at(1));
}
};
......
......@@ -50,7 +50,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Log>(new_args.at(0));
}
......
......@@ -76,7 +76,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<MaxPool>(
new_args.at(0), m_window_shape, m_window_movement_strides);
}
......@@ -114,7 +116,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
MaxPoolBackprop* mpbp = new MaxPoolBackprop(new_args.at(0),
new_args.at(1),
......
......@@ -52,7 +52,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Maximum>(new_args.at(0), new_args.at(1));
}
......
......@@ -52,7 +52,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Minimum>(new_args.at(0), new_args.at(1));
}
......
......@@ -52,7 +52,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Multiply>(new_args.at(0), new_args.at(1));
}
......
......@@ -50,7 +50,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Negative>(new_args.at(0));
}
......
......@@ -47,7 +47,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Not>(new_args.at(0));
}
};
......
......@@ -52,7 +52,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<NotEqual>(new_args.at(0), new_args.at(1));
}
};
......
......@@ -56,7 +56,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<OneHot>(new_args.at(0), m_shape, m_one_hot_axis);
}
......
......@@ -30,7 +30,9 @@ op::Parameter::Parameter(const ngraph::element::Type& element_type, const Shape&
shared_ptr<Node> op::Parameter::copy_with_new_args(const vector<shared_ptr<Node>>& new_args) const
{
if (new_args.size() != 0)
{
throw ngraph_error("Incorrect number of new arguments");
}
const descriptor::Output& output = get_outputs().at(0);
return make_shared<Parameter>(output.get_element_type(), output.get_shape());
}
......
......@@ -52,7 +52,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Power>(new_args.at(0), new_args.at(1));
}
......
......@@ -100,7 +100,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Reduce>(
new_args.at(0), new_args.at(1), m_reduction_function, m_reduction_axes);
}
......
......@@ -70,7 +70,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<ReduceWindow>(new_args.at(0),
new_args.at(1),
m_reduction_function,
......
......@@ -54,7 +54,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Remainder>(new_args.at(0), new_args.at(1));
}
};
......
......@@ -78,7 +78,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<ReplaceSlice>(
new_args.at(0), new_args.at(1), m_lower_bounds, m_upper_bounds, m_strides);
}
......
......@@ -73,7 +73,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Reshape>(new_args.at(0), m_input_order, m_output_shape);
}
......
......@@ -56,7 +56,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Reverse>(new_args.at(0), m_reversed_axes);
}
......
......@@ -53,7 +53,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 3)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Select>(new_args.at(0), new_args.at(1), new_args.at(2));
}
......
......@@ -91,7 +91,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 3)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<SelectAndScatter>(new_args.at(0),
new_args.at(1),
new_args.at(2),
......
......@@ -52,7 +52,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Sign>(new_args.at(0));
}
};
......
......@@ -50,7 +50,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Sin>(new_args.at(0));
}
......
......@@ -50,7 +50,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Sinh>(new_args.at(0));
}
......
......@@ -76,7 +76,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Slice>(
new_args.at(0), m_lower_bounds, m_upper_bounds, m_strides);
}
......
......@@ -50,7 +50,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Sqrt>(new_args.at(0));
}
......
......@@ -52,7 +52,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Subtract>(new_args.at(0), new_args.at(1));
}
......
......@@ -89,7 +89,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Sum>(new_args.at(0), m_reduction_axes);
}
......
......@@ -50,7 +50,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Tan>(new_args.at(0));
}
......
......@@ -50,7 +50,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<Tanh>(new_args.at(0));
}
......
......@@ -55,7 +55,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<XLAGetTupleElement>(new_args.at(0), m_n);
}
......
File mode changed from 100644 to 100755
......@@ -14,16 +14,18 @@
* limitations under the License.
*******************************************************************************/
#include "ngraph/runtime/cpu/cpu_emitter.hpp"
#include <algorithm>
#include <cmath>
#include <iostream>
#include <numeric>
#include <string>
#include <typeindex>
#include <unordered_map>
#include <vector>
#include "ngraph/node.hpp"
#include "ngraph/ops/avg_pool.hpp"
#include "ngraph/ops/batch_norm.hpp"
#include "ngraph/ops/broadcast.hpp"
#include "ngraph/ops/concatenate.hpp"
#include "ngraph/ops/constant.hpp"
......@@ -42,7 +44,6 @@
#include "ngraph/ops/select_and_scatter.hpp"
#include "ngraph/ops/slice.hpp"
#include "ngraph/ops/sum.hpp"
#include "ngraph/runtime/cpu/cpu_emitter.hpp"
#include "ngraph/runtime/cpu/cpu_kernel_emitters.hpp"
#include "ngraph/runtime/cpu/ops/matmul_bias.hpp"
#include "ngraph/types/element_type.hpp"
......@@ -210,6 +211,85 @@ void runtime::cpu::CPU_Emitter::EMITTER_DECL(EmitMatmulBias)
writer << "}\n";
}
void runtime::cpu::CPU_Emitter::EMITTER_DECL(EmitBatchNorm)
{
const ngraph::op::BatchNorm* batchnorm = static_cast<const ngraph::op::BatchNorm*>(node);
// get the shape of all the inputs and output to batchnorm
auto gamma_shape = args[0].get_shape();
auto beta_shape = args[1].get_shape();
auto input_shape = args[2].get_shape();
auto mean_shape = args[3].get_shape();
auto variance_shape = args[4].get_shape();
auto result_shape = out[0].get_shape();
// get input element type
const string& et = get_mkldnn_data_type(args[2].get_element_type().c_type_string());
writer << "{\n";
writer.indent++;
// define weights
writer << "std::vector<" << args[0].get_element_type().c_type_string() << ">bn_weights(2);\n";
auto weights_shape = Shape{2, input_shape[1]};
// push gamma and beta
writer << "auto gamma = " << args[0].get_name() << ";\n";
writer << "auto beta = " << args[1].get_name() << ";\n";
writer << "memcpy(&bn_weights[0], gamma,"
<< args[1].get_size() * args[0].get_element_type().size() << ");\n";
writer << "memcpy(&bn_weights[0]+" << args[1].get_size() << ", beta, "
<< args[1].get_size() * args[1].get_element_type().size() << ");\n";
// get the eps value from the bn node
writer << "auto epsilon = " << batchnorm->get_eps_value() << ";\n";
// Bind to CPU engine
writer << "engine cpu_engine = engine(engine::cpu, 0);\n";
// create memory descriptors
writer << "memory::desc input_data_desc = memory::desc({" << join(input_shape) << "}, " << et
<< ", memory::format::nchw);\n";
// TODO define weights by stacking gamma and beta values
writer << "memory::desc weights_desc = memory::desc({" << join(weights_shape) << "}, " << et
<< ", memory::format::nc);\n";
writer << "memory::desc result_desc = memory::desc({" << join(result_shape) << "}, " << et
<< ", memory::format::nchw);\n";
writer << "memory::desc mean_desc = memory::desc({" << join(mean_shape) << "}, " << et
<< ", memory::format::x);\n";
writer << "memory::desc variance_desc = memory::desc({" << join(variance_shape) << "}, " << et
<< ", memory::format::x);\n";
// Define memory for the user data
writer << "memory input_data = memory({input_data_desc, cpu_engine}, " << args[2].get_name()
<< ");\n";
writer << "memory weights = memory({weights_desc, cpu_engine}, bn_weights.data()"
<< ");\n";
writer << "memory mean = memory({mean_desc, cpu_engine}, " << args[3].get_name() << ");\n";
writer << "memory variance = memory({variance_desc, cpu_engine}, " << args[4].get_name()
<< ");\n";
writer << "memory result = memory({result_desc, cpu_engine}, " << out[0].get_name() << ");\n";
// create batchnorm descriptor
writer << "batch_normalization_forward::desc bn_fprop_desc = "
"batch_normalization_forward::desc(forward_training,"
<< "input_data_desc, epsilon, use_global_stats|use_scale_shift);\n";
// bn fprop primitive descriptor
writer << "batch_normalization_forward::primitive_desc bn_fprop_prim_desc = "
"batch_normalization_forward::primitive_desc(bn_fprop_desc, cpu_engine);\n";
// create a batchnorm fprop primitive
writer
<< "batch_normalization_forward bn_fprop = batch_normalization_forward(bn_fprop_prim_desc, "
"primitive::at(input_data),primitive::at(mean), primitive::at(variance),"
<< "primitive::at(weights), result); \n";
// create stream and execute
writer << "stream s = stream(stream::kind::eager);\n"
<< "s.submit({bn_fprop}).wait();\n";
writer.indent--;
writer << "}\n";
}
void runtime::cpu::CPU_Emitter::EMITTER_DECL(EmitDot)
{
const ngraph::op::Dot* dot = static_cast<const ngraph::op::Dot*>(node);
......@@ -343,10 +423,16 @@ void runtime::cpu::CPU_Emitter::EMITTER_DECL(EmitAbs)
writer << emit_array1d(out[0]) << " =\n";
writer << "Eigen::abs(" << emit_array1d(args[0]) << ");\n";
#else
// Some C++ implementations don't like it when we call std::abs on unsigned types, so we will
// avoid doing so here.
auto& result_element_type = out[0].get_element_type();
writer << "#pragma omp parallel for\n";
writer << "for (size_t i = 0; i < " << out[0].get_size() << "; i++)\n";
writer << "{\n";
writer << " " << out[0].get_name() << "[i] = std::abs(" << args[0].get_name() << "[i]);\n";
writer << " " << out[0].get_name()
<< "[i] = " << (result_element_type.is_signed() ? "std::abs" : "") << "("
<< args[0].get_name() << "[i]);\n";
writer << "}\n";
#endif
writer.indent--;
......
......@@ -102,6 +102,7 @@ namespace ngraph
static void EMITTER_DECL(EmitAvgPool);
static void EMITTER_DECL(EmitAvgPoolBackprop);
static void EMITTER_DECL(EmitPad);
static void EMITTER_DECL(EmitBatchNorm);
static void EMITTER_DECL(EmitMaxPoolBackprop);
static void EmitMKLDNNPreamble(codegen::CodeWriter& writer);
......
......@@ -39,6 +39,7 @@
#include "ngraph/ops/asin.hpp"
#include "ngraph/ops/atan.hpp"
#include "ngraph/ops/avg_pool.hpp"
#include "ngraph/ops/batch_norm.hpp"
#include "ngraph/ops/broadcast.hpp"
#include "ngraph/ops/ceiling.hpp"
#include "ngraph/ops/concatenate.hpp"
......@@ -215,6 +216,7 @@ static const runtime::cpu::OpMap dispatcher{
{TI(ngraph::op::AvgPool), &runtime::cpu::CPU_Emitter::EmitAvgPool},
{TI(ngraph::op::AvgPoolBackprop), &runtime::cpu::CPU_Emitter::EmitAvgPoolBackprop},
{TI(ngraph::op::Pad), &runtime::cpu::CPU_Emitter::EmitPad},
{TI(ngraph::op::BatchNorm), &runtime::cpu::CPU_Emitter::EmitBatchNorm},
{TI(ngraph::op::MaxPoolBackprop), &runtime::cpu::CPU_Emitter::EmitMaxPoolBackprop},
};
......@@ -244,7 +246,6 @@ void runtime::cpu::CPU_ExternalFunction::compile()
pass_manager.register_pass<ngraph::pass::MemoryLayout>(s_memory_pool_alignment);
pass_manager.run_passes(m_function);
codegen::CodeWriter writer;
bool include_mkldnn_headers = false;
......@@ -262,7 +263,6 @@ void runtime::cpu::CPU_ExternalFunction::compile()
writer +=
R"(// Generated by the NGraph CPU backend
#include <cmath>
)";
writer +=
......@@ -831,7 +831,11 @@ using namespace ngraph::runtime;
m_execution_engine->add_module(codegen_module);
m_execution_engine->finalize();
m_compiled_function = m_execution_engine->find_function<EntryPoint_t>(function_name);
assert(m_compiled_function);
if (m_compiled_function == nullptr)
{
throw runtime_error("could not find compiled function");
}
m_is_compiled = true;
if (m_release_function)
......
......@@ -14,9 +14,9 @@
* limitations under the License.
*******************************************************************************/
#include <algorithm>
#include "cpu_layout_descriptor.hpp"
#include <algorithm>
#include <numeric>
namespace ngraph
{
......
......@@ -18,6 +18,7 @@
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include <mkldnn.hpp>
......
......@@ -14,12 +14,14 @@
* limitations under the License.
*******************************************************************************/
#include <string>
#include <typeindex>
#include <typeinfo>
#include <unordered_set>
#include "ngraph/node.hpp"
#include "ngraph/ops/avg_pool.hpp"
#include "ngraph/ops/batch_norm.hpp"
#include "ngraph/ops/convolution.hpp"
#include "ngraph/ops/max_pool.hpp"
......@@ -38,6 +40,7 @@ namespace ngraph
const std::unordered_set<std::type_index> s_op_registry{
TI(ngraph::op::AvgPool),
TI(ngraph::op::AvgPoolBackprop),
TI(ngraph::op::BatchNorm)};
TI(ngraph::op::Convolution),
TI(ngraph::op::ConvolutionBackpropData),
TI(ngraph::op::ConvolutionBackpropFilters),
......
......@@ -16,6 +16,7 @@
#pragma once
#include <string>
#include <typeindex>
#include <typeinfo>
#include <unordered_set>
......
......@@ -47,7 +47,9 @@ namespace ngraph
const std::vector<std::shared_ptr<Node>>& new_args) const override
{
if (new_args.size() != 1)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<ConvertLayout>(new_args.at(0), output_layout);
}
......
......@@ -20,7 +20,9 @@ std::shared_ptr<ngraph::Node> ngraph::op::MatmulBias::copy_with_new_args(
const std::vector<std::shared_ptr<ngraph::Node>>& new_args) const
{
if (new_args.size() != 2)
{
throw ngraph_error("Incorrect number of new arguments");
}
return std::make_shared<MatmulBias>(new_args.at(0),
new_args.at(1),
new_args.at(1),
......
/*******************************************************************************
* Copyright 2018 Intel Corporation
* Copyright 2017-2018 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -17,15 +17,24 @@
#include "cpu_fusion.hpp"
#include <algorithm>
#include <iostream>
#include <numeric>
#include <unordered_set>
#include "ngraph/graph_util.hpp"
#include "ngraph/log.hpp"
#include "ngraph/ops/add.hpp"
#include "ngraph/ops/add.hpp"
#include "ngraph/ops/batch_norm.hpp"
#include "ngraph/ops/broadcast.hpp"
#include "ngraph/ops/broadcast.hpp"
#include "ngraph/ops/constant.hpp"
#include "ngraph/ops/divide.hpp"
#include "ngraph/ops/dot.hpp"
#include "ngraph/ops/multiply.hpp"
#include "ngraph/ops/parameter.hpp"
#include "ngraph/ops/reshape.hpp"
#include "ngraph/ops/sqrt.hpp"
#include "ngraph/ops/subtract.hpp"
#include "ngraph/ops/sum.hpp"
#include "ngraph/pattern/matcher.hpp"
#include "ngraph/pattern/op/any.hpp"
#include "ngraph/pattern/op/label.hpp"
......@@ -166,3 +175,98 @@ void ngraph::runtime::cpu::pass::CPUFusion::construct_gemm_pattern()
auto m = std::make_shared<ngraph::pattern::Matcher>(padd, callback);
this->add_matcher(m);
}
void ngraph::runtime::cpu::pass::CPUFusion::construct_fprop_bn()
{
// construct varaiance
auto N = op::Constant::create(element::f32, Shape{3}, {2, 2, 2});
auto input = std::make_shared<pattern::op::Label>(element::f32, Shape{2, 3});
auto input_sq = std::make_shared<op::Multiply>(input, input);
auto sum_input = std::make_shared<op::Sum>(input, AxisSet{0});
auto square_sumed_input = std::make_shared<op::Multiply>(sum_input, sum_input);
auto sum_squared_input = std::make_shared<op::Sum>(input_sq, AxisSet{0});
auto avg_input_sum_sq = std::make_shared<op::Divide>(square_sumed_input, N);
auto xmu = std::make_shared<op::Subtract>(sum_squared_input, avg_input_sum_sq);
auto variance = std::make_shared<op::Divide>(xmu, N);
auto variance_label = std::make_shared<pattern::op::Label>(variance, nullptr, Nodes{variance});
auto variance_with_broadcast =
std::make_shared<op::Broadcast>(variance_label, Shape{2, 3}, AxisSet{0});
// construct mean
auto sum_input1 = std::make_shared<op::Sum>(input, AxisSet{0});
auto mean = std::make_shared<op::Divide>(sum_input1, N);
auto mean_label = std::make_shared<pattern::op::Label>(mean, nullptr, Nodes{mean});
auto mean_with_broadcast = std::make_shared<op::Broadcast>(mean_label, Shape{2, 3}, AxisSet{0});
auto input_diff_mean = std::make_shared<op::Subtract>(input, mean_with_broadcast);
// Eps
auto eps_label = std::make_shared<pattern::op::Label>(element::f32, Shape{3});
auto eps_with_broadcast = std::make_shared<op::Broadcast>(eps_label, Shape{2, 3}, AxisSet{0});
auto add1 = std::make_shared<op::Add>(eps_with_broadcast, variance_with_broadcast);
auto sqrt_variance_eps = std::make_shared<op::Sqrt>(add1);
auto divide_mean_variance = std::make_shared<op::Divide>(input_diff_mean, sqrt_variance_eps);
//Gamma
auto gamma_label = std::make_shared<pattern::op::Label>(element::f32, Shape{3});
auto gamma_with_broadcast =
std::make_shared<op::Broadcast>(gamma_label, Shape{2, 3}, AxisSet{0});
auto multiply_gamma =
std::make_shared<op::Multiply>(gamma_with_broadcast, divide_mean_variance);
//Beta
auto beta_label = std::make_shared<pattern::op::Label>(element::f32, Shape{3});
auto beta_with_broadcast = std::make_shared<op::Broadcast>(beta_label, Shape{2, 3}, AxisSet{0});
auto add_beta = std::make_shared<op::Add>(beta_with_broadcast, multiply_gamma);
// This completes fprop bn pattern
//Define a call back that needs to called once the DFG matches the pattern
ngraph::pattern::gr_callback_fn callback =
[variance_label, mean_label, input, eps_label, gamma_label, beta_label](
pattern::Matcher& m) {
NGRAPH_DEBUG << "In a callback for construct_fprop_bn pattern against "
<< m.match_root()->get_name();
std::shared_ptr<Node> nn = nullptr;
//TODO - add assert's based on the matched node
auto pattern_map = m.get_pattern_map();
NGRAPH_DEBUG << "Input: " << pattern_map[input]->get_name() << " "
<< pattern_map[input]->get_shape().size();
NGRAPH_DEBUG << "Variance: " << pattern_map[variance_label]->get_name() << " "
<< pattern_map[variance_label]->get_shape().size();
NGRAPH_DEBUG << "Mean: " << pattern_map[mean_label]->get_name() << " "
<< pattern_map[mean_label]->get_shape().size();
NGRAPH_DEBUG << "eps: " << pattern_map[eps_label]->get_name() << " "
<< pattern_map[eps_label]->get_shape().size();
NGRAPH_DEBUG << "gamma: " << pattern_map[gamma_label]->get_name() << " "
<< pattern_map[gamma_label]->get_shape().size();
NGRAPH_DEBUG << "beta: " << pattern_map[beta_label]->get_name() << " "
<< pattern_map[beta_label]->get_shape().size();
// dont fuse if the inout doesnt have 4dims
if (pattern_map[input]->get_shape().size() != 4)
{
NGRAPH_DEBUG << "Input to bn doesnt not have a rank=4, so not fusing";
return nn;
}
Shape bn_output_shape{m.match_root()->get_shape()};
Shape m_bn_mean_shape{pattern_map[mean_label]->get_shape()};
Shape m_bn_variance_shape{pattern_map[variance_label]->get_shape()};
// get epsilon value
auto eps_ptr = std::dynamic_pointer_cast<op::Constant>(pattern_map[eps_label]);
double epsilon = *(reinterpret_cast<const double*>(eps_ptr->get_data_ptr()));
auto bn_node = std::shared_ptr<Node>(new op::BatchNorm(epsilon,
pattern_map[gamma_label],
pattern_map[beta_label],
pattern_map[input],
pattern_map[mean_label],
pattern_map[variance_label]));
return bn_node;
};
auto m = std::make_shared<ngraph::pattern::Matcher>(add_beta, callback);
this->add_matcher(m);
}
/*******************************************************************************
* Copyright 2018 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/pass/graph_rewrite.hpp"
namespace ngraph
{
namespace runtime
{
namespace cpu
{
namespace pass
{
class CPUFusion;
}
}
}
}
class ngraph::runtime::cpu::pass::CPUFusion : public ngraph::pass::GraphRewrite
{
public:
CPUFusion()
: GraphRewrite()
{
construct_gemm_pattern();
}
private:
void construct_gemm_pattern();
};
/*******************************************************************************
* Copyright 2017-2018 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/pass/graph_rewrite.hpp"
namespace ngraph
{
namespace runtime
{
namespace cpu
{
namespace pass
{
class CPUFusion;
}
}
}
}
class ngraph::runtime::cpu::pass::CPUFusion : public ngraph::pass::GraphRewrite
{
public:
CPUFusion()
: GraphRewrite()
{
construct_gemm_pattern();
construct_fprop_bn();
}
private:
void construct_gemm_pattern();
void construct_fprop_bn();
};
......@@ -16,6 +16,7 @@
#include <algorithm>
#include <memory>
#include <string>
#include <mkldnn.hpp>
......
......@@ -22,6 +22,7 @@
#include "ngraph/ops/asin.hpp"
#include "ngraph/ops/atan.hpp"
#include "ngraph/ops/avg_pool.hpp"
#include "ngraph/ops/batch_norm.hpp"
#include "ngraph/ops/broadcast.hpp"
#include "ngraph/ops/ceiling.hpp"
#include "ngraph/ops/concatenate.hpp"
......@@ -367,6 +368,11 @@ static shared_ptr<ngraph::Function>
padding_below,
padding_above);
}
else if (node_op == "BatchNorm")
{
auto epsilon = node_js.at("eps").get<double>();
node = make_shared<op::BatchNorm>(epsilon, args[0], args[1], args[2], args[3], args[4]);
}
else if (node_op == "Broadcast")
{
auto shape = node_js.at("shape").get<vector<size_t>>();
......@@ -840,6 +846,11 @@ static json write(const Node& n)
node["padding_below"] = tmp->get_padding_below();
node["padding_above"] = tmp->get_padding_above();
}
else if (node_op == "BatchNorm")
{
auto tmp = dynamic_cast<const op::BatchNorm*>(&n);
node["eps"] = tmp->get_eps_value();
}
else if (node_op == "Broadcast")
{
auto tmp = dynamic_cast<const op::Broadcast*>(&n);
......
......@@ -14,7 +14,7 @@
# limitations under the License.
# ******************************************************************************
if (NGRAPH_CPU_ENABLE AND NOT APPLE)
if (NGRAPH_CPU_ENABLE)
set (SRC
main.cpp
util.cpp
......
......@@ -83,10 +83,21 @@ int main(int argc, char** argv)
}
}
vector<ResourceInfo> include_paths;
#ifdef __APPLE__
include_paths.push_back({EIGEN_HEADERS_PATH, {}, true});
include_paths.push_back({MKLDNN_HEADERS_PATH, {}, true});
#ifdef NGRAPH_TBB_ENABLE
include_paths.push_back({TBB_HEADERS_PATH, {}, true});
#endif
include_paths.push_back({NGRAPH_HEADERS_PATH, {}, true});
include_paths.push_back({CLANG_BUILTIN_HEADERS_PATH, {}, true});
include_paths.push_back({"/Library/Developer/CommandLineTools/usr/include/c++/v1", {}});
#else // __APPLE__
string cpp0 = find_path("/usr/include/x86_64-linux-gnu/c++/");
string cpp1 = find_path("/usr/include/c++/");
vector<ResourceInfo> include_paths;
include_paths.push_back({CLANG_BUILTIN_HEADERS_PATH, {}, true});
include_paths.push_back({"/usr/include/x86_64-linux-gnu", {"asm", "sys", "bits", "gnu"}});
include_paths.push_back({"/usr/include", {"asm", "sys", "bits", "gnu"}});
......@@ -99,6 +110,7 @@ int main(int argc, char** argv)
include_paths.push_back({NGRAPH_HEADERS_PATH, {}, true});
#ifdef NGRAPH_TBB_ENABLE
include_paths.push_back({TBB_HEADERS_PATH, {}, true});
#endif
#endif
if (output_path.empty())
......
This diff is collapsed.
[{
"name" : "Function_4",
"ops" : [
{
"element_type" : "float",
"inputs" : [],
"name" : "Parameter_155",
"op" : "Parameter",
"outputs" : ["Parameter_155_0"],
"shape" : [ 2, 3, 2, 2 ]
},
{
"element_type" : "float",
"inputs" : [],
"name" : "Parameter_109",
"op" : "Parameter",
"outputs" : ["Parameter_109_0"],
"shape" : [3]
},
{
"element_type" : "float",
"inputs" : [],
"name" : "Parameter_108",
"op" : "Parameter",
"outputs" : ["Parameter_108_0"],
"shape" : [3]
},
{
"element_type" : "float",
"inputs" : [],
"name" : "Parameter_107",
"op" : "Parameter",
"outputs" : ["Parameter_107_0"],
"shape" : [3]
},
{
"element_type" : "float",
"inputs" : [],
"name" : "Parameter_106",
"op" : "Parameter",
"outputs" : ["Parameter_106_0"],
"shape" : [3]
},
{
"element_type" : "float",
"inputs" : [],
"name" : "Parameter_105",
"op" : "Parameter",
"outputs" : ["Parameter_105_0"],
"shape" : [ 2, 3, 2, 2 ]
},
{
"element_type" : "float",
"inputs" : [],
"name" : "Constant_137",
"op" : "Constant",
"outputs" : ["Constant_137_0"],
"shape" : [],
"value" : ["0.001"]
},
{
"element_type" : "float",
"inputs" : [],
"name" : "Constant_117",
"op" : "Constant",
"outputs" : ["Constant_117_0"],
"shape" : [3],
"value" : [ "8", "8", "8" ]
},
{
"element_type" : "float",
"inputs" : [],
"name" : "Constant_111",
"op" : "Constant",
"outputs" : ["Constant_111_0"],
"shape" : [3],
"value" : [ "8", "8", "8" ]
},
{
"input_order" : [0],
"inputs" : ["Parameter_107"],
"name" : "Reshape_148",
"op" : "Reshape",
"output_shape" : [ 1, 3, 1, 1 ],
"outputs" : ["Reshape_148_0"]
},
{
"input_order" : [0],
"inputs" : ["Parameter_106"],
"name" : "Reshape_147",
"op" : "Reshape",
"output_shape" : [ 1, 3, 1, 1 ],
"outputs" : ["Reshape_147_0"]
},
{
"inputs" : [ "Parameter_105", "Parameter_105" ],
"name" : "Multiply_115",
"op" : "Multiply",
"outputs" : ["Multiply_115_0"]
},
{
"inputs" : ["Parameter_105"],
"name" : "Sum_110",
"op" : "Sum",
"outputs" : ["Sum_110_0"],
"reduction_axes" : [ 0, 2, 3 ]
},
{
"inputs" : ["Parameter_105"],
"name" : "Sum_114",
"op" : "Sum",
"outputs" : ["Sum_114_0"],
"reduction_axes" : [ 0, 2, 3 ]
},
{
"axes" : [ 0, 1, 2, 3 ],
"inputs" : ["Constant_137"],
"name" : "Broadcast_138",
"op" : "Broadcast",
"outputs" : ["Broadcast_138_0"],
"shape" : [ 2, 3, 2, 2 ]
},
{
"input_order" : [ 0, 1, 2, 3 ],
"inputs" : ["Reshape_148"],
"name" : "Reshape_152",
"op" : "Reshape",
"output_shape" : [3],
"outputs" : ["Reshape_152_0"]
},
{
"input_order" : [ 0, 1, 2, 3 ],
"inputs" : ["Reshape_147"],
"name" : "Reshape_149",
"op" : "Reshape",
"output_shape" : [3],
"outputs" : ["Reshape_149_0"]
},
{
"inputs" : ["Multiply_115"],
"name" : "Sum_116",
"op" : "Sum",
"outputs" : ["Sum_116_0"],
"reduction_axes" : [ 0, 2, 3 ]
},
{
"inputs" : [ "Sum_110", "Constant_111" ],
"name" : "Divide_112",
"op" : "Divide",
"outputs" : ["Divide_112_0"]
},
{
"inputs" : [ "Sum_114", "Sum_114" ],
"name" : "Multiply_118",
"op" : "Multiply",
"outputs" : ["Multiply_118_0"]
},
{
"axes" : [ 0, 2, 3 ],
"inputs" : ["Reshape_152"],
"name" : "Broadcast_153",
"op" : "Broadcast",
"outputs" : ["Broadcast_153_0"],
"shape" : [ 2, 3, 2, 2 ]
},
{
"axes" : [ 0, 2, 3 ],
"inputs" : ["Reshape_149"],
"name" : "Broadcast_150",
"op" : "Broadcast",
"outputs" : ["Broadcast_150_0"],
"shape" : [ 2, 3, 2, 2 ]
},
{
"input_order" : [0],
"inputs" : ["Divide_112"],
"name" : "Reshape_113",
"op" : "Reshape",
"output_shape" : [ 1, 3, 1, 1 ],
"outputs" : ["Reshape_113_0"]
},
{
"inputs" : [ "Multiply_118", "Constant_117" ],
"name" : "Divide_119",
"op" : "Divide",
"outputs" : ["Divide_119_0"]
},
{
"input_order" : [ 0, 1, 2, 3 ],
"inputs" : ["Reshape_113"],
"name" : "Reshape_143",
"op" : "Reshape",
"output_shape" : [3],
"outputs" : ["Reshape_143_0"]
},
{
"inputs" : [ "Sum_116", "Divide_119" ],
"name" : "Subtract_120",
"op" : "Subtract",
"outputs" : ["Subtract_120_0"]
},
{
"axes" : [ 0, 2, 3 ],
"inputs" : ["Reshape_143"],
"name" : "Broadcast_144",
"op" : "Broadcast",
"outputs" : ["Broadcast_144_0"],
"shape" : [ 2, 3, 2, 2 ]
},
{
"inputs" : [ "Subtract_120", "Constant_117" ],
"name" : "Divide_121",
"op" : "Divide",
"outputs" : ["Divide_121_0"]
},
{
"inputs" : [ "Parameter_105", "Broadcast_144" ],
"name" : "Subtract_145",
"op" : "Subtract",
"outputs" : ["Subtract_145_0"]
},
{
"input_order" : [0],
"inputs" : ["Divide_121"],
"name" : "Reshape_122",
"op" : "Reshape",
"output_shape" : [ 1, 3, 1, 1 ],
"outputs" : ["Reshape_122_0"]
},
{
"input_order" : [ 0, 1, 2, 3 ],
"inputs" : ["Reshape_122"],
"name" : "Reshape_139",
"op" : "Reshape",
"output_shape" : [3],
"outputs" : ["Reshape_139_0"]
},
{
"axes" : [ 0, 2, 3 ],
"inputs" : ["Reshape_139"],
"name" : "Broadcast_140",
"op" : "Broadcast",
"outputs" : ["Broadcast_140_0"],
"shape" : [ 2, 3, 2, 2 ]
},
{
"inputs" : [ "Broadcast_140", "Broadcast_138" ],
"name" : "Add_141",
"op" : "Add",
"outputs" : ["Add_141_0"]
},
{
"inputs" : ["Add_141"],
"name" : "Sqrt_142",
"op" : "Sqrt",
"outputs" : ["Sqrt_142_0"]
},
{
"inputs" : [ "Subtract_145", "Sqrt_142" ],
"name" : "Divide_146",
"op" : "Divide",
"outputs" : ["Divide_146_0"]
},
{
"inputs" : [ "Divide_146", "Broadcast_150" ],
"name" : "Multiply_151",
"op" : "Multiply",
"outputs" : ["Multiply_151_0"]
},
{
"inputs" : [ "Multiply_151", "Broadcast_153" ],
"name" : "Add_154",
"op" : "Add",
"outputs" : ["Add_154_0"]
},
{
"inputs" : [ "Add_154", "Parameter_155" ],
"name" : "Multiply_156",
"op" : "Multiply",
"outputs" : ["Multiply_156_0"]
}
],
"parameters" : [
"Parameter_105", "Parameter_106", "Parameter_107", "Parameter_108",
"Parameter_109", "Parameter_155"
],
"result" : ["Multiply_156"]
}]
......@@ -21,15 +21,26 @@
#include <memory>
#include "gtest/gtest.h"
#include "ngraph/file_util.hpp"
#include "ngraph/graph_util.hpp"
#include "ngraph/log.hpp"
#include "ngraph/ngraph.hpp"
#include "ngraph/ops/add.hpp"
#include "ngraph/ops/batch_norm.hpp"
#include "ngraph/ops/constant.hpp"
#include "ngraph/ops/divide.hpp"
#include "ngraph/ops/multiply.hpp"
#include "ngraph/ops/sqrt.hpp"
#include "ngraph/ops/subtract.hpp"
#include "ngraph/ops/sum.hpp"
#include "ngraph/ops/sum.hpp"
#include "ngraph/pass/graph_rewrite.hpp"
#include "ngraph/pass/manager.hpp"
#include "ngraph/pattern/matcher.hpp"
#include "ngraph/pattern/op/any.hpp"
#include "ngraph/pattern/op/label.hpp"
#include "ngraph/runtime/cpu/pass/cpu_fusion.hpp"
#include "ngraph/serializer.hpp"
#include "util/matcher.hpp"
using namespace ngraph;
......@@ -125,6 +136,34 @@ std::shared_ptr<pattern::op::Label> construct_sum_pattern() //for the sake of ex
return std::make_shared<pattern::op::Label>(element::i32, Shape{}, sum_predicate);
}
static std::shared_ptr<pattern::op::Label> construct_variance_graph()
{
// construct varaiance
auto N = op::Constant::create(element::f32, Shape{3}, {2, 2, 2});
auto input = std::make_shared<pattern::op::Label>(element::f32, Shape{2, 3});
auto input_sq = std::make_shared<op::Multiply>(input, input);
auto sum_input = std::make_shared<op::Sum>(input, AxisSet{0});
auto square_sumed_input = std::make_shared<op::Multiply>(sum_input, sum_input);
auto sum_squared_input = std::make_shared<op::Sum>(input_sq, AxisSet{0});
auto avg_input_sum_sq = std::make_shared<op::Divide>(square_sumed_input, N);
auto xmu = std::make_shared<op::Subtract>(sum_squared_input, avg_input_sum_sq);
auto variance = std::make_shared<op::Divide>(xmu, N);
auto variance_label = std::make_shared<pattern::op::Label>(variance, nullptr, Nodes{variance});
return variance_label;
}
static std::shared_ptr<pattern::op::Label> construct_mean_graph()
{
//construct mean;
auto input = std::make_shared<pattern::op::Label>(element::f32, Shape{2, 3});
auto N = op::Constant::create(element::f32, Shape{3}, {2, 2, 2});
auto sum_input1 = std::make_shared<op::Sum>(input, AxisSet{0});
auto mean = std::make_shared<op::Divide>(sum_input1, N);
auto mean_label = std::make_shared<pattern::op::Label>(mean, nullptr, Nodes{mean});
return mean_label;
}
class TestGraphRewrite : public ngraph::pass::GraphRewrite
{
public:
......@@ -474,3 +513,37 @@ TEST(pattern, sum)
ASSERT_TRUE(n.match(nested_reduce_label, nested_sum_graph));
ASSERT_EQ(n.get_pattern_map()[reduce_label], sum_graph);
}
TEST(pattern, mean)
{
//construct mean
TestMatcher n(nullptr);
auto input = std::make_shared<op::Parameter>(element::f32, Shape{2, 3});
auto N = op::Constant::create(element::f32, Shape{3}, {2, 2, 2});
auto sum_input1 = std::make_shared<op::Sum>(input, AxisSet{0});
auto mean = std::make_shared<op::Divide>(sum_input1, N);
auto mean_graph = construct_mean_graph();
ASSERT_TRUE(n.match(mean_graph, mean));
ASSERT_EQ(n.get_pattern_map()[mean_graph], mean);
}
TEST(pattern, variance)
{
//construct variance
TestMatcher n(nullptr);
auto N = op::Constant::create(element::f32, Shape{3}, {2, 2, 2});
auto input = std::make_shared<pattern::op::Label>(element::f32, Shape{2, 3});
auto input_sq = std::make_shared<op::Multiply>(input, input);
auto sum_input = std::make_shared<op::Sum>(input, AxisSet{0});
auto square_sumed_input = std::make_shared<op::Multiply>(sum_input, sum_input);
auto sum_squared_input = std::make_shared<op::Sum>(input_sq, AxisSet{0});
auto avg_input_sum_sq = std::make_shared<op::Divide>(square_sumed_input, N);
auto xmu = std::make_shared<op::Subtract>(sum_squared_input, avg_input_sum_sq);
auto variance = std::make_shared<op::Divide>(xmu, N);
auto var_graph = construct_variance_graph();
ASSERT_TRUE(n.match(var_graph, variance));
ASSERT_EQ(n.get_pattern_map()[var_graph], variance);
}
\ No newline at end of file
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