Unverified Commit 33840ab0 authored by Robert Kimball's avatar Robert Kimball Committed by GitHub

Merge branch 'master' into drwebb/cudnn_hello_world

parents 8af5a886 1d919bfc
...@@ -43,6 +43,9 @@ endif() ...@@ -43,6 +43,9 @@ endif()
set(CMAKE_DISABLE_SOURCE_CHANGES ON) set(CMAKE_DISABLE_SOURCE_CHANGES ON)
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
# Create compilation database compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# set directory where the custom finders live # set directory where the custom finders live
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
......
...@@ -11,5 +11,7 @@ ...@@ -11,5 +11,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DIN_NGRAPH_LIBRARY")
add_subdirectory( ngraph ) add_subdirectory( ngraph )
...@@ -45,6 +45,7 @@ set (SRC ...@@ -45,6 +45,7 @@ set (SRC
ops/negative.cpp ops/negative.cpp
ops/op.cpp ops/op.cpp
ops/parameter.cpp ops/parameter.cpp
ops/power.cpp
ops/reduce.cpp ops/reduce.cpp
ops/reshape.cpp ops/reshape.cpp
ops/select.cpp ops/select.cpp
......
...@@ -82,7 +82,7 @@ void Compiler::set_precompiled_header_source(const std::string& source) ...@@ -82,7 +82,7 @@ void Compiler::set_precompiled_header_source(const std::string& source)
std::unique_ptr<llvm::Module> Compiler::compile(const std::string& source) std::unique_ptr<llvm::Module> Compiler::compile(const std::string& source)
{ {
lock_guard<mutex> lock(m_mutex); lock_guard<mutex> lock(m_mutex);
return s_static_compiler.compile(source); return s_static_compiler.compile(compiler_action, source);
} }
static std::string GetExecutablePath(const char* Argv0) static std::string GetExecutablePath(const char* Argv0)
...@@ -112,11 +112,10 @@ StaticCompiler::StaticCompiler() ...@@ -112,11 +112,10 @@ StaticCompiler::StaticCompiler()
args.push_back(m_source_name.c_str()); args.push_back(m_source_name.c_str());
// Prepare DiagnosticEngine // Prepare DiagnosticEngine
DiagnosticOptions DiagOpts; IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
TextDiagnosticPrinter* textDiagPrinter = new clang::TextDiagnosticPrinter(errs(), &DiagOpts); TextDiagnosticPrinter* textDiagPrinter = new clang::TextDiagnosticPrinter(errs(), &*DiagOpts);
IntrusiveRefCntPtr<clang::DiagnosticIDs> pDiagIDs; IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
DiagnosticsEngine* pDiagnosticsEngine = DiagnosticsEngine DiagEngine(DiagID, &*DiagOpts, textDiagPrinter);
new DiagnosticsEngine(pDiagIDs, &DiagOpts, textDiagPrinter);
// Create and initialize CompilerInstance // Create and initialize CompilerInstance
m_compiler = std::unique_ptr<CompilerInstance>(new CompilerInstance()); m_compiler = std::unique_ptr<CompilerInstance>(new CompilerInstance());
...@@ -124,7 +123,7 @@ StaticCompiler::StaticCompiler() ...@@ -124,7 +123,7 @@ StaticCompiler::StaticCompiler()
// Initialize CompilerInvocation // Initialize CompilerInvocation
CompilerInvocation::CreateFromArgs( CompilerInvocation::CreateFromArgs(
m_compiler->getInvocation(), &args[0], &args[0] + args.size(), *pDiagnosticsEngine); m_compiler->getInvocation(), &args[0], &args[0] + args.size(), DiagEngine);
// Infer the builtin include path if unspecified. // Infer the builtin include path if unspecified.
if (m_compiler->getHeaderSearchOpts().UseBuiltinIncludes && if (m_compiler->getHeaderSearchOpts().UseBuiltinIncludes &&
...@@ -209,7 +208,7 @@ StaticCompiler::StaticCompiler() ...@@ -209,7 +208,7 @@ StaticCompiler::StaticCompiler()
CGO.OmitLeafFramePointer = 1; CGO.OmitLeafFramePointer = 1;
CGO.VectorizeLoop = 1; CGO.VectorizeLoop = 1;
CGO.VectorizeSLP = 1; CGO.VectorizeSLP = 1;
CGO.CXAAtExit = 0; CGO.CXAAtExit = 1;
if (m_debuginfo_enabled) if (m_debuginfo_enabled)
{ {
...@@ -305,7 +304,9 @@ void StaticCompiler::use_cached_files() ...@@ -305,7 +304,9 @@ void StaticCompiler::use_cached_files()
} }
} }
std::unique_ptr<llvm::Module> StaticCompiler::compile(const string& source) std::unique_ptr<llvm::Module>
StaticCompiler::compile(std::unique_ptr<clang::CodeGenAction>& compiler_action,
const string& source)
{ {
if (!m_precompiled_header_valid && m_precomiled_header_source.empty() == false) if (!m_precompiled_header_valid && m_precomiled_header_source.empty() == false)
{ {
...@@ -325,11 +326,11 @@ std::unique_ptr<llvm::Module> StaticCompiler::compile(const string& source) ...@@ -325,11 +326,11 @@ std::unique_ptr<llvm::Module> StaticCompiler::compile(const string& source)
m_compiler->getInvocation().getPreprocessorOpts().addRemappedFile(m_source_name, buffer.get()); m_compiler->getInvocation().getPreprocessorOpts().addRemappedFile(m_source_name, buffer.get());
// Create and execute action // Create and execute action
CodeGenAction* compilerAction = new EmitCodeGenOnlyAction(); compiler_action.reset(new EmitCodeGenOnlyAction());
std::unique_ptr<llvm::Module> rc; std::unique_ptr<llvm::Module> rc;
if (m_compiler->ExecuteAction(*compilerAction) == true) if (m_compiler->ExecuteAction(*compiler_action) == true)
{ {
rc = compilerAction->takeModule(); rc = compiler_action->takeModule();
} }
buffer.release(); buffer.release();
...@@ -359,4 +360,5 @@ void StaticCompiler::generate_pch(const string& source) ...@@ -359,4 +360,5 @@ void StaticCompiler::generate_pch(const string& source)
buffer.release(); buffer.release();
m_compiler->getInvocation().getPreprocessorOpts().clearRemappedFiles(); m_compiler->getInvocation().getPreprocessorOpts().clearRemappedFiles();
delete compilerAction;
} }
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <clang/CodeGen/CodeGenAction.h>
#include <llvm/ExecutionEngine/MCJIT.h> // forces JIT to link in #include <llvm/ExecutionEngine/MCJIT.h> // forces JIT to link in
#include <llvm/ExecutionEngine/SectionMemoryManager.h> #include <llvm/ExecutionEngine/SectionMemoryManager.h>
#include <llvm/Option/Arg.h> #include <llvm/Option/Arg.h>
...@@ -53,8 +55,9 @@ public: ...@@ -53,8 +55,9 @@ public:
~Compiler(); ~Compiler();
void set_precompiled_header_source(const std::string& source); void set_precompiled_header_source(const std::string& source);
std::unique_ptr<llvm::Module> compile(const std::string& source); std::unique_ptr<llvm::Module> compile(const std::string& source);
std::unique_ptr<clang::CodeGenAction>& get_compiler_action() { return compiler_action; }
private: private:
std::unique_ptr<clang::CodeGenAction> compiler_action;
}; };
class ngraph::codegen::StaticCompiler : public llvm::SectionMemoryManager class ngraph::codegen::StaticCompiler : public llvm::SectionMemoryManager
...@@ -70,7 +73,9 @@ public: ...@@ -70,7 +73,9 @@ public:
m_precomiled_header_source = source; m_precomiled_header_source = source;
} }
void add_header_search_path(const std::string& path); void add_header_search_path(const std::string& path);
std::unique_ptr<llvm::Module> compile(const std::string& source);
std::unique_ptr<llvm::Module> compile(std::unique_ptr<clang::CodeGenAction>& compiler_action,
const std::string& source);
void generate_pch(const std::string& source); void generate_pch(const std::string& source);
private: private:
......
...@@ -34,11 +34,11 @@ bool codegen::ExecutionEngine::add_module(std::unique_ptr<llvm::Module>& module) ...@@ -34,11 +34,11 @@ bool codegen::ExecutionEngine::add_module(std::unique_ptr<llvm::Module>& module)
{ {
if (!m_execution_engine) if (!m_execution_engine)
{ {
m_execution_engine = llvm::EngineBuilder(move(module)) m_execution_engine.reset(llvm::EngineBuilder(move(module))
.setEngineKind(llvm::EngineKind::JIT) .setEngineKind(llvm::EngineKind::JIT)
.setOptLevel(llvm::CodeGenOpt::Aggressive) .setOptLevel(llvm::CodeGenOpt::Aggressive)
.setErrorStr(&m_jit_error) .setErrorStr(&m_jit_error)
.create(); .create());
if (!m_execution_engine) if (!m_execution_engine)
{ {
......
...@@ -46,7 +46,7 @@ public: ...@@ -46,7 +46,7 @@ public:
} }
private: private:
llvm::ExecutionEngine* m_execution_engine; std::unique_ptr<llvm::ExecutionEngine> m_execution_engine;
std::string m_jit_error; std::string m_jit_error;
template <typename signature> template <typename signature>
......
...@@ -69,6 +69,18 @@ size_t Tensor::get_pool_offset() const ...@@ -69,6 +69,18 @@ size_t Tensor::get_pool_offset() const
std::ostream& operator<<(std::ostream& out, const Tensor& tensor) std::ostream& operator<<(std::ostream& out, const Tensor& tensor)
{ {
out << "Tensor(" << tensor.get_name() << ")"; out << "Tensor(" << tensor.get_name() << ", ";
out << (tensor.is_persistent() ? "P" : "");
out << (tensor.is_constant() ? "C" : "");
out << (tensor.is_input() ? "I" : "");
out << (tensor.is_output() ? "O" : "");
if (!tensor.is_persistent() && !tensor.is_constant() && !tensor.is_input() &&
!tensor.is_output())
{
out << "T";
}
out << ")";
return out; return out;
} }
...@@ -31,9 +31,9 @@ Function::Function(const std::shared_ptr<Node>& result, ...@@ -31,9 +31,9 @@ Function::Function(const std::shared_ptr<Node>& result,
, m_name(name) , m_name(name)
, m_result_type(result_type) , m_result_type(result_type)
, m_ordered_ops_valid(false) , m_ordered_ops_valid(false)
, m_temporary_pool_size(0)
, m_instance_id(m_next_instance_id.fetch_add(1)) , m_instance_id(m_next_instance_id.fetch_add(1))
{ {
m_result->set_is_output();
traverse_nodes(this, [&](shared_ptr<Node> node) { m_ops.push_back(node); }); traverse_nodes(this, [&](shared_ptr<Node> node) { m_ops.push_back(node); });
} }
...@@ -97,6 +97,16 @@ void Function::set_name(const string& name) ...@@ -97,6 +97,16 @@ void Function::set_name(const string& name)
} }
} }
size_t Function::get_temporary_pool_size()
{
return m_temporary_pool_size;
}
void Function::set_temporary_pool_size(size_t size)
{
m_temporary_pool_size = size;
}
std::ostream& ngraph::operator<<(std::ostream& out, const Function& f) std::ostream& ngraph::operator<<(std::ostream& out, const Function& f)
{ {
out << "Function(" << f.get_name() << ")"; out << "Function(" << f.get_name() << ")";
......
...@@ -56,6 +56,9 @@ namespace ngraph ...@@ -56,6 +56,9 @@ namespace ngraph
void clear_ordered_ops_valid() { m_ordered_ops_valid = false; } void clear_ordered_ops_valid() { m_ordered_ops_valid = false; }
friend std::ostream& operator<<(std::ostream&, const Function&); friend std::ostream& operator<<(std::ostream&, const Function&);
size_t get_instance_id() { return m_instance_id; } size_t get_instance_id() { return m_instance_id; }
size_t get_temporary_pool_size();
void set_temporary_pool_size(size_t);
protected: protected:
std::shared_ptr<Node> m_result; std::shared_ptr<Node> m_result;
std::vector<std::shared_ptr<ngraph::op::Parameter>> m_parameters; std::vector<std::shared_ptr<ngraph::op::Parameter>> m_parameters;
...@@ -64,6 +67,7 @@ namespace ngraph ...@@ -64,6 +67,7 @@ namespace ngraph
bool m_ordered_ops_valid; bool m_ordered_ops_valid;
std::list<std::shared_ptr<Node>> m_ordered_ops; std::list<std::shared_ptr<Node>> m_ordered_ops;
std::list<std::shared_ptr<Node>> m_ops; std::list<std::shared_ptr<Node>> m_ops;
size_t m_temporary_pool_size;
private: private:
Function(const Function&) = delete; Function(const Function&) = delete;
......
This diff is collapsed.
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
#pragma once #pragma once
#ifdef IN_NGRAPH_LIBRARY
#error("ngraph.hpp is for external use only")
#endif
/// @namespace ngraph /// @namespace ngraph
/// @brief The Intel Nervana Graph C++ API. /// @brief The Intel Nervana Graph C++ API.
......
...@@ -12,8 +12,10 @@ ...@@ -12,8 +12,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#include "ngraph/node.hpp"
#include "ngraph/autodiff/adjoints.hpp" #include "ngraph/autodiff/adjoints.hpp"
#include "ngraph/ngraph.hpp" #include "ngraph/descriptor/primary_tensor_view.hpp"
#include "ngraph/ops/parameter.hpp"
using namespace std; using namespace std;
using namespace ngraph; using namespace ngraph;
......
// ----------------------------------------------------------------------------
// Copyright 2017 Nervana Systems Inc.
// 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
// ----------------------------------------------------------------------------
#include "ngraph/ops/power.hpp"
#include "ngraph/ops/divide.hpp"
#include "ngraph/ops/log.hpp"
#include "ngraph/ops/multiply.hpp"
void ngraph::op::Power::generate_adjoints(autodiff::Adjoints& adjoints,
const std::shared_ptr<Node>& delta)
{
auto x = m_arguments[0];
auto y = m_arguments[1];
auto log_x = std::make_shared<op::Log>(x);
adjoints.add_delta(x, delta * y * shared_from_this() / x);
adjoints.add_delta(y, delta * shared_from_this() * log_x);
}
...@@ -37,9 +37,9 @@ namespace ngraph ...@@ -37,9 +37,9 @@ namespace ngraph
/// ///
/// ## Implementation Status /// ## Implementation Status
/// ///
/// | Backend | Status | /// | Backend | Status |
/// | ------- | ---------------- | /// | ------- | ------------------ |
/// | NGVM | Not implemented. | /// | NGVM | Fully implemented. |
class Power : public BinaryElementwiseArithmetic class Power : public BinaryElementwiseArithmetic
{ {
public: public:
...@@ -59,6 +59,10 @@ namespace ngraph ...@@ -59,6 +59,10 @@ namespace ngraph
throw ngraph_error("Incorrect number of new arguments"); throw ngraph_error("Incorrect number of new arguments");
return std::make_shared<Power>(new_args.at(0), new_args.at(1)); return std::make_shared<Power>(new_args.at(0), new_args.at(1));
} }
protected:
virtual void generate_adjoints(autodiff::Adjoints& adjoints,
const std::shared_ptr<Node>& delta) override;
}; };
} }
} }
...@@ -67,6 +67,7 @@ void ngraph::pass::Manager::run_passes(shared_ptr<Function> func) ...@@ -67,6 +67,7 @@ void ngraph::pass::Manager::run_passes(shared_ptr<Function> func)
vector<shared_ptr<Function>> fs; vector<shared_ptr<Function>> fs;
for (shared_ptr<Function> f : get_state().get_functions()) for (shared_ptr<Function> f : get_state().get_functions())
{ {
f->get_result()->set_is_output();
fs.push_back(f); fs.push_back(f);
} }
......
...@@ -27,13 +27,3 @@ const vector<shared_ptr<Function>>& ngraph::pass::ManagerState::get_functions() ...@@ -27,13 +27,3 @@ const vector<shared_ptr<Function>>& ngraph::pass::ManagerState::get_functions()
{ {
return m_function_list; return m_function_list;
} }
size_t ngraph::pass::ManagerState::get_temporary_pool_size()
{
return m_temporary_pool_size;
}
void ngraph::pass::ManagerState::set_temporary_pool_size(size_t size)
{
m_temporary_pool_size = size;
}
...@@ -39,10 +39,6 @@ public: ...@@ -39,10 +39,6 @@ public:
m_function_list.insert(m_function_list.begin(), collection.begin(), collection.end()); m_function_list.insert(m_function_list.begin(), collection.begin(), collection.end());
} }
size_t get_temporary_pool_size();
void set_temporary_pool_size(size_t);
private: private:
size_t m_temporary_pool_size = 0;
std::vector<std::shared_ptr<Function>> m_function_list; std::vector<std::shared_ptr<Function>> m_function_list;
}; };
...@@ -31,10 +31,10 @@ pass::MemoryLayout::MemoryLayout(size_t alignment) ...@@ -31,10 +31,10 @@ pass::MemoryLayout::MemoryLayout(size_t alignment)
{ {
} }
bool pass::MemoryLayout::run_on_call_graph(std::list<std::shared_ptr<Node>>& node_list) bool pass::MemoryLayout::run_on_function(std::shared_ptr<ngraph::Function> function)
{ {
MemoryManager mm(m_alignment); MemoryManager mm(m_alignment);
for (shared_ptr<Node> node : node_list) for (shared_ptr<Node> node : function->get_ordered_ops())
{ {
for (Tensor* tensor : node->liveness_new_list) for (Tensor* tensor : node->liveness_new_list)
{ {
...@@ -46,7 +46,7 @@ bool pass::MemoryLayout::run_on_call_graph(std::list<std::shared_ptr<Node>>& nod ...@@ -46,7 +46,7 @@ bool pass::MemoryLayout::run_on_call_graph(std::list<std::shared_ptr<Node>>& nod
mm.free(tensor->get_pool_offset()); mm.free(tensor->get_pool_offset());
} }
} }
get_state().set_temporary_pool_size(mm.max_allocated()); function->set_temporary_pool_size(mm.max_allocated());
return false; return false;
} }
......
...@@ -30,11 +30,11 @@ namespace ngraph ...@@ -30,11 +30,11 @@ namespace ngraph
} }
} }
class ngraph::pass::MemoryLayout : public CallGraphPass class ngraph::pass::MemoryLayout : public FunctionPass
{ {
public: public:
MemoryLayout(size_t alignment = 1); MemoryLayout(size_t alignment = 1);
virtual bool run_on_call_graph(std::list<std::shared_ptr<Node>>&) override; bool run_on_function(std::shared_ptr<ngraph::Function>) override;
private: private:
size_t m_alignment; size_t m_alignment;
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include "ngraph/runtime/parameterized_tensor_view.hpp" #include "ngraph/runtime/parameterized_tensor_view.hpp"
#include "ngraph/runtime/tensor_view.hpp" #include "ngraph/runtime/tensor_view.hpp"
#include "ngraph/runtime/tuple.hpp" #include "ngraph/runtime/tuple.hpp"
#include "ngraph/types/element_type.hpp"
using namespace ngraph::runtime; using namespace ngraph::runtime;
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include "ngraph/common.hpp" #include "ngraph/common.hpp"
#include "ngraph/log.hpp" #include "ngraph/log.hpp"
#include "ngraph/runtime/ndarray.hpp" #include "ngraph/types/element_type.hpp"
namespace ngraph namespace ngraph
{ {
...@@ -35,9 +35,6 @@ namespace ngraph ...@@ -35,9 +35,6 @@ namespace ngraph
class Tuple; class Tuple;
class Value; class Value;
template <typename ET>
class ParameterizedTensorView;
/// @brief Interface to a generic backend. /// @brief Interface to a generic backend.
/// ///
/// Backends are responsible for function execution and value allocation. /// Backends are responsible for function execution and value allocation.
...@@ -56,12 +53,11 @@ namespace ngraph ...@@ -56,12 +53,11 @@ namespace ngraph
make_primary_tensor_view(const ngraph::element::Type& element_type, make_primary_tensor_view(const ngraph::element::Type& element_type,
const Shape& shape); const Shape& shape);
template <typename ET> template <typename T>
std::shared_ptr<ngraph::runtime::ParameterizedTensorView<ET>> std::shared_ptr<ngraph::runtime::TensorView>
make_parameterized_tensor_view(const Shape& shape) make_primary_tensor_view(const Shape& shape)
{ {
return std::dynamic_pointer_cast<ngraph::runtime::ParameterizedTensorView<ET>>( return make_primary_tensor_view(element::from<T>(), shape);
make_primary_tensor_view(ET::element_type(), shape));
} }
/// @brief Construct a tuple handle from a sequence of values. /// @brief Construct a tuple handle from a sequence of values.
......
...@@ -36,8 +36,8 @@ namespace ngraph ...@@ -36,8 +36,8 @@ namespace ngraph
/// ///
/// Tuples will be expanded into their tensor views to build the call frame. /// Tuples will be expanded into their tensor views to build the call frame.
virtual void virtual void
operator()(const std::vector<std::shared_ptr<ngraph::runtime::Value>>& inputs, call(const std::vector<std::shared_ptr<ngraph::runtime::Value>>& inputs,
const std::vector<std::shared_ptr<ngraph::runtime::Value>>& outputs) = 0; const std::vector<std::shared_ptr<ngraph::runtime::Value>>& outputs) = 0;
/// @brief Invoke the function with tuples pre-expanded to their underlying tensor views. /// @brief Invoke the function with tuples pre-expanded to their underlying tensor views.
virtual void tensor_call(const TensorViewPtrs& inputs, virtual void tensor_call(const TensorViewPtrs& inputs,
......
...@@ -20,8 +20,10 @@ ...@@ -20,8 +20,10 @@
using namespace std; using namespace std;
using namespace ngraph::runtime::cpu; using namespace ngraph::runtime::cpu;
CallFrame::CallFrame(EntryPoint compiled_function) CallFrame::CallFrame(std::shared_ptr<ExternalFunction> external_function,
: m_compiled_function(compiled_function) EntryPoint compiled_function)
: m_external_function(external_function)
, m_compiled_function(compiled_function)
{ {
} }
...@@ -45,11 +47,11 @@ void CallFrame::tensor_call( ...@@ -45,11 +47,11 @@ void CallFrame::tensor_call(
} }
// Invoke compiled computation // Invoke compiled computation
m_compiled_function(inputs, outputs); m_compiled_function(inputs.data(), outputs.data());
} }
void CallFrame::operator()(const std::vector<std::shared_ptr<ngraph::runtime::Value>>& arguments, void CallFrame::call(const std::vector<std::shared_ptr<ngraph::runtime::Value>>& arguments,
const std::vector<std::shared_ptr<ngraph::runtime::Value>>& results) const std::vector<std::shared_ptr<ngraph::runtime::Value>>& results)
{ {
// TODO: Check types of args and result // TODO: Check types of args and result
vector<shared_ptr<ngraph::runtime::TensorView>> inputs; vector<shared_ptr<ngraph::runtime::TensorView>> inputs;
......
...@@ -31,9 +31,9 @@ namespace ngraph ...@@ -31,9 +31,9 @@ namespace ngraph
namespace cpu namespace cpu
{ {
class CallFrame; class CallFrame;
class ExternalFunction;
using EntryPoint_t = void(const std::vector<void*>& inputs, using EntryPoint_t = void(void** inputs, void** outputs);
const std::vector<void*>& outputs);
using EntryPoint = std::function<EntryPoint_t>; using EntryPoint = std::function<EntryPoint_t>;
...@@ -41,14 +41,14 @@ namespace ngraph ...@@ -41,14 +41,14 @@ namespace ngraph
class CallFrame : public ngraph::runtime::CallFrame class CallFrame : public ngraph::runtime::CallFrame
{ {
public: public:
CallFrame(EntryPoint compiled_function); CallFrame(std::shared_ptr<ExternalFunction> external_function,
EntryPoint compiled_function);
/// @brief Invoke the function with values matching the signature of the function. /// @brief Invoke the function with values matching the signature of the function.
/// ///
/// Tuples will be expanded into their tensor views to build the call frame. /// Tuples will be expanded into their tensor views to build the call frame.
void void call(const std::vector<std::shared_ptr<ngraph::runtime::Value>>& inputs,
operator()(const std::vector<std::shared_ptr<ngraph::runtime::Value>>& inputs, const std::vector<std::shared_ptr<ngraph::runtime::Value>>& outputs);
const std::vector<std::shared_ptr<ngraph::runtime::Value>>& outputs);
/// @brief Invoke the function with tuples pre-expanded to their underlying /// @brief Invoke the function with tuples pre-expanded to their underlying
/// tensor views. /// tensor views.
...@@ -56,6 +56,7 @@ namespace ngraph ...@@ -56,6 +56,7 @@ namespace ngraph
const std::vector<std::shared_ptr<TensorView>>& outputs); const std::vector<std::shared_ptr<TensorView>>& outputs);
protected: protected:
std::shared_ptr<ExternalFunction> m_external_function;
EntryPoint m_compiled_function; EntryPoint m_compiled_function;
}; };
} }
......
This diff is collapsed.
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#define EMITTER_DECL(E) \ #define EMITTER_DECL(E) \
E(const ngraph::Node* n, \ E(const ngraph::Node* n, \
ExternalFunction* ef, \
const std::vector<TensorViewInfo>& inputs, \ const std::vector<TensorViewInfo>& inputs, \
const std::vector<TensorViewInfo>& outputs) const std::vector<TensorViewInfo>& outputs)
...@@ -94,6 +93,7 @@ namespace ngraph ...@@ -94,6 +93,7 @@ namespace ngraph
void EMITTER_DECL(EmitAsin); void EMITTER_DECL(EmitAsin);
void EMITTER_DECL(EmitAcos); void EMITTER_DECL(EmitAcos);
void EMITTER_DECL(EmitAtan); void EMITTER_DECL(EmitAtan);
void EMITTER_DECL(EmitPower);
private: private:
void generate_call(const std::vector<TensorViewInfo>& inputs, void generate_call(const std::vector<TensorViewInfo>& inputs,
......
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#include "ngraph/ops/multiply.hpp" #include "ngraph/ops/multiply.hpp"
#include "ngraph/ops/negative.hpp" #include "ngraph/ops/negative.hpp"
#include "ngraph/ops/not_equal.hpp" #include "ngraph/ops/not_equal.hpp"
#include "ngraph/ops/power.hpp"
#include "ngraph/ops/reduce.hpp" #include "ngraph/ops/reduce.hpp"
#include "ngraph/ops/reshape.hpp" #include "ngraph/ops/reshape.hpp"
#include "ngraph/ops/select.hpp" #include "ngraph/ops/select.hpp"
...@@ -117,6 +118,7 @@ static const OpMap dispatcher{ ...@@ -117,6 +118,7 @@ static const OpMap dispatcher{
{TI(ngraph::op::Minimum), &Emitter::EmitMinimum}, {TI(ngraph::op::Minimum), &Emitter::EmitMinimum},
{TI(ngraph::op::Negative), &Emitter::EmitNegative}, {TI(ngraph::op::Negative), &Emitter::EmitNegative},
{TI(ngraph::op::NotEqual), &Emitter::EmitNotEqual}, {TI(ngraph::op::NotEqual), &Emitter::EmitNotEqual},
{TI(ngraph::op::Power), &Emitter::EmitPower},
{TI(ngraph::op::Select), &Emitter::EmitSelect}, {TI(ngraph::op::Select), &Emitter::EmitSelect},
{TI(ngraph::op::Subtract), &Emitter::EmitSubtract}, {TI(ngraph::op::Subtract), &Emitter::EmitSubtract},
{TI(ngraph::op::ParameterizedConstant<ngraph::element::Bool>), {TI(ngraph::op::ParameterizedConstant<ngraph::element::Bool>),
...@@ -170,13 +172,16 @@ void ExternalFunction::compile() ...@@ -170,13 +172,16 @@ void ExternalFunction::compile()
return; return;
} }
string function_name = m_function->get_name();
string dump_filename = file_util::path_join(s_output_dir, function_name + "_ops.txt");
pass::Manager pass_manager; pass::Manager pass_manager;
pass_manager.register_pass<pass::TopologicalSort>(); pass_manager.register_pass<pass::TopologicalSort>();
// For now, just make everyone row-major. // For now, just make everyone row-major.
pass_manager.register_pass<pass::AssignLayout<DenseTensorViewLayout>>(); pass_manager.register_pass<pass::AssignLayout<DenseTensorViewLayout>>();
pass_manager.register_pass<pass::Liveness>(); pass_manager.register_pass<pass::Liveness>();
pass_manager.register_pass<pass::MemoryLayout>(64); pass_manager.register_pass<pass::MemoryLayout>(64);
pass_manager.register_pass<pass::DumpSorted>("sorted_ops.txt"); pass_manager.register_pass<pass::DumpSorted>(dump_filename);
pass_manager.run_passes(m_function); pass_manager.run_passes(m_function);
// Now we build the TU // Now we build the TU
...@@ -186,7 +191,6 @@ void ExternalFunction::compile() ...@@ -186,7 +191,6 @@ void ExternalFunction::compile()
TU += TU +=
R"(// Generated by the NGraph CPU backend R"(// Generated by the NGraph CPU backend
#include <cmath> #include <cmath>
#include <vector>
#include <Eigen/Dense> #include <Eigen/Dense>
...@@ -199,20 +203,24 @@ using namespace ngraph::runtime::cpu::eigen; ...@@ -199,20 +203,24 @@ using namespace ngraph::runtime::cpu::eigen;
)"; )";
string pch_header_source = TU.get_code(); string pch_header_source = TU.get_code();
// The "dso_handle" symbol is required by __cxa_atexit()
// which is enabled because the JIT uses it as the default mechanism
// to register cleanup handlers. We use it, and not atexit(), because
// atexit() happens too late, when the JIT is no longer alive
TU << "void *__dso_handle = 0;\n\n";
TU << "// Declare all functions\n"; TU << "// Declare all functions\n";
for (shared_ptr<Function> f : pass_manager.get_state().get_functions()) for (shared_ptr<Function> f : pass_manager.get_state().get_functions())
{ {
TU << "extern \"C\" void " << f->get_name() << "(\n"; TU << "extern \"C\" void " << f->get_name() << "(void** inputs, void** outputs);\n";
TU << " const std::vector<void*>& inputs,\n";
TU << " const std::vector<void*>& outputs);\n";
} }
TU << "\n"; TU << "\n";
for (shared_ptr<Function> current_function : pass_manager.get_state().get_functions()) for (shared_ptr<Function> current_function : pass_manager.get_state().get_functions())
{ {
TU << "extern \"C\" void " << current_function->get_name() << "(\n"; TU << "extern \"C\" void " << current_function->get_name();
TU << " const std::vector<void*>& inputs,\n"; TU << "(void** inputs, void** outputs)\n";
TU << " const std::vector<void*>& outputs)\n";
TU << "{\n"; TU << "{\n";
TU.indent++; TU.indent++;
...@@ -227,7 +235,7 @@ using namespace ngraph::runtime::cpu::eigen; ...@@ -227,7 +235,7 @@ using namespace ngraph::runtime::cpu::eigen;
} }
if (temporaries_used) if (temporaries_used)
{ {
size_t temp_pool_size = pass_manager.get_state().get_temporary_pool_size(); size_t temp_pool_size = current_function->get_temporary_pool_size();
TU << "// Allocate the memory pool\n"; TU << "// Allocate the memory pool\n";
TU << "ngraph::runtime::AlignedBuffer memory_handler(" << temp_pool_size << ", " TU << "ngraph::runtime::AlignedBuffer memory_handler(" << temp_pool_size << ", "
<< ngraph::runtime::cpu::alignment << ");\n"; << ngraph::runtime::cpu::alignment << ");\n";
...@@ -297,7 +305,7 @@ using namespace ngraph::runtime::cpu::eigen; ...@@ -297,7 +305,7 @@ using namespace ngraph::runtime::cpu::eigen;
auto tv = output.get_tensor_view(); auto tv = output.get_tensor_view();
out.push_back({0, tv}); out.push_back({0, tv});
} }
handler->second(&emitter, node.get(), this, in, out); handler->second(&emitter, node.get(), in, out);
} }
TU.indent--; TU.indent--;
...@@ -308,7 +316,6 @@ using namespace ngraph::runtime::cpu::eigen; ...@@ -308,7 +316,6 @@ using namespace ngraph::runtime::cpu::eigen;
// TODO: Cleanup and make this a utility function // TODO: Cleanup and make this a utility function
string function_name = m_function->get_name();
file_util::make_directory(s_output_dir); file_util::make_directory(s_output_dir);
string filename = file_util::path_join(s_output_dir, function_name + "_codegen.cpp"); string filename = file_util::path_join(s_output_dir, function_name + "_codegen.cpp");
ofstream out(filename); ofstream out(filename);
...@@ -316,19 +323,20 @@ using namespace ngraph::runtime::cpu::eigen; ...@@ -316,19 +323,20 @@ using namespace ngraph::runtime::cpu::eigen;
out << code; out << code;
out.close(); out.close();
codegen::Compiler compiler; compiler.reset(new codegen::Compiler());
codegen::ExecutionEngine execution_engine; execution_engine.reset(new codegen::ExecutionEngine());
compiler->set_precompiled_header_source(pch_header_source);
compiler.set_precompiled_header_source(pch_header_source); auto llvm_module = compiler->compile(code);
auto llvm_module = compiler.compile(code);
if (llvm_module == nullptr) if (llvm_module == nullptr)
{ {
throw runtime_error("function failed to compile"); throw runtime_error("function failed to compile");
} }
execution_engine.add_module(llvm_module); execution_engine->add_module(llvm_module);
execution_engine.finalize(); execution_engine->finalize();
m_compiled_function = execution_engine.find_function<EntryPoint_t>(function_name); m_compiled_function = execution_engine->find_function<EntryPoint_t>(function_name);
assert(m_compiled_function); assert(m_compiled_function);
m_is_compiled = true; m_is_compiled = true;
...@@ -345,5 +353,5 @@ shared_ptr<ngraph::runtime::CallFrame> ExternalFunction::make_call_frame() ...@@ -345,5 +353,5 @@ shared_ptr<ngraph::runtime::CallFrame> ExternalFunction::make_call_frame()
compile(); compile();
} }
return make_shared<ngraph::runtime::cpu::CallFrame>(m_compiled_function); return make_shared<ngraph::runtime::cpu::CallFrame>(shared_from_this(), m_compiled_function);
} }
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <unordered_map> #include <unordered_map>
#include "ngraph/codegen/compiler.hpp" #include "ngraph/codegen/compiler.hpp"
#include "ngraph/codegen/execution_engine.hpp"
#include "ngraph/function.hpp" #include "ngraph/function.hpp"
#include "ngraph/runtime/cpu/call_frame.hpp" #include "ngraph/runtime/cpu/call_frame.hpp"
#include "ngraph/runtime/external_function.hpp" #include "ngraph/runtime/external_function.hpp"
...@@ -36,18 +37,15 @@ namespace ngraph ...@@ -36,18 +37,15 @@ namespace ngraph
class Emitter; class Emitter;
class CallFrame; class CallFrame;
using FunctionMap =
std::unordered_map<std::shared_ptr<Function>, std::shared_ptr<ExternalFunction>>;
using OpFunction = std::function<void(Emitter*, using OpFunction = std::function<void(Emitter*,
const ngraph::Node*, const ngraph::Node*,
ExternalFunction*,
const std::vector<TensorViewInfo>& inputs, const std::vector<TensorViewInfo>& inputs,
const std::vector<TensorViewInfo>& outputs)>; const std::vector<TensorViewInfo>& outputs)>;
using OpMap = std::unordered_map<std::type_index, OpFunction>; using OpMap = std::unordered_map<std::type_index, OpFunction>;
class ExternalFunction : public ngraph::runtime::ExternalFunction class ExternalFunction : public ngraph::runtime::ExternalFunction,
public std::enable_shared_from_this<ExternalFunction>
{ {
public: public:
ExternalFunction(const std::shared_ptr<ngraph::Function>& function, ExternalFunction(const std::shared_ptr<ngraph::Function>& function,
...@@ -58,6 +56,10 @@ namespace ngraph ...@@ -58,6 +56,10 @@ namespace ngraph
void compile(); void compile();
EntryPoint m_compiled_function; EntryPoint m_compiled_function;
private:
std::unique_ptr<codegen::Compiler> compiler;
std::unique_ptr<codegen::ExecutionEngine> execution_engine;
}; };
} }
} }
......
...@@ -63,8 +63,8 @@ void CallFrame::tensor_call( ...@@ -63,8 +63,8 @@ void CallFrame::tensor_call(
fill_n(m_tensor_views.begin(), m_n_inputs + m_n_outputs, nullptr); fill_n(m_tensor_views.begin(), m_n_inputs + m_n_outputs, nullptr);
} }
void CallFrame::operator()(const std::vector<std::shared_ptr<ngraph::runtime::Value>>& arguments, void CallFrame::call(const std::vector<std::shared_ptr<ngraph::runtime::Value>>& arguments,
const std::vector<std::shared_ptr<ngraph::runtime::Value>>& results) const std::vector<std::shared_ptr<ngraph::runtime::Value>>& results)
{ {
// TODO: Check types of args and result // TODO: Check types of args and result
std::vector<std::shared_ptr<ngraph::runtime::TensorView>> inputs; std::vector<std::shared_ptr<ngraph::runtime::TensorView>> inputs;
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "ngraph/function.hpp" #include "ngraph/function.hpp"
#include "ngraph/runtime/call_frame.hpp" #include "ngraph/runtime/call_frame.hpp"
#include "ngraph/runtime/parameterized_tensor_view.hpp"
#include "ngraph/runtime/tensor_view.hpp" #include "ngraph/runtime/tensor_view.hpp"
namespace ngraph namespace ngraph
...@@ -46,9 +47,8 @@ namespace ngraph ...@@ -46,9 +47,8 @@ namespace ngraph
/// @brief Invoke the function with values matching the signature of the function. /// @brief Invoke the function with values matching the signature of the function.
/// ///
/// Tuples will be expanded into their tensor views to build the call frame. /// Tuples will be expanded into their tensor views to build the call frame.
void void call(const std::vector<std::shared_ptr<ngraph::runtime::Value>>& inputs,
operator()(const std::vector<std::shared_ptr<ngraph::runtime::Value>>& inputs, const std::vector<std::shared_ptr<ngraph::runtime::Value>>& outputs);
const std::vector<std::shared_ptr<ngraph::runtime::Value>>& outputs);
/// @brief Invoke the function with tuples pre-expanded to their underlying tensor views. /// @brief Invoke the function with tuples pre-expanded to their underlying tensor views.
void tensor_call(const TensorViewPtrs& inputs, const TensorViewPtrs& outputs); void tensor_call(const TensorViewPtrs& inputs, const TensorViewPtrs& outputs);
......
...@@ -58,7 +58,7 @@ namespace ngraph ...@@ -58,7 +58,7 @@ namespace ngraph
{ {
outputs.push_back(call_frame.get_tensor_view(out.get_index())); outputs.push_back(call_frame.get_tensor_view(out.get_index()));
} }
(*cf)(inputs, outputs); cf->call(inputs, outputs);
} }
protected: protected:
......
// ----------------------------------------------------------------------------
// Copyright 2017 Nervana Systems Inc.
// 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
// ----------------------------------------------------------------------------
#pragma once
#include "ngraph/runtime/ngvm/call_frame.hpp"
#include "ngraph/runtime/ngvm/eigen/utils.hpp"
#include "ngraph/runtime/ngvm/instruction.hpp"
#include "ngraph/runtime/tensor_view.hpp"
namespace ngraph
{
namespace runtime
{
namespace ngvm
{
namespace eigen
{
template <typename ET>
class PowerInstruction : public Instruction
{
public:
PowerInstruction(const TensorViewInfo& arg0,
const TensorViewInfo& arg1,
const TensorViewInfo& out)
: m_arg0(arg0)
, m_arg1(arg1)
, m_out(out)
{
}
virtual void execute(CallFrame& call_frame) const override
{
EigenArray1d<ET>(call_frame, m_out) =
EigenArray1d<ET>(call_frame, m_arg0)
.pow(EigenArray1d<ET>(call_frame, m_arg1));
}
protected:
TensorViewInfo m_arg0;
TensorViewInfo m_arg1;
TensorViewInfo m_out;
};
}
}
}
}
...@@ -55,7 +55,7 @@ namespace ngraph ...@@ -55,7 +55,7 @@ namespace ngraph
auto ty = ngraph::runtime::make_tensor<ET>(Shape{}, {y}); auto ty = ngraph::runtime::make_tensor<ET>(Shape{}, {y});
auto tr = ngraph::runtime::make_tensor<ET>(Shape{}); auto tr = ngraph::runtime::make_tensor<ET>(Shape{});
(*cf)({tx, ty}, {tr}); cf->call({tx, ty}, {tr});
return tr->get_vector()[0]; return tr->get_vector()[0];
}; };
EigenVector<ET>(call_frame, m_out) = EigenVector<ET>(call_frame, m_out) =
......
...@@ -55,7 +55,7 @@ namespace ngraph ...@@ -55,7 +55,7 @@ namespace ngraph
auto ty = ngraph::runtime::make_tensor<ET>(Shape{}, {y}); auto ty = ngraph::runtime::make_tensor<ET>(Shape{}, {y});
auto tr = ngraph::runtime::make_tensor<ET>(Shape{}); auto tr = ngraph::runtime::make_tensor<ET>(Shape{});
(*cf)({tx, ty}, {tr}); cf->call({tx, ty}, {tr});
return tr->get_vector()[0]; return tr->get_vector()[0];
}; };
EigenVector<ET>(call_frame, m_out) = EigenVector<ET>(call_frame, m_out) =
......
...@@ -55,7 +55,7 @@ namespace ngraph ...@@ -55,7 +55,7 @@ namespace ngraph
auto ty = ngraph::runtime::make_tensor<ET>(Shape{}, {y}); auto ty = ngraph::runtime::make_tensor<ET>(Shape{}, {y});
auto tr = ngraph::runtime::make_tensor<ET>(Shape{}); auto tr = ngraph::runtime::make_tensor<ET>(Shape{});
(*cf)({tx, ty}, {tr}); cf->call({tx, ty}, {tr});
return tr->get_vector()[0]; return tr->get_vector()[0];
}; };
EigenArray1d<ET>(call_frame, m_out) = EigenArray1d<ET>(call_frame, m_out) =
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include "ngraph/ops/multiply.hpp" #include "ngraph/ops/multiply.hpp"
#include "ngraph/ops/negative.hpp" #include "ngraph/ops/negative.hpp"
#include "ngraph/ops/not_equal.hpp" #include "ngraph/ops/not_equal.hpp"
#include "ngraph/ops/power.hpp"
#include "ngraph/ops/reduce.hpp" #include "ngraph/ops/reduce.hpp"
#include "ngraph/ops/reshape.hpp" #include "ngraph/ops/reshape.hpp"
#include "ngraph/ops/select.hpp" #include "ngraph/ops/select.hpp"
...@@ -98,6 +99,7 @@ ...@@ -98,6 +99,7 @@
#include "ngraph/runtime/ngvm/eigen/multiply.hpp" #include "ngraph/runtime/ngvm/eigen/multiply.hpp"
#include "ngraph/runtime/ngvm/eigen/negate.hpp" #include "ngraph/runtime/ngvm/eigen/negate.hpp"
#include "ngraph/runtime/ngvm/eigen/not_equal.hpp" #include "ngraph/runtime/ngvm/eigen/not_equal.hpp"
#include "ngraph/runtime/ngvm/eigen/power.hpp"
#include "ngraph/runtime/ngvm/eigen/reduce_matrix_columns.hpp" #include "ngraph/runtime/ngvm/eigen/reduce_matrix_columns.hpp"
#include "ngraph/runtime/ngvm/eigen/reduce_matrix_rows.hpp" #include "ngraph/runtime/ngvm/eigen/reduce_matrix_rows.hpp"
#include "ngraph/runtime/ngvm/eigen/reduce_to_scalar.hpp" #include "ngraph/runtime/ngvm/eigen/reduce_to_scalar.hpp"
...@@ -380,6 +382,7 @@ ExternalFunction::OpMap& ExternalFunction::get_op_map() ...@@ -380,6 +382,7 @@ ExternalFunction::OpMap& ExternalFunction::get_op_map()
REGISTER_NUMERIC_BINOP(op::Maximum, eigen::MaximumInstruction); REGISTER_NUMERIC_BINOP(op::Maximum, eigen::MaximumInstruction);
REGISTER_NUMERIC_BINOP(op::Minimum, eigen::MinimumInstruction); REGISTER_NUMERIC_BINOP(op::Minimum, eigen::MinimumInstruction);
REGISTER_NUMERIC_BINOP(op::Multiply, eigen::MultiplyInstruction); REGISTER_NUMERIC_BINOP(op::Multiply, eigen::MultiplyInstruction);
REGISTER_NUMERIC_BINOP(op::Power, eigen::PowerInstruction);
REGISTER_NUMERIC_BINOP(op::Subtract, eigen::SubtractInstruction); REGISTER_NUMERIC_BINOP(op::Subtract, eigen::SubtractInstruction);
REGISTER_TO_OP_MAP(op::Constant) REGISTER_TO_OP_MAP(op::Constant)
......
...@@ -25,9 +25,11 @@ const element::Type element::boolean(8, false, false, "bool"); ...@@ -25,9 +25,11 @@ const element::Type element::boolean(8, false, false, "bool");
const element::Type element::f32(32, true, true, "float"); const element::Type element::f32(32, true, true, "float");
const element::Type element::f64(64, true, true, "double"); const element::Type element::f64(64, true, true, "double");
const element::Type element::i8(8, false, true, "int8_t"); const element::Type element::i8(8, false, true, "int8_t");
const element::Type element::i16(16, false, true, "int16_t");
const element::Type element::i32(32, false, true, "int32_t"); const element::Type element::i32(32, false, true, "int32_t");
const element::Type element::i64(64, false, true, "int64_t"); const element::Type element::i64(64, false, true, "int64_t");
const element::Type element::u8(8, false, false, "uint8_t"); const element::Type element::u8(8, false, false, "uint8_t");
const element::Type element::u16(16, false, false, "uint16_t");
const element::Type element::u32(32, false, false, "uint32_t"); const element::Type element::u32(32, false, false, "uint32_t");
const element::Type element::u64(64, false, false, "uint64_t"); const element::Type element::u64(64, false, false, "uint64_t");
......
...@@ -29,14 +29,22 @@ ...@@ -29,14 +29,22 @@
namespace ngraph namespace ngraph
{ {
namespace runtime
{
template <typename ET>
class ParameterizedTensorView;
}
namespace element namespace element
{ {
class Type;
extern const Type boolean;
extern const Type f32;
extern const Type f64;
extern const Type i8;
extern const Type i16;
extern const Type i32;
extern const Type i64;
extern const Type u8;
extern const Type u16;
extern const Type u32;
extern const Type u64;
class Type class Type
{ {
Type(const Type&) = delete; Type(const Type&) = delete;
...@@ -66,15 +74,58 @@ namespace ngraph ...@@ -66,15 +74,58 @@ namespace ngraph
const std::string m_cname; const std::string m_cname;
}; };
extern const Type boolean; template <typename T>
extern const Type f32; const Type& from()
extern const Type f64; {
extern const Type i8; if (typeid(T) == typeid(char) || typeid(T) == typeid(bool))
extern const Type i32; {
extern const Type i64; return boolean;
extern const Type u8; }
extern const Type u32; else if (typeid(T) == typeid(float))
extern const Type u64; {
return f32;
}
else if (typeid(T) == typeid(double))
{
return f64;
}
else if (typeid(T) == typeid(int8_t))
{
return i8;
}
else if (typeid(T) == typeid(int16_t))
{
return i16;
}
else if (typeid(T) == typeid(int32_t))
{
return i32;
}
else if (typeid(T) == typeid(int64_t))
{
return i64;
}
else if (typeid(T) == typeid(uint8_t))
{
return u8;
}
else if (typeid(T) == typeid(uint16_t))
{
return u16;
}
else if (typeid(T) == typeid(uint32_t))
{
return u32;
}
else if (typeid(T) == typeid(uint64_t))
{
return u64;
}
else
{
throw std::invalid_argument("Unknown type");
}
}
std::ostream& operator<<(std::ostream& out, const ngraph::element::Type& obj); std::ostream& operator<<(std::ostream& out, const ngraph::element::Type& obj);
......
...@@ -23,9 +23,10 @@ include_directories( ...@@ -23,9 +23,10 @@ include_directories(
set (SRC set (SRC
autodiff.cpp autodiff.cpp
copy.cpp
build_graph.cpp build_graph.cpp
copy.cpp
eigen.cpp eigen.cpp
element_type.cpp
file_util.cpp file_util.cpp
input_output_assign.cpp input_output_assign.cpp
main.cpp main.cpp
...@@ -33,6 +34,7 @@ set (SRC ...@@ -33,6 +34,7 @@ set (SRC
pass_liveness.cpp pass_liveness.cpp
pass_manager.cpp pass_manager.cpp
pass_memory_layout.cpp pass_memory_layout.cpp
serialize.cpp
shape.cpp shape.cpp
tensor.cpp tensor.cpp
topological_sort.cpp topological_sort.cpp
......
This diff is collapsed.
This diff is collapsed.
...@@ -39,7 +39,6 @@ bool check_unary() ...@@ -39,7 +39,6 @@ bool check_unary()
auto node = make_shared<OP>(arg0); auto node = make_shared<OP>(arg0);
auto new_node = node->copy_with_new_args(new_args); auto new_node = node->copy_with_new_args(new_args);
auto node_cast = dynamic_pointer_cast<OP>(new_node);
return (nullptr != new_node) && (new_args == new_node->get_arguments()); return (nullptr != new_node) && (new_args == new_node->get_arguments());
} }
...@@ -56,7 +55,6 @@ bool check_binary() ...@@ -56,7 +55,6 @@ bool check_binary()
auto node = make_shared<OP>(arg0, arg1); auto node = make_shared<OP>(arg0, arg1);
auto new_node = node->copy_with_new_args(new_args); auto new_node = node->copy_with_new_args(new_args);
auto node_cast = dynamic_pointer_cast<OP>(new_node);
return (nullptr != new_node) && (new_args == new_node->get_arguments()); return (nullptr != new_node) && (new_args == new_node->get_arguments());
} }
...@@ -99,6 +97,7 @@ TEST(copy, broadcast) ...@@ -99,6 +97,7 @@ TEST(copy, broadcast)
auto node = make_shared<op::Broadcast>(arg0, shape, axes); auto node = make_shared<op::Broadcast>(arg0, shape, axes);
auto new_node = node->copy_with_new_args(new_args); auto new_node = node->copy_with_new_args(new_args);
auto node_cast = dynamic_pointer_cast<op::Broadcast>(new_node); auto node_cast = dynamic_pointer_cast<op::Broadcast>(new_node);
ASSERT_NE(node_cast, nullptr);
ASSERT_TRUE(nullptr != new_node); ASSERT_TRUE(nullptr != new_node);
ASSERT_TRUE(new_args == new_node->get_arguments()); ASSERT_TRUE(new_args == new_node->get_arguments());
...@@ -123,6 +122,7 @@ TEST(copy, concat) ...@@ -123,6 +122,7 @@ TEST(copy, concat)
auto node = make_shared<op::Concat>(Nodes{arg0, arg1}, axis); auto node = make_shared<op::Concat>(Nodes{arg0, arg1}, axis);
auto new_node = node->copy_with_new_args(new_args); auto new_node = node->copy_with_new_args(new_args);
auto node_cast = dynamic_pointer_cast<op::Concat>(new_node); auto node_cast = dynamic_pointer_cast<op::Concat>(new_node);
ASSERT_NE(node_cast, nullptr);
ASSERT_TRUE(nullptr != new_node); ASSERT_TRUE(nullptr != new_node);
ASSERT_TRUE(new_args == new_node->get_arguments()); ASSERT_TRUE(new_args == new_node->get_arguments());
...@@ -140,9 +140,11 @@ TEST(copy, parameterized_constant) ...@@ -140,9 +140,11 @@ TEST(copy, parameterized_constant)
Shape shape{2, 2}; Shape shape{2, 2};
auto cptv = dynamic_pointer_cast<ngraph::runtime::ParameterizedTensorView<element::Float32>>(c); auto cptv = dynamic_pointer_cast<ngraph::runtime::ParameterizedTensorView<element::Float32>>(c);
ASSERT_NE(cptv, nullptr);
auto node = make_shared<op::ParameterizedConstant<element::Float32>>(shape, cptv); auto node = make_shared<op::ParameterizedConstant<element::Float32>>(shape, cptv);
auto new_node = node->copy_with_new_args(Nodes{}); auto new_node = node->copy_with_new_args(Nodes{});
auto node_cast = dynamic_pointer_cast<op::ParameterizedConstant<element::Float32>>(new_node); auto node_cast = dynamic_pointer_cast<op::ParameterizedConstant<element::Float32>>(new_node);
ASSERT_NE(node_cast, nullptr);
ASSERT_TRUE(nullptr != new_node); ASSERT_TRUE(nullptr != new_node);
ASSERT_TRUE(Nodes{} == new_node->get_arguments()); ASSERT_TRUE(Nodes{} == new_node->get_arguments());
ASSERT_TRUE(node_cast->get_value() == c); ASSERT_TRUE(node_cast->get_value() == c);
...@@ -157,6 +159,7 @@ TEST(copy, constant) ...@@ -157,6 +159,7 @@ TEST(copy, constant)
auto node = make_shared<op::Constant>(et, shape, c); auto node = make_shared<op::Constant>(et, shape, c);
auto new_node = node->copy_with_new_args(Nodes{}); auto new_node = node->copy_with_new_args(Nodes{});
auto node_cast = dynamic_pointer_cast<op::Constant>(new_node); auto node_cast = dynamic_pointer_cast<op::Constant>(new_node);
ASSERT_NE(node_cast, nullptr);
ASSERT_TRUE(nullptr != new_node); ASSERT_TRUE(nullptr != new_node);
ASSERT_TRUE(Nodes{} == new_node->get_arguments()); ASSERT_TRUE(Nodes{} == new_node->get_arguments());
ASSERT_TRUE(node_cast->get_value_strings() == c); ASSERT_TRUE(node_cast->get_value_strings() == c);
...@@ -175,6 +178,7 @@ TEST(copy, convert) ...@@ -175,6 +178,7 @@ TEST(copy, convert)
auto node = make_shared<op::Convert>(arg0, et); auto node = make_shared<op::Convert>(arg0, et);
auto new_node = node->copy_with_new_args(new_args); auto new_node = node->copy_with_new_args(new_args);
auto node_cast = dynamic_pointer_cast<op::Convert>(new_node); auto node_cast = dynamic_pointer_cast<op::Convert>(new_node);
ASSERT_NE(node_cast, nullptr);
ASSERT_TRUE(nullptr != new_node); ASSERT_TRUE(nullptr != new_node);
ASSERT_TRUE(new_args == new_node->get_arguments()); ASSERT_TRUE(new_args == new_node->get_arguments());
...@@ -236,6 +240,7 @@ TEST(copy, FunctionCall) ...@@ -236,6 +240,7 @@ TEST(copy, FunctionCall)
make_shared<op::Parameter>(element::Float32::element_type(), shape)}; make_shared<op::Parameter>(element::Float32::element_type(), shape)};
auto new_node = node->copy_with_new_args(new_args); auto new_node = node->copy_with_new_args(new_args);
auto node_cast = dynamic_pointer_cast<op::FunctionCall>(new_node); auto node_cast = dynamic_pointer_cast<op::FunctionCall>(new_node);
ASSERT_NE(node_cast, nullptr);
ASSERT_TRUE(nullptr != new_node); ASSERT_TRUE(nullptr != new_node);
ASSERT_TRUE(new_args == new_node->get_arguments()); ASSERT_TRUE(new_args == new_node->get_arguments());
...@@ -255,6 +260,7 @@ TEST(copy, GetTupleElement) ...@@ -255,6 +260,7 @@ TEST(copy, GetTupleElement)
auto node = make_shared<op::GetTupleElement>(arg0, n); auto node = make_shared<op::GetTupleElement>(arg0, n);
auto new_node = node->copy_with_new_args(new_args); auto new_node = node->copy_with_new_args(new_args);
auto node_cast = dynamic_pointer_cast<op::GetTupleElement>(new_node); auto node_cast = dynamic_pointer_cast<op::GetTupleElement>(new_node);
ASSERT_NE(node_cast, nullptr);
ASSERT_TRUE(nullptr != new_node); ASSERT_TRUE(nullptr != new_node);
ASSERT_TRUE(new_args == new_node->get_arguments()); ASSERT_TRUE(new_args == new_node->get_arguments());
...@@ -317,6 +323,7 @@ TEST(copy, parameter) ...@@ -317,6 +323,7 @@ TEST(copy, parameter)
auto node = make_shared<op::Parameter>(element::Float32::element_type(), shape); auto node = make_shared<op::Parameter>(element::Float32::element_type(), shape);
auto new_node = node->copy_with_new_args({}); auto new_node = node->copy_with_new_args({});
auto node_cast = dynamic_pointer_cast<op::Parameter>(new_node); auto node_cast = dynamic_pointer_cast<op::Parameter>(new_node);
ASSERT_NE(node_cast, nullptr);
ASSERT_TRUE(nullptr != new_node); ASSERT_TRUE(nullptr != new_node);
ASSERT_TRUE(new_node->get_arguments().size() == 0); ASSERT_TRUE(new_node->get_arguments().size() == 0);
...@@ -347,6 +354,7 @@ TEST(copy, reduce) ...@@ -347,6 +354,7 @@ TEST(copy, reduce)
auto node = make_shared<op::Reduce>(arg0, arg_init, f, axes); auto node = make_shared<op::Reduce>(arg0, arg_init, f, axes);
auto new_node = node->copy_with_new_args(new_args); auto new_node = node->copy_with_new_args(new_args);
auto node_cast = dynamic_pointer_cast<op::Reduce>(new_node); auto node_cast = dynamic_pointer_cast<op::Reduce>(new_node);
ASSERT_NE(node_cast, nullptr);
ASSERT_TRUE(nullptr != new_node); ASSERT_TRUE(nullptr != new_node);
ASSERT_TRUE(new_args == new_node->get_arguments()); ASSERT_TRUE(new_args == new_node->get_arguments());
...@@ -372,6 +380,7 @@ TEST(copy, reshape) ...@@ -372,6 +380,7 @@ TEST(copy, reshape)
auto node = make_shared<op::Reshape>(arg0, axes, shape_out); auto node = make_shared<op::Reshape>(arg0, axes, shape_out);
auto new_node = node->copy_with_new_args(new_args); auto new_node = node->copy_with_new_args(new_args);
auto node_cast = dynamic_pointer_cast<op::Reshape>(new_node); auto node_cast = dynamic_pointer_cast<op::Reshape>(new_node);
ASSERT_NE(node_cast, nullptr);
ASSERT_TRUE(nullptr != new_node); ASSERT_TRUE(nullptr != new_node);
ASSERT_TRUE(new_args == new_node->get_arguments()); ASSERT_TRUE(new_args == new_node->get_arguments());
...@@ -393,6 +402,7 @@ TEST(copy, select) ...@@ -393,6 +402,7 @@ TEST(copy, select)
auto node = make_shared<op::Select>(arg0, arg1, arg2); auto node = make_shared<op::Select>(arg0, arg1, arg2);
auto new_node = node->copy_with_new_args(new_args); auto new_node = node->copy_with_new_args(new_args);
auto node_cast = dynamic_pointer_cast<op::Select>(new_node); auto node_cast = dynamic_pointer_cast<op::Select>(new_node);
ASSERT_NE(node_cast, nullptr);
ASSERT_TRUE(nullptr != new_node); ASSERT_TRUE(nullptr != new_node);
ASSERT_TRUE(new_args == new_node->get_arguments()); ASSERT_TRUE(new_args == new_node->get_arguments());
...@@ -427,6 +437,7 @@ TEST(copy, slice) ...@@ -427,6 +437,7 @@ TEST(copy, slice)
auto node = make_shared<op::Slice>(arg0, lower, upper, step); auto node = make_shared<op::Slice>(arg0, lower, upper, step);
auto new_node = node->copy_with_new_args(new_args); auto new_node = node->copy_with_new_args(new_args);
auto node_cast = dynamic_pointer_cast<op::Slice>(new_node); auto node_cast = dynamic_pointer_cast<op::Slice>(new_node);
ASSERT_NE(node_cast, nullptr);
ASSERT_TRUE(nullptr != new_node); ASSERT_TRUE(nullptr != new_node);
ASSERT_TRUE(new_args == new_node->get_arguments()); ASSERT_TRUE(new_args == new_node->get_arguments());
...@@ -451,6 +462,7 @@ TEST(copy, sum) ...@@ -451,6 +462,7 @@ TEST(copy, sum)
auto node = make_shared<op::Sum>(arg0, axes); auto node = make_shared<op::Sum>(arg0, axes);
auto new_node = node->copy_with_new_args(new_args); auto new_node = node->copy_with_new_args(new_args);
auto node_cast = dynamic_pointer_cast<op::Sum>(new_node); auto node_cast = dynamic_pointer_cast<op::Sum>(new_node);
ASSERT_NE(node_cast, nullptr);
ASSERT_TRUE(nullptr != new_node); ASSERT_TRUE(nullptr != new_node);
ASSERT_TRUE(new_args == new_node->get_arguments()); ASSERT_TRUE(new_args == new_node->get_arguments());
...@@ -479,6 +491,7 @@ TEST(copy, tuple) ...@@ -479,6 +491,7 @@ TEST(copy, tuple)
auto node = make_shared<op::Tuple>(Nodes{arg0, arg1}); auto node = make_shared<op::Tuple>(Nodes{arg0, arg1});
auto new_node = node->copy_with_new_args(new_args); auto new_node = node->copy_with_new_args(new_args);
auto node_cast = dynamic_pointer_cast<op::Tuple>(new_node); auto node_cast = dynamic_pointer_cast<op::Tuple>(new_node);
ASSERT_NE(node_cast, nullptr);
ASSERT_TRUE(nullptr != new_node); ASSERT_TRUE(nullptr != new_node);
ASSERT_TRUE(new_args == new_node->get_arguments()); ASSERT_TRUE(new_args == new_node->get_arguments());
......
// ----------------------------------------------------------------------------
// Copyright 2017 Nervana Systems Inc.
// 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
// ----------------------------------------------------------------------------
#include "gtest/gtest.h"
#include "ngraph/types/element_type.hpp"
using namespace ngraph;
TEST(element_type, from)
{
EXPECT_EQ(element::from<char>(), element::boolean);
EXPECT_EQ(element::from<bool>(), element::boolean);
EXPECT_EQ(element::from<float>(), element::f32);
EXPECT_EQ(element::from<double>(), element::f64);
EXPECT_EQ(element::from<int8_t>(), element::i8);
EXPECT_EQ(element::from<int16_t>(), element::i16);
EXPECT_EQ(element::from<int32_t>(), element::i32);
EXPECT_EQ(element::from<int64_t>(), element::i64);
EXPECT_EQ(element::from<uint8_t>(), element::u8);
EXPECT_EQ(element::from<uint16_t>(), element::u16);
EXPECT_EQ(element::from<uint32_t>(), element::u32);
EXPECT_EQ(element::from<uint64_t>(), element::u64);
}
...@@ -215,7 +215,7 @@ TEST(memory_layout, basic) ...@@ -215,7 +215,7 @@ TEST(memory_layout, basic)
auto graph = make_test_graph(); auto graph = make_test_graph();
pass_manager.run_passes(graph); pass_manager.run_passes(graph);
auto sorted = graph->get_ordered_ops(); auto sorted = graph->get_ordered_ops();
size_t temporary_pool_size = pass_manager.get_state().get_temporary_pool_size(); size_t temporary_pool_size = graph->get_temporary_pool_size();
EXPECT_EQ(12, temporary_pool_size); EXPECT_EQ(12, temporary_pool_size);
} }
...@@ -235,6 +235,6 @@ TEST(memory_layout, constant) ...@@ -235,6 +235,6 @@ TEST(memory_layout, constant)
pass_manager.run_passes(f); pass_manager.run_passes(f);
auto sorted = f->get_ordered_ops(); auto sorted = f->get_ordered_ops();
size_t temporary_pool_size = pass_manager.get_state().get_temporary_pool_size(); size_t temporary_pool_size = f->get_temporary_pool_size();
EXPECT_EQ(0, temporary_pool_size); EXPECT_EQ(0, temporary_pool_size);
} }
// ----------------------------------------------------------------------------
// Copyright 2017 Nervana Systems Inc.
// 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
// ----------------------------------------------------------------------------
#include "gtest/gtest.h"
...@@ -185,20 +185,20 @@ TEST(util, all_close) ...@@ -185,20 +185,20 @@ TEST(util, all_close)
auto backend = manager->allocate_backend(); auto backend = manager->allocate_backend();
// Create some tensors for input/output // Create some tensors for input/output
auto a = backend->make_parameterized_tensor_view<element::Float32>(Shape{2, 3}); auto a = backend->make_primary_tensor_view(element::Float32::element_type(), Shape{2, 3});
auto b = backend->make_parameterized_tensor_view<element::Float32>(Shape{2, 3}); auto b = backend->make_primary_tensor_view(element::Float32::element_type(), Shape{2, 3});
copy_data(a, runtime::NDArray<float, 2>({{1, 2, 3}, {3, 4, 5}}).get_vector()); copy_data(a, runtime::NDArray<float, 2>({{1, 2, 3}, {3, 4, 5}}).get_vector());
copy_data(b, runtime::NDArray<float, 2>({{1, 2, 3}, {3, 4, 5}}).get_vector()); copy_data(b, runtime::NDArray<float, 2>({{1, 2, 3}, {3, 4, 5}}).get_vector());
EXPECT_TRUE(ngraph::test::all_close(a, b)); EXPECT_TRUE(ngraph::test::all_close<float>(a, b));
auto c = backend->make_parameterized_tensor_view<element::Float32>(Shape{2, 3}); auto c = backend->make_primary_tensor_view(element::Float32::element_type(), Shape{2, 3});
copy_data(c, runtime::NDArray<float, 2>({{1.1f, 2, 3}, {3, 4, 5}}).get_vector()); copy_data(c, runtime::NDArray<float, 2>({{1.1f, 2, 3}, {3, 4, 5}}).get_vector());
EXPECT_FALSE(ngraph::test::all_close(c, a, 0, .05f)); EXPECT_FALSE(ngraph::test::all_close<float>(c, a, 0, .05f));
EXPECT_TRUE(ngraph::test::all_close(c, a, 0, .11f)); EXPECT_TRUE(ngraph::test::all_close<float>(c, a, 0, .11f));
EXPECT_FALSE(ngraph::test::all_close(c, a, .05f, 0)); EXPECT_FALSE(ngraph::test::all_close<float>(c, a, .05f, 0));
EXPECT_TRUE(ngraph::test::all_close(c, a, .11f, 0)); EXPECT_TRUE(ngraph::test::all_close<float>(c, a, .11f, 0));
} }
...@@ -54,11 +54,11 @@ namespace ngraph ...@@ -54,11 +54,11 @@ namespace ngraph
/// @param rtol Relative tolerance /// @param rtol Relative tolerance
/// @param atol Absolute tolerance /// @param atol Absolute tolerance
/// Returns true if shapes match and for all elements, |a_i-b_i| <= atol + rtol*|b_i|. /// Returns true if shapes match and for all elements, |a_i-b_i| <= atol + rtol*|b_i|.
template <typename ET> template <typename T>
bool all_close(const std::shared_ptr<ngraph::runtime::ParameterizedTensorView<ET>>& a, bool all_close(const std::shared_ptr<ngraph::runtime::TensorView>& a,
const std::shared_ptr<ngraph::runtime::ParameterizedTensorView<ET>>& b, const std::shared_ptr<ngraph::runtime::TensorView>& b,
typename ET::type rtol = 1e-5f, T rtol = 1e-5f,
typename ET::type atol = 1e-8f) T atol = 1e-8f)
{ {
// Check that the layouts are compatible // Check that the layouts are compatible
if (*a->get_tensor_view_layout() != *b->get_tensor_view_layout()) if (*a->get_tensor_view_layout() != *b->get_tensor_view_layout())
...@@ -69,7 +69,7 @@ namespace ngraph ...@@ -69,7 +69,7 @@ namespace ngraph
if (a->get_shape() != b->get_shape()) if (a->get_shape() != b->get_shape())
return false; return false;
return all_close(a->get_vector(), b->get_vector(), rtol, atol); return all_close(a->get_vector<T>(), b->get_vector<T>(), rtol, atol);
} }
/// @brief Same as numpy.allclose /// @brief Same as numpy.allclose
...@@ -78,12 +78,11 @@ namespace ngraph ...@@ -78,12 +78,11 @@ namespace ngraph
/// @param rtol Relative tolerance /// @param rtol Relative tolerance
/// @param atol Absolute tolerance /// @param atol Absolute tolerance
/// Returns true if shapes match and for all elements, |a_i-b_i| <= atol + rtol*|b_i|. /// Returns true if shapes match and for all elements, |a_i-b_i| <= atol + rtol*|b_i|.
template <typename ET> template <typename T>
bool all_close( bool all_close(const std::vector<std::shared_ptr<ngraph::runtime::TensorView>>& as,
const std::vector<std::shared_ptr<ngraph::runtime::ParameterizedTensorView<ET>>>& as, const std::vector<std::shared_ptr<ngraph::runtime::TensorView>>& bs,
const std::vector<std::shared_ptr<ngraph::runtime::ParameterizedTensorView<ET>>>& bs, T rtol,
typename ET::type rtol, T atol)
typename ET::type atol)
{ {
if (as.size() != bs.size()) if (as.size() != bs.size())
{ {
......
...@@ -39,24 +39,24 @@ namespace ngraph ...@@ -39,24 +39,24 @@ namespace ngraph
/// @returns f'(X_i..., c) where f'(x_i, ..., c)_j is backprop for X_j /// @returns f'(X_i..., c) where f'(x_i, ..., c)_j is backprop for X_j
std::shared_ptr<Function> backprop_function(const std::shared_ptr<Function>& f); std::shared_ptr<Function> backprop_function(const std::shared_ptr<Function>& f);
template <typename ET> template <typename T>
std::vector<std::shared_ptr<runtime::ParameterizedTensorView<ET>>> backprop_derivative( std::vector<std::shared_ptr<runtime::TensorView>>
const std::shared_ptr<runtime::Manager>& manager, backprop_derivative(const std::shared_ptr<runtime::Manager>& manager,
const std::shared_ptr<runtime::Backend>& backend, const std::shared_ptr<runtime::Backend>& backend,
const std::shared_ptr<Function>& f, const std::shared_ptr<Function>& f,
const std::vector<std::shared_ptr<runtime::ParameterizedTensorView<ET>>>& args) const std::vector<std::shared_ptr<runtime::TensorView>>& args)
{ {
auto y = f->get_result(); auto y = f->get_result();
Shape y_shape = Shape y_shape =
std::dynamic_pointer_cast<const TensorViewType>(y->get_value_type())->get_shape(); std::dynamic_pointer_cast<const TensorViewType>(y->get_value_type())->get_shape();
auto c_param = std::make_shared<op::Parameter>(ET::element_type(), y_shape); auto c_param = std::make_shared<op::Parameter>(element::from<T>(), y_shape);
auto c_arg = backend->make_parameterized_tensor_view<ET>(y_shape); auto c_arg = backend->make_primary_tensor_view<T>(y_shape);
auto params = f->get_parameters(); auto params = f->get_parameters();
std::vector<std::shared_ptr<Node>> deriv_nodes; std::vector<std::shared_ptr<Node>> deriv_nodes;
std::vector<std::shared_ptr<runtime::ParameterizedTensorView<ET>>> bprops; std::vector<std::shared_ptr<runtime::TensorView>> bprops;
std::vector<std::shared_ptr<runtime::ParameterizedTensorView<ET>>> results; std::vector<std::shared_ptr<runtime::TensorView>> results;
for (auto param : params) for (auto param : params)
{ {
Shape s = y_shape; Shape s = y_shape;
...@@ -64,8 +64,8 @@ namespace ngraph ...@@ -64,8 +64,8 @@ namespace ngraph
std::dynamic_pointer_cast<const TensorViewType>(param->get_value_type()) std::dynamic_pointer_cast<const TensorViewType>(param->get_value_type())
->get_shape(); ->get_shape();
s.insert(s.end(), param_shape.begin(), param_shape.end()); s.insert(s.end(), param_shape.begin(), param_shape.end());
results.push_back(backend->make_parameterized_tensor_view<ET>(s)); results.push_back(backend->make_primary_tensor_view<T>(s));
bprops.push_back(backend->make_parameterized_tensor_view<ET>(param_shape)); bprops.push_back(backend->make_primary_tensor_view<T>(param_shape));
deriv_nodes.push_back(y->backprop_node(param, c_param)); deriv_nodes.push_back(y->backprop_node(param, c_param));
} }
...@@ -78,22 +78,22 @@ namespace ngraph ...@@ -78,22 +78,22 @@ namespace ngraph
auto cf = backend->make_call_frame(external); auto cf = backend->make_call_frame(external);
// We compute the derivatives chunk by chunk // We compute the derivatives chunk by chunk
std::vector<typename std::vector<typename ET::type>::iterator> result_pos; std::vector<typename std::vector<T>::iterator> result_pos;
std::vector<std::vector<typename ET::type>> result_vect; std::vector<std::vector<T>> result_vect;
for (auto result : results) for (auto result : results)
{ {
result_vect.push_back(result->get_vector()); // storage for results result_vect.push_back(result->get_vector<T>()); // storage for results
result_pos.push_back(result_vect.back().begin()); result_pos.push_back(result_vect.back().begin());
} }
ngraph::runtime::TensorViewPtrs args_tv; std::vector<std::shared_ptr<ngraph::runtime::TensorView>> args_tv;
args_tv.insert(args_tv.begin(), args.begin(), args.end()); args_tv.insert(args_tv.begin(), args.begin(), args.end());
args_tv.push_back(c_arg); args_tv.push_back(c_arg);
runtime::TensorViewPtrs bprops_tv; std::vector<std::shared_ptr<ngraph::runtime::TensorView>> bprops_tv;
bprops_tv.insert(bprops_tv.begin(), bprops.begin(), bprops.end()); bprops_tv.insert(bprops_tv.begin(), bprops.begin(), bprops.end());
auto c_vec = c_arg->get_vector(); auto c_vec = c_arg->template get_vector<T>();
for (size_t i = 0; i < c_vec.size(); i++) for (size_t i = 0; i < c_vec.size(); i++)
{ {
c_vec[i] = 1; c_vec[i] = 1;
...@@ -103,7 +103,7 @@ namespace ngraph ...@@ -103,7 +103,7 @@ namespace ngraph
c_arg->write(c_vec); c_arg->write(c_vec);
for (size_t j = 0; j < results.size(); j++) for (size_t j = 0; j < results.size(); j++)
{ {
auto bprop_vec = bprops[j]->get_vector(); auto bprop_vec = bprops[j]->get_vector<T>();
result_pos[j] = std::copy(bprop_vec.begin(), bprop_vec.end(), result_pos[j]); result_pos[j] = std::copy(bprop_vec.begin(), bprop_vec.end(), result_pos[j]);
} }
} }
......
...@@ -33,13 +33,13 @@ namespace ngraph ...@@ -33,13 +33,13 @@ namespace ngraph
/// @param args Values for the arguments (the independent variables) /// @param args Values for the arguments (the independent variables)
/// @param delta increment for the variables /// @param delta increment for the variables
/// @returns vector of dy/dvar, where each dy/dvar's shape is concat(y.shape(), var.shape()) /// @returns vector of dy/dvar, where each dy/dvar's shape is concat(y.shape(), var.shape())
template <typename ET> template <typename T>
std::vector<std::shared_ptr<runtime::ParameterizedTensorView<ET>>> numeric_derivative( std::vector<std::shared_ptr<runtime::TensorView>>
const std::shared_ptr<runtime::Manager>& manager, numeric_derivative(const std::shared_ptr<runtime::Manager>& manager,
const std::shared_ptr<runtime::Backend>& backend, const std::shared_ptr<runtime::Backend>& backend,
const std::shared_ptr<Function>& f, const std::shared_ptr<Function>& f,
const std::vector<std::shared_ptr<runtime::ParameterizedTensorView<ET>>>& args, const std::vector<std::shared_ptr<runtime::TensorView>>& args,
typename ET::type delta) T delta)
{ {
auto y = f->get_result(); auto y = f->get_result();
...@@ -49,7 +49,7 @@ namespace ngraph ...@@ -49,7 +49,7 @@ namespace ngraph
auto params = f->get_parameters(); auto params = f->get_parameters();
// Results for each derivative, shape Y|X_i // Results for each derivative, shape Y|X_i
std::vector<std::shared_ptr<runtime::ParameterizedTensorView<ET>>> results; std::vector<std::shared_ptr<runtime::TensorView>> results;
for (auto param : params) for (auto param : params)
{ {
Shape s = y_shape; Shape s = y_shape;
...@@ -57,39 +57,36 @@ namespace ngraph ...@@ -57,39 +57,36 @@ namespace ngraph
std::dynamic_pointer_cast<const TensorViewType>(param->get_value_type()) std::dynamic_pointer_cast<const TensorViewType>(param->get_value_type())
->get_shape(); ->get_shape();
s.insert(s.end(), param_shape.begin(), param_shape.end()); s.insert(s.end(), param_shape.begin(), param_shape.end());
results.push_back(backend->make_parameterized_tensor_view<ET>(s)); results.push_back(backend->make_primary_tensor_view<T>(s));
} }
auto external = manager->compile(f); auto external = manager->compile(f);
auto cf = backend->make_call_frame(external); auto cf = backend->make_call_frame(external);
// ref_y is the function evaluated at the args // ref_y is the function evaluated at the args
auto ref_y = backend->make_parameterized_tensor_view<ET>(y_shape); auto ref_y = backend->make_primary_tensor_view<T>(y_shape);
ngraph::runtime::TensorViewPtrs args_tv; cf->tensor_call(args, std::vector<std::shared_ptr<ngraph::runtime::TensorView>>{ref_y});
args_tv.insert(args_tv.begin(), args.begin(), args.end()); auto ref_vec = ref_y->template get_vector<T>();
cf->tensor_call(args_tv, runtime::TensorViewPtrs{ref_y});
auto& ref_vec = ref_y->get_vector();
// inc_y will hold f(x+dx) values // inc_y will hold f(x+dx) values
auto inc_y = backend->make_parameterized_tensor_view<ET>(y_shape); auto inc_y = backend->make_primary_tensor_view<T>(y_shape);
auto& inc_vec = inc_y->get_vector();
// Assuming vars, y, and results are row-major // Assuming vars, y, and results are row-major
typename ET::type inv_delta = 1 / delta; T inv_delta = 1 / delta;
for (size_t i = 0; i < args.size(); ++i) for (size_t i = 0; i < args.size(); ++i)
{ {
auto arg = args[i]; auto arg = args[i];
auto res = results[i]->get_vector(); auto res = results[i]->get_vector<T>();
auto vec = arg->get_vector(); auto vec = arg->get_vector<T>();
for (size_t j = 0; j < vec.size(); j++) for (size_t j = 0; j < vec.size(); j++)
{ {
auto old_val = vec[j]; auto old_val = vec[j];
vec[j] += delta; vec[j] += delta;
arg->write(vec); arg->write(vec);
cf->tensor_call(args_tv, {inc_y}); cf->tensor_call(args, {inc_y});
auto inc_vec = inc_y->template get_vector<T>();
vec[j] = old_val; vec[j] = old_val;
arg->write(vec); arg->write(vec);
size_t res_k = j; size_t res_k = j;
......
...@@ -25,13 +25,11 @@ namespace ngraph ...@@ -25,13 +25,11 @@ namespace ngraph
{ {
/// @brief A predictable pseudo-random number generator /// @brief A predictable pseudo-random number generator
/// The seed is initialized so that we get repeatable pseudo-random numbers for tests /// The seed is initialized so that we get repeatable pseudo-random numbers for tests
template <typename ET> template <typename T>
class Uniform class Uniform
{ {
public: public:
using type = typename ET::type; Uniform(T min, T max, T seed = 0)
Uniform(type min, type max, type seed = 0)
: m_engine(seed) : m_engine(seed)
, m_distribution(min, max) , m_distribution(min, max)
, m_r(std::bind(m_distribution, m_engine)) , m_r(std::bind(m_distribution, m_engine))
...@@ -40,11 +38,11 @@ namespace ngraph ...@@ -40,11 +38,11 @@ namespace ngraph
/// @brief Randomly initialize a tensor /// @brief Randomly initialize a tensor
/// @param ptv The tensor to initialize /// @param ptv The tensor to initialize
const std::shared_ptr<runtime::ParameterizedTensorView<ET>> const std::shared_ptr<runtime::TensorView>
initialize(const std::shared_ptr<runtime::ParameterizedTensorView<ET>>& ptv) initialize(const std::shared_ptr<runtime::TensorView>& ptv)
{ {
auto vec = ptv->get_vector(); std::vector<T> vec = ptv->get_vector<T>();
for (auto& elt : vec) for (T& elt : vec)
{ {
elt = m_r(); elt = m_r();
} }
...@@ -54,8 +52,8 @@ namespace ngraph ...@@ -54,8 +52,8 @@ namespace ngraph
protected: protected:
std::default_random_engine m_engine; std::default_random_engine m_engine;
std::uniform_real_distribution<type> m_distribution; std::uniform_real_distribution<T> m_distribution;
std::function<type()> m_r; std::function<T()> m_r;
}; };
} }
} }
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