Commit a960f07e authored by Robert Kimball's avatar Robert Kimball Committed by Adam Procter

Bob/backend work (#295)

* add support for n-dimensional operations by calling runtime/kernels

* rename cpu backend classes and files

* add tuple support to INTERPRETER

* move ndarray out of runtime to test where it belonged

* fix Tuple op per review comment
parent ab63fd33
......@@ -147,14 +147,15 @@ if (NGRAPH_CPU_ENABLE AND LLVM_INCLUDE_DIR AND
codegen/code_writer.cpp
codegen/compiler.cpp
codegen/execution_engine.cpp
runtime/cpu/call_frame.cpp
runtime/cpu/cpu_call_frame.cpp
runtime/cpu/cpu_backend.cpp
runtime/cpu/cpu_manager.cpp
runtime/cpu/cpu_kernels.cpp
runtime/cpu/emitter.cpp
runtime/cpu/external_function.cpp
runtime/cpu/tensor_view.cpp
)
runtime/cpu/cpu_emitter.cpp
runtime/cpu/cpu_external_function.cpp
runtime/cpu/cpu_tensor_view.cpp
runtime/cpu/cpu_tensor_view_wrapper.cpp
)
# LLVM binary builds are typically built without RTTI
# The built-in headers are in a version-specific directory
# This must be kept in sync with the LLVM + Clang version in use
......
......@@ -15,6 +15,7 @@
#include <memory>
#include "ngraph/function.hpp"
#include "ngraph/log.hpp"
#include "ngraph/util.hpp"
using namespace std;
......
......@@ -15,67 +15,11 @@
#include <memory>
#include "ngraph/runtime/backend.hpp"
#include "ngraph/runtime/parameterized_tensor_view.hpp"
#include "ngraph/runtime/tensor_view.hpp"
#include "ngraph/runtime/tuple.hpp"
using namespace ngraph::runtime;
std::shared_ptr<TensorView>
Backend::make_primary_tensor_view(const ngraph::element::Type& element_type, const Shape& shape)
{
std::shared_ptr<TensorView> rc;
if (element_type == element::Bool::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::Bool>>(shape);
}
else if (element_type == element::Float32::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::Float32>>(shape);
}
else if (element_type == element::Float64::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::Float64>>(shape);
}
else if (element_type == element::Int8::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::Int8>>(shape);
}
else if (element_type == element::Int16::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::Int16>>(shape);
}
else if (element_type == element::Int32::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::Int32>>(shape);
}
else if (element_type == element::Int64::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::Int64>>(shape);
}
else if (element_type == element::UInt8::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::UInt8>>(shape);
}
else if (element_type == element::UInt16::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::UInt16>>(shape);
}
else if (element_type == element::UInt32::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::UInt32>>(shape);
}
else if (element_type == element::UInt64::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::UInt64>>(shape);
}
else
{
throw std::invalid_argument("Unknown element type in make_primary_tensor_view");
}
return rc;
}
std::shared_ptr<ngraph::runtime::Tuple>
Backend::make_tuple(const std::vector<std::shared_ptr<ngraph::runtime::Value>>& elements)
{
......
......@@ -51,7 +51,7 @@ namespace ngraph
/// @brief Return a handle for a tensor on the backend device.
virtual std::shared_ptr<ngraph::runtime::TensorView>
make_primary_tensor_view(const ngraph::element::Type& element_type,
const Shape& shape);
const Shape& shape) = 0;
template <typename T>
std::shared_ptr<ngraph::runtime::TensorView>
......
......@@ -13,22 +13,23 @@
// ----------------------------------------------------------------------------
#include "ngraph/runtime/cpu/cpu_backend.hpp"
#include "ngraph/runtime/cpu/tensor_view.hpp"
#include "ngraph/log.hpp"
#include "ngraph/runtime/cpu/cpu_tensor_view.hpp"
#include "ngraph/runtime/external_function.hpp"
using namespace ngraph;
using namespace std;
std::shared_ptr<ngraph::runtime::CallFrame> runtime::cpu::CPUBackend::make_call_frame(
std::shared_ptr<ngraph::runtime::CallFrame> runtime::cpu::CPU_Backend::make_call_frame(
const std::shared_ptr<ExternalFunction>& external_function)
{
return external_function->make_call_frame();
}
std::shared_ptr<ngraph::runtime::TensorView>
runtime::cpu::CPUBackend::make_primary_tensor_view(const ngraph::element::Type& element_type,
const Shape& shape)
runtime::cpu::CPU_Backend::make_primary_tensor_view(const ngraph::element::Type& element_type,
const Shape& shape)
{
auto rc = make_shared<runtime::cpu::CPUTensorView>(element_type, shape);
auto rc = make_shared<runtime::cpu::CPU_TensorView>(element_type, shape);
return dynamic_pointer_cast<runtime::TensorView>(rc);
}
......@@ -24,7 +24,7 @@ namespace ngraph
{
static size_t alignment = 64;
class CPUBackend : public runtime::Backend
class CPU_Backend : public runtime::Backend
{
public:
std::shared_ptr<ngraph::runtime::CallFrame> make_call_frame(
......
......@@ -14,20 +14,20 @@
#include <algorithm>
#include "call_frame.hpp"
#include "ngraph/runtime/cpu/tensor_view.hpp"
#include "ngraph/runtime/cpu/cpu_call_frame.hpp"
#include "ngraph/runtime/cpu/cpu_tensor_view.hpp"
using namespace std;
using namespace ngraph::runtime::cpu;
using namespace ngraph;
CallFrame::CallFrame(std::shared_ptr<ExternalFunction> external_function,
EntryPoint compiled_function)
runtime::cpu::CPU_CallFrame::CPU_CallFrame(std::shared_ptr<CPU_ExternalFunction> external_function,
EntryPoint compiled_function)
: m_external_function(external_function)
, m_compiled_function(compiled_function)
{
}
void CallFrame::tensor_call(
void runtime::cpu::CPU_CallFrame::tensor_call(
const std::vector<std::shared_ptr<ngraph::runtime::TensorView>>& input_tvs,
const std::vector<std::shared_ptr<ngraph::runtime::TensorView>>& output_tvs)
{
......@@ -35,14 +35,14 @@ void CallFrame::tensor_call(
vector<void*> outputs;
for (size_t i = 0; i < input_tvs.size(); i++)
{
shared_ptr<runtime::cpu::CPUTensorView> tv =
static_pointer_cast<runtime::cpu::CPUTensorView>(input_tvs[i]);
shared_ptr<runtime::cpu::CPU_TensorView> tv =
static_pointer_cast<runtime::cpu::CPU_TensorView>(input_tvs[i]);
inputs.push_back(tv->get_data_ptr());
}
for (size_t i = 0; i < output_tvs.size(); i++)
{
shared_ptr<runtime::cpu::CPUTensorView> tv =
static_pointer_cast<runtime::cpu::CPUTensorView>(output_tvs[i]);
shared_ptr<runtime::cpu::CPU_TensorView> tv =
static_pointer_cast<runtime::cpu::CPU_TensorView>(output_tvs[i]);
outputs.push_back(tv->get_data_ptr());
}
......@@ -50,8 +50,9 @@ void CallFrame::tensor_call(
m_compiled_function(inputs.data(), outputs.data());
}
void CallFrame::call(const std::vector<std::shared_ptr<ngraph::runtime::Value>>& arguments,
const std::vector<std::shared_ptr<ngraph::runtime::Value>>& results)
void runtime::cpu::CPU_CallFrame::call(
const std::vector<std::shared_ptr<ngraph::runtime::Value>>& arguments,
const std::vector<std::shared_ptr<ngraph::runtime::Value>>& results)
{
// TODO: Check types of args and result
vector<shared_ptr<ngraph::runtime::TensorView>> inputs;
......
......@@ -30,19 +30,19 @@ namespace ngraph
namespace cpu
{
class CallFrame;
class ExternalFunction;
class CPU_CallFrame;
class CPU_ExternalFunction;
using EntryPoint_t = void(void** inputs, void** outputs);
using EntryPoint = std::function<EntryPoint_t>;
// Compile and execute graphs
class CallFrame : public ngraph::runtime::CallFrame
class CPU_CallFrame : public ngraph::runtime::CallFrame
{
public:
CallFrame(std::shared_ptr<ExternalFunction> external_function,
EntryPoint compiled_function);
CPU_CallFrame(std::shared_ptr<CPU_ExternalFunction> external_function,
EntryPoint compiled_function);
/// @brief Invoke the function with values matching the signature of the function.
///
......@@ -56,7 +56,7 @@ namespace ngraph
const std::vector<std::shared_ptr<TensorView>>& outputs);
protected:
std::shared_ptr<ExternalFunction> m_external_function;
std::shared_ptr<CPU_ExternalFunction> m_external_function;
EntryPoint m_compiled_function;
};
}
......
......@@ -22,8 +22,6 @@ namespace ngraph
{
namespace runtime
{
class TensorViewInfo;
namespace cpu
{
class CallFrame;
......
This diff is collapsed.
......@@ -19,13 +19,13 @@
#include "ngraph/codegen/code_writer.hpp"
#include "ngraph/node.hpp"
#include "ngraph/runtime/cpu/external_function.hpp"
#include "ngraph/runtime/tensor_view_info.hpp"
#include "ngraph/runtime/cpu/cpu_external_function.hpp"
#include "ngraph/runtime/cpu/cpu_tensor_view_wrapper.hpp"
#define EMITTER_DECL(E) \
E(const ngraph::Node* n, \
const std::vector<TensorViewInfo>& inputs, \
const std::vector<TensorViewInfo>& outputs)
const std::vector<ngraph::runtime::cpu::TensorViewWrapper>& args, \
const std::vector<ngraph::runtime::cpu::TensorViewWrapper>& out)
namespace ngraph
{
......@@ -33,18 +33,18 @@ namespace ngraph
{
namespace cpu
{
class Emitter
class CPU_Emitter
{
protected:
codegen::CodeWriter TU;
codegen::CodeWriter m_out;
public:
Emitter()
: TU()
CPU_Emitter()
: m_out()
{
}
std::string get_code() { return TU.get_code(); }
codegen::CodeWriter& get_code_writer() { return TU; }
std::string get_code() { return m_out.get_code(); }
codegen::CodeWriter& get_code_writer() { return m_out; }
void EMITTER_DECL(EmitNop);
void EMITTER_DECL(EmitAdd);
void EMITTER_DECL(EmitDot);
......@@ -101,13 +101,13 @@ namespace ngraph
void EMITTER_DECL(EmitSqrt);
private:
void generate_call(const std::vector<TensorViewInfo>& inputs,
const std::vector<TensorViewInfo>& outputs,
void generate_call(const std::vector<TensorViewWrapper>& args,
const std::vector<TensorViewWrapper>& out,
std::shared_ptr<Function> function);
std::string emit_vector(const TensorViewInfo&, const std::string& name = "");
std::string emit_array1d(const TensorViewInfo&, const std::string& name = "");
std::string emit_matrix(const TensorViewInfo&, const std::string& name = "");
std::string emit_vector(const TensorViewWrapper&, const std::string& name = "");
std::string emit_array1d(const TensorViewWrapper&, const std::string& name = "");
std::string emit_matrix(const TensorViewWrapper&, const std::string& name = "");
};
}
}
......
......@@ -23,9 +23,9 @@
#include "ngraph/codegen/compiler.hpp"
#include "ngraph/codegen/execution_engine.hpp"
#include "ngraph/function.hpp"
#include "ngraph/runtime/cpu/call_frame.hpp"
#include "ngraph/runtime/cpu/cpu_call_frame.hpp"
#include "ngraph/runtime/cpu/cpu_tensor_view_wrapper.hpp"
#include "ngraph/runtime/external_function.hpp"
#include "ngraph/runtime/tensor_view_info.hpp"
namespace ngraph
{
......@@ -33,23 +33,23 @@ namespace ngraph
{
namespace cpu
{
class ExternalFunction;
class Emitter;
class CallFrame;
class CPU_ExternalFunction;
class CPU_Emitter;
class CPU_CallFrame;
using OpFunction = std::function<void(Emitter*,
using OpFunction = std::function<void(CPU_Emitter*,
const ngraph::Node*,
const std::vector<TensorViewInfo>& inputs,
const std::vector<TensorViewInfo>& outputs)>;
const std::vector<TensorViewWrapper>& inputs,
const std::vector<TensorViewWrapper>& outputs)>;
using OpMap = std::unordered_map<std::type_index, OpFunction>;
class ExternalFunction : public ngraph::runtime::ExternalFunction,
public std::enable_shared_from_this<ExternalFunction>
class CPU_ExternalFunction : public ngraph::runtime::ExternalFunction,
public std::enable_shared_from_this<CPU_ExternalFunction>
{
public:
ExternalFunction(const std::shared_ptr<ngraph::Function>& function,
bool release_function = true);
CPU_ExternalFunction(const std::shared_ptr<ngraph::Function>& function,
bool release_function = true);
std::shared_ptr<ngraph::runtime::CallFrame> make_call_frame();
protected:
......
......@@ -15,23 +15,24 @@
#include <memory>
#include "ngraph/runtime/cpu/cpu_backend.hpp"
#include "ngraph/runtime/cpu/cpu_external_function.hpp"
#include "ngraph/runtime/cpu/cpu_manager.hpp"
#include "ngraph/runtime/cpu/external_function.hpp"
using namespace ngraph::runtime::cpu;
using namespace ngraph;
std::shared_ptr<ngraph::runtime::Backend> CPUManager::allocate_backend()
std::shared_ptr<ngraph::runtime::Backend> runtime::cpu::CPU_Manager::allocate_backend()
{
return std::make_shared<CPUBackend>();
return std::make_shared<CPU_Backend>();
}
std::shared_ptr<ngraph::runtime::ExternalFunction>
CPUManager::compile(const std::shared_ptr<ngraph::Function>& fun)
runtime::cpu::CPU_Manager::compile(const std::shared_ptr<ngraph::Function>& fun)
{
return std::make_shared<ExternalFunction>(fun);
return std::make_shared<CPU_ExternalFunction>(fun);
}
ngraph::runtime::Manager::Factory CPUManager::factory = ngraph::runtime::Manager::register_factory(
"CPU", [](const std::string& name) -> std::shared_ptr<ngraph::runtime::Manager> {
return std::make_shared<CPUManager>();
});
ngraph::runtime::Manager::Factory runtime::cpu::CPU_Manager::factory =
ngraph::runtime::Manager::register_factory(
"CPU", [](const std::string& name) -> std::shared_ptr<ngraph::runtime::Manager> {
return std::make_shared<CPU_Manager>();
});
......@@ -30,7 +30,7 @@ namespace ngraph
namespace cpu
{
/// @brief Transformer for the interpreted backend
class CPUManager : public Manager
class CPU_Manager : public Manager
{
protected:
ngraph::codegen::ExecutionEngine exec_state;
......
......@@ -12,18 +12,19 @@
// See the License for the specific language governing permissions and
// ----------------------------------------------------------------------------
#include <cstring>
#include <memory>
#include "ngraph/descriptor/layout/dense_tensor_view_layout.hpp"
#include "ngraph/descriptor/primary_tensor_view.hpp"
#include "ngraph/runtime/cpu/cpu_backend.hpp"
#include "ngraph/runtime/cpu/tensor_view.hpp"
#include "ngraph/runtime/cpu/cpu_tensor_view.hpp"
using namespace ngraph;
using namespace std;
runtime::cpu::CPUTensorView::CPUTensorView(const ngraph::element::Type& element_type,
const Shape& shape)
runtime::cpu::CPU_TensorView::CPU_TensorView(const ngraph::element::Type& element_type,
const Shape& shape)
: runtime::TensorView(std::make_shared<ngraph::descriptor::PrimaryTensorView>(
std::make_shared<ngraph::TensorViewType>(element_type, shape),
"external",
......@@ -51,7 +52,7 @@ runtime::cpu::CPUTensorView::CPUTensorView(const ngraph::element::Type& element_
}
}
runtime::cpu::CPUTensorView::~CPUTensorView()
runtime::cpu::CPU_TensorView::~CPU_TensorView()
{
if (m_allocated_buffer_pool != nullptr)
{
......@@ -59,17 +60,17 @@ runtime::cpu::CPUTensorView::~CPUTensorView()
}
}
char* runtime::cpu::CPUTensorView::get_data_ptr()
char* runtime::cpu::CPU_TensorView::get_data_ptr()
{
return m_aligned_buffer_pool;
}
const char* runtime::cpu::CPUTensorView::get_data_ptr() const
const char* runtime::cpu::CPU_TensorView::get_data_ptr() const
{
return m_aligned_buffer_pool;
}
void runtime::cpu::CPUTensorView::write(const void* source, size_t tensor_offset, size_t n)
void runtime::cpu::CPU_TensorView::write(const void* source, size_t tensor_offset, size_t n)
{
if (tensor_offset + n > m_buffer_size)
{
......@@ -79,7 +80,7 @@ void runtime::cpu::CPUTensorView::write(const void* source, size_t tensor_offset
memcpy(&target[tensor_offset], source, n);
}
void runtime::cpu::CPUTensorView::read(void* target, size_t tensor_offset, size_t n) const
void runtime::cpu::CPU_TensorView::read(void* target, size_t tensor_offset, size_t n) const
{
if (tensor_offset + n > m_buffer_size)
{
......@@ -88,3 +89,13 @@ void runtime::cpu::CPUTensorView::read(void* target, size_t tensor_offset, size_
const char* source = get_data_ptr();
memcpy(target, &source[tensor_offset], n);
}
size_t runtime::cpu::CPU_TensorView::get_size() const
{
return get_tensor_view_layout()->get_size();
}
const element::Type& runtime::cpu::CPU_TensorView::get_element_type() const
{
return get_tensor_view_layout()->get_element_type();
}
......@@ -25,20 +25,23 @@ namespace ngraph
{
namespace cpu
{
class CPUTensorView;
class CPU_TensorView;
}
}
}
class ngraph::runtime::cpu::CPUTensorView : public ngraph::runtime::TensorView
class ngraph::runtime::cpu::CPU_TensorView : public ngraph::runtime::TensorView
{
public:
CPUTensorView(const ngraph::element::Type& element_type, const Shape& shape);
virtual ~CPUTensorView();
CPU_TensorView(const ngraph::element::Type& element_type, const Shape& shape);
virtual ~CPU_TensorView();
char* get_data_ptr();
const char* get_data_ptr() const;
size_t get_size() const;
const element::Type& get_element_type() const;
/// @brief Write bytes directly into the tensor
/// @param p Pointer to source of data
/// @param tensor_offset Offset into tensor storage to begin writing. Must be element-aligned.
......
// ----------------------------------------------------------------------------
// 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/runtime/cpu/cpu_tensor_view_wrapper.hpp"
#include "ngraph/descriptor/layout/tensor_view_layout.hpp"
#include "ngraph/descriptor/tensor.hpp"
using namespace std;
using namespace ngraph;
runtime::cpu::TensorViewWrapper::TensorViewWrapper(const shared_ptr<descriptor::TensorView>& tv)
: m_tensor_view(tv)
{
}
size_t runtime::cpu::TensorViewWrapper::get_size() const
{
return m_tensor_view->get_tensor_view_layout()->get_size();
}
const vector<size_t>& runtime::cpu::TensorViewWrapper::get_shape() const
{
return m_tensor_view->get_tensor_view_layout()->get_shape();
}
const vector<size_t>& runtime::cpu::TensorViewWrapper::get_strides() const
{
return m_tensor_view->get_tensor_view_layout()->get_strides();
}
const element::Type& runtime::cpu::TensorViewWrapper::get_element_type() const
{
return m_tensor_view->get_tensor_view_layout()->get_element_type();
}
const std::string& runtime::cpu::TensorViewWrapper::get_name() const
{
return m_tensor_view->get_tensor().get_name();
}
const std::string& runtime::cpu::TensorViewWrapper::get_type() const
{
return get_element_type().c_type_string();
}
bool runtime::cpu::TensorViewWrapper::is_output() const
{
return m_tensor_view->get_tensor().is_output();
}
// ----------------------------------------------------------------------------
// 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 <memory>
#include "ngraph/descriptor/tensor_view.hpp"
#include "ngraph/types/element_type.hpp"
namespace ngraph
{
namespace runtime
{
namespace cpu
{
class TensorViewWrapper;
}
}
}
class ngraph::runtime::cpu::TensorViewWrapper
{
public:
TensorViewWrapper(const std::shared_ptr<descriptor::TensorView>&);
size_t get_size() const;
const std::vector<size_t>& get_shape() const;
const std::vector<size_t>& get_strides() const;
const element::Type& get_element_type() const;
const std::string& get_name() const;
const std::string& get_type() const;
bool is_output() const;
private:
std::shared_ptr<descriptor::TensorView> m_tensor_view;
};
This diff is collapsed.
......@@ -20,7 +20,6 @@
#include <unordered_map>
#include "ngraph/function.hpp"
#include "ngraph/runtime/tensor_view_info.hpp"
namespace ngraph
{
......
......@@ -14,6 +14,8 @@
#include <algorithm>
#include "ngraph/ops/get_tuple_element.hpp"
#include "ngraph/ops/tuple.hpp"
#include "ngraph/runtime/interpreter/int_call_frame.hpp"
#include "ngraph/runtime/interpreter/int_tensor_view.hpp"
......@@ -33,121 +35,93 @@ void runtime::interpreter::INT_CallFrame::call(
const vector<shared_ptr<runtime::interpreter::INT_TensorView>>& output_tvs)
{
unordered_map<string, shared_ptr<runtime::interpreter::INT_TensorView>> tensor_map;
const std::vector<std::shared_ptr<op::Parameter>>& params = function->get_parameters();
for (size_t i = 0; i < input_tvs.size(); i++)
size_t arg_index = 0;
for (shared_ptr<op::Parameter> param : function->get_parameters())
{
string name = params[i]->get_name();
tensor_map.insert({name, input_tvs[i]});
for (const descriptor::Output& output : param->get_outputs())
{
shared_ptr<descriptor::TensorView> tv = output.get_tensor_view();
string name = tv->get_tensor().get_name();
tensor_map.insert({name, input_tvs[arg_index++]});
}
}
for (size_t i = 0; i < output_tvs.size(); i++)
{
string name = function->get_result()->get_name();
descriptor::Output& output = function->get_result()->get_outputs().at(i);
shared_ptr<descriptor::TensorView> tv = output.get_tensor_view();
string name = tv->get_tensor().get_name();
tensor_map.insert({name, output_tvs[i]});
}
// Invoke computation
for (shared_ptr<Node> op : function->get_ordered_ops())
{
vector<shared_ptr<runtime::interpreter::INT_TensorView>> inputs;
vector<shared_ptr<runtime::interpreter::INT_TensorView>> outputs;
element::Type base_type;
if (op->get_inputs().empty())
{
base_type = op->get_element_type();
}
else
{
base_type = op->get_inputs().at(0).get_tensor().get_element_type();
}
element::Type secondary_type = op->get_element_type();
// Some ops have unusual intput/output types so handle those special cases here
if (op->description() == "Select")
if (op->description() == "Parameter")
{
base_type = op->get_inputs().at(1).get_tensor().get_element_type();
secondary_type = op->get_inputs().at(0).get_tensor().get_element_type();
continue;
}
vector<shared_ptr<runtime::interpreter::INT_TensorView>> inputs;
vector<shared_ptr<runtime::interpreter::INT_TensorView>> outputs;
for (const descriptor::Input& input : op->get_inputs())
{
string name = input.get_output().get_node()->get_name();
shared_ptr<runtime::interpreter::INT_TensorView> tv = tensor_map.at(name);
inputs.push_back(tv);
// NGRAPH_INFO << "Op Inputs " << name;
shared_ptr<descriptor::TensorView> tv = input.get_output().get_tensor_view();
string name = tv->get_tensor().get_name();
inputs.push_back(tensor_map.at(name));
}
for (descriptor::Output& output : op->get_outputs())
{
string name = output.get_node()->get_name();
shared_ptr<runtime::interpreter::INT_TensorView> tv;
shared_ptr<descriptor::TensorView> tv = output.get_tensor_view();
string name = tv->get_tensor().get_name();
shared_ptr<runtime::interpreter::INT_TensorView> itv;
if (!contains_key(tensor_map, name))
{
// The output tensor is not in the tensor map so create a new tensor
const Shape& shape = output.get_tensor_view_type()->get_shape();
element::Type element_type = output.get_tensor_view_type()->get_element_type();
string tensor_name = output.get_tensor().get_name();
tv = make_shared<runtime::interpreter::INT_TensorView>(
itv = make_shared<runtime::interpreter::INT_TensorView>(
element_type, shape, tensor_name);
tensor_map.insert({name, tv});
tensor_map.insert({name, itv});
}
else
{
tv = tensor_map.at(name);
itv = tensor_map.at(name);
}
outputs.push_back(tv);
// NGRAPH_INFO << "Op Outputs " << name;
}
if (base_type == element::boolean)
{
generate_calls<char>(secondary_type, *op, inputs, outputs);
}
else if (base_type == element::f32)
{
generate_calls<float>(secondary_type, *op, inputs, outputs);
outputs.push_back(itv);
}
else if (base_type == element::f64)
auto tuple = dynamic_pointer_cast<op::Tuple>(op);
if (tuple)
{
generate_calls<double>(secondary_type, *op, inputs, outputs);
}
else if (base_type == element::i8)
{
generate_calls<int8_t>(secondary_type, *op, inputs, outputs);
}
else if (base_type == element::i16)
{
generate_calls<int16_t>(secondary_type, *op, inputs, outputs);
}
else if (base_type == element::i32)
{
generate_calls<int32_t>(secondary_type, *op, inputs, outputs);
}
else if (base_type == element::i64)
{
generate_calls<int64_t>(secondary_type, *op, inputs, outputs);
}
else if (base_type == element::u8)
{
generate_calls<uint8_t>(secondary_type, *op, inputs, outputs);
}
else if (base_type == element::u16)
{
generate_calls<uint16_t>(secondary_type, *op, inputs, outputs);
}
else if (base_type == element::u32)
{
generate_calls<uint32_t>(secondary_type, *op, inputs, outputs);
}
else if (base_type == element::u64)
{
generate_calls<uint64_t>(secondary_type, *op, inputs, outputs);
for (size_t i = 0; i < inputs.size(); i++)
{
const element::Type& type = inputs[0]->get_tensor().get_element_type();
generate_calls(type, type, *op, {inputs[i]}, {outputs[i]});
}
}
else
{
stringstream ss;
ss << "unsupported element type " << base_type << " op " << op->get_name();
throw runtime_error(ss.str());
element::Type base_type;
element::Type secondary_type;
if (op->get_inputs().empty())
{
base_type = op->get_element_type();
}
else
{
base_type = op->get_inputs().at(0).get_tensor().get_element_type();
}
secondary_type = op->get_element_type();
// Some ops have unusual intput/output types so handle those special cases here
if (op->description() == "Select")
{
base_type = op->get_inputs().at(1).get_tensor().get_element_type();
secondary_type = op->get_inputs().at(0).get_tensor().get_element_type();
}
generate_calls(base_type, secondary_type, *op, inputs, outputs);
}
// Delete any obsolete tensors
......@@ -165,6 +139,65 @@ void runtime::interpreter::INT_CallFrame::call(
}
}
void runtime::interpreter::INT_CallFrame::generate_calls(
const element::Type& base_type,
const element::Type& secondary_type,
ngraph::Node& op,
const std::vector<std::shared_ptr<INT_TensorView>>& args,
const std::vector<std::shared_ptr<INT_TensorView>>& out)
{
if (base_type == element::boolean)
{
generate_calls<char>(secondary_type, op, args, out);
}
else if (base_type == element::f32)
{
generate_calls<float>(secondary_type, op, args, out);
}
else if (base_type == element::f64)
{
generate_calls<double>(secondary_type, op, args, out);
}
else if (base_type == element::i8)
{
generate_calls<int8_t>(secondary_type, op, args, out);
}
else if (base_type == element::i16)
{
generate_calls<int16_t>(secondary_type, op, args, out);
}
else if (base_type == element::i32)
{
generate_calls<int32_t>(secondary_type, op, args, out);
}
else if (base_type == element::i64)
{
generate_calls<int64_t>(secondary_type, op, args, out);
}
else if (base_type == element::u8)
{
generate_calls<uint8_t>(secondary_type, op, args, out);
}
else if (base_type == element::u16)
{
generate_calls<uint16_t>(secondary_type, op, args, out);
}
else if (base_type == element::u32)
{
generate_calls<uint32_t>(secondary_type, op, args, out);
}
else if (base_type == element::u64)
{
generate_calls<uint64_t>(secondary_type, op, args, out);
}
else
{
stringstream ss;
ss << "unsupported element type " << base_type << " op " << op.get_name();
throw runtime_error(ss.str());
}
}
void runtime::interpreter::INT_CallFrame::tensor_call(
const vector<shared_ptr<runtime::interpreter::INT_TensorView>>& input_tvs,
const vector<shared_ptr<runtime::interpreter::INT_TensorView>>& output_tvs)
......
......@@ -23,6 +23,7 @@
#include "ngraph/ops/broadcast.hpp"
#include "ngraph/ops/concatenate.hpp"
#include "ngraph/ops/constant.hpp"
#include "ngraph/ops/get_tuple_element.hpp"
#include "ngraph/ops/one_hot.hpp"
#include "ngraph/ops/reduce.hpp"
#include "ngraph/ops/replace_slice.hpp"
......@@ -119,6 +120,11 @@ private:
std::shared_ptr<ExternalFunction> m_external_function;
std::shared_ptr<Function> m_function;
void generate_calls(const element::Type& base_type,
const element::Type& secondary_type,
ngraph::Node& op,
const std::vector<std::shared_ptr<INT_TensorView>>& args,
const std::vector<std::shared_ptr<INT_TensorView>>& out);
template <typename BASE>
void generate_calls(const element::Type& type,
......@@ -358,6 +364,13 @@ private:
std::shared_ptr<Function> function = node.get_function();
call(function, args, out);
}
else if (node_op == "GetTupleElement")
{
auto gte = dynamic_cast<op::GetTupleElement*>(&node);
kernel::copy<T>(reinterpret_cast<T*>(args[gte->get_n()]->get_data_ptr()),
reinterpret_cast<T*>(out[0]->get_data_ptr()),
out[0]->get_element_count());
}
else if (node_op == "Greater")
{
kernel::greater<T>(reinterpret_cast<T*>(args[0]->get_data_ptr()),
......@@ -675,6 +688,15 @@ private:
reinterpret_cast<T*>(out[0]->get_data_ptr()),
out[0]->get_element_count());
}
else if (node_op == "Tuple")
{
for (size_t i = 0; i < args.size(); ++i)
{
kernel::copy<T>(reinterpret_cast<T*>(args[i]->get_data_ptr()),
reinterpret_cast<T*>(out[i]->get_data_ptr()),
out[i]->get_element_count());
}
}
else
{
std::stringstream ss;
......
......@@ -24,7 +24,6 @@
#include "ngraph/runtime/external_function.hpp"
#include "ngraph/runtime/interpreter/int_backend.hpp"
#include "ngraph/runtime/interpreter/int_call_frame.hpp"
#include "ngraph/runtime/tensor_view_info.hpp"
namespace ngraph
{
......
......@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// ----------------------------------------------------------------------------
#include <cstring>
#include <memory>
#include "ngraph/descriptor/layout/dense_tensor_view_layout.hpp"
......
// ----------------------------------------------------------------------------
// 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 <Eigen/Dense>
#include "ngraph/common.hpp"
namespace ngraph
{
namespace runtime
{
class TensorViewInfo;
class CallFrame;
namespace kernel
{
using DynamicStrides = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
using VectorStrides = Eigen::Stride<Eigen::Dynamic, 1>;
template <typename T>
using DynamicArray = Eigen::Array<T, Eigen::Dynamic, Eigen::Dynamic>;
template <typename T>
using EigenArrayBase = Eigen::Map<DynamicArray<T>, 0, DynamicStrides>;
template <typename T>
using DynamicMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
template <typename T>
using EigenMatrixBase = Eigen::Map<DynamicMatrix<T>, 0, DynamicStrides>;
template <typename T>
using DynamicVector = Eigen::Matrix<T, Eigen::Dynamic, 1>;
template <typename T>
using EigenVectorBase = Eigen::Map<DynamicVector<T>, 0, VectorStrides>;
namespace fmt
{
/// @brief vector format for Eigen wrappers.
class V
{
public:
V(size_t s)
: l0(s)
{
}
public:
size_t l0;
size_t l1{1};
size_t s0{1};
size_t s1{1};
};
class M
{
public:
M(const Shape& shape, const Strides& strides)
: l0(shape.at(0))
, l1(shape.at(1))
, s0(strides.at(0))
, s1(strides.at(1))
{
}
public:
size_t l0;
size_t l1;
size_t s0;
size_t s1;
};
}
// T element type
// FMT array format (fmt::V for vector, etc.)
// BASE select array/matrix
template <typename T, typename FMT, typename BASE, typename STRIDES = DynamicStrides>
class EigenWrapper : public BASE
{
using base = BASE;
public:
EigenWrapper(T* t, const FMT& fmt)
: base(t, fmt.l0, fmt.l1, STRIDES(fmt.s0, fmt.s1))
{
}
template <typename U>
EigenWrapper& operator=(const U& other)
{
this->base::operator=(other);
return *this;
}
};
template <typename T, typename FMT = fmt::V>
using EigenArray1d = EigenWrapper<T, FMT, EigenArrayBase<T>>;
template <typename T, typename FMT = fmt::M>
using EigenArray2d = EigenWrapper<T, FMT, EigenArrayBase<T>>;
template <typename T, typename FMT = fmt::M>
using EigenMatrix = EigenWrapper<T, FMT, EigenMatrixBase<T>>;
template <typename T, typename FMT = fmt::V>
using EigenVector = EigenWrapper<T, FMT, EigenVectorBase<T>, VectorStrides>;
}
}
}
......@@ -21,7 +21,7 @@
#include "ngraph/function.hpp"
#include "ngraph/runtime/external_function.hpp"
#include "ngraph/runtime/tensor_view_info.hpp"
#include "ngraph/runtime/ngvm/tensor_view_info.hpp"
namespace ngraph
{
......
......@@ -16,8 +16,8 @@
#include "ngraph/runtime/ngvm/call_frame.hpp"
#include "ngraph/runtime/ngvm/instruction.hpp"
#include "ngraph/runtime/ngvm/tensor_view_info.hpp"
#include "ngraph/runtime/tensor_view.hpp"
#include "ngraph/runtime/tensor_view_info.hpp"
namespace ngraph
{
......
......@@ -14,6 +14,7 @@
#include "ngraph/runtime/ngvm/ngvm_backend.hpp"
#include "ngraph/runtime/external_function.hpp"
#include "ngraph/runtime/parameterized_tensor_view.hpp"
using namespace ngraph::runtime::ngvm;
......@@ -22,3 +23,59 @@ std::shared_ptr<ngraph::runtime::CallFrame>
{
return external_function->make_call_frame();
}
std::shared_ptr<ngraph::runtime::TensorView>
NGVMBackend::make_primary_tensor_view(const ngraph::element::Type& element_type,
const Shape& shape)
{
std::shared_ptr<TensorView> rc;
if (element_type == element::Bool::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::Bool>>(shape);
}
else if (element_type == element::Float32::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::Float32>>(shape);
}
else if (element_type == element::Float64::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::Float64>>(shape);
}
else if (element_type == element::Int8::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::Int8>>(shape);
}
else if (element_type == element::Int16::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::Int16>>(shape);
}
else if (element_type == element::Int32::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::Int32>>(shape);
}
else if (element_type == element::Int64::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::Int64>>(shape);
}
else if (element_type == element::UInt8::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::UInt8>>(shape);
}
else if (element_type == element::UInt16::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::UInt16>>(shape);
}
else if (element_type == element::UInt32::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::UInt32>>(shape);
}
else if (element_type == element::UInt64::element_type())
{
rc = std::make_shared<ParameterizedTensorView<element::UInt64>>(shape);
}
else
{
throw std::invalid_argument("Unknown element type in make_primary_tensor_view");
}
return rc;
}
......@@ -26,8 +26,13 @@ namespace ngraph
class NGVMBackend : public Backend
{
public:
virtual std::shared_ptr<ngraph::runtime::CallFrame> make_call_frame(
const std::shared_ptr<ngraph::runtime::ExternalFunction>& external_function);
std::shared_ptr<ngraph::runtime::CallFrame> make_call_frame(
const std::shared_ptr<ngraph::runtime::ExternalFunction>& external_function)
override;
std::shared_ptr<ngraph::runtime::TensorView>
make_primary_tensor_view(const ngraph::element::Type& element_type,
const Shape& shape) override;
};
}
}
......
......@@ -18,7 +18,7 @@
#include "ngraph/descriptor/layout/dense_tensor_view_layout.hpp"
#include "ngraph/runtime/ngvm/call_frame.hpp"
#include "ngraph/runtime/tensor_view_info.hpp"
#include "ngraph/runtime/ngvm/tensor_view_info.hpp"
namespace ngraph
{
......
......@@ -18,8 +18,6 @@
#include <vector>
#include "ngraph/descriptor/tensor_view.hpp"
#include "ngraph/log.hpp"
#include "ngraph/runtime/ndarray.hpp"
#include "ngraph/runtime/value.hpp"
#include "ngraph/shape.hpp"
#include "ngraph/util.hpp"
......@@ -81,18 +79,6 @@ namespace ngraph
// This is for unit test only
template <typename T>
bool operator==(const NDArrayBase<T>& ndarray) const
{
bool rc = false;
if (get_shape() == ndarray.get_shape())
{
std::vector<T> lhs(ndarray.get_vector().size());
read(lhs.data(), 0, ndarray.get_vector().size() * sizeof(T));
rc = (lhs == ndarray.get_vector());
}
return rc;
}
template <typename T>
std::vector<T> get_vector()
{
size_t element_count = shape_size(get_shape());
......
This diff is collapsed.
......@@ -38,7 +38,7 @@ namespace ngraph
public:
virtual ~ValueType() {}
virtual bool operator==(const ValueType& that) const = 0;
bool operator!=(const ValueType& that) const { return !(*this == that); }
bool operator!=(const ValueType& that) const;
/// Add tensor views in depth-first order.
virtual void collect_tensor_views(
std::vector<std::shared_ptr<const TensorViewType>>& views) const = 0;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment