Unverified Commit 0ef1c2f9 authored by Jai Menon's avatar Jai Menon Committed by GitHub

Merge pull request #243 from NervanaSystems/bob/static_compiler

Bob/static compiler
parents 7b9b35d3 1ac8d820
......@@ -106,12 +106,14 @@ if (NGRAPH_CPU_ENABLE AND LLVM_INCLUDE_DIR AND
set(SRC ${SRC}
codegen/code_writer.cpp
codegen/compiler.cpp
codegen/execution_engine.cpp
runtime/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/memory_handler.cpp
runtime/cpu/tensor_view.cpp
)
# LLVM binary builds are typically built without RTTI
......
This diff is collapsed.
......@@ -27,10 +27,18 @@ namespace ngraph
namespace codegen
{
class module;
class execution_state;
class Compiler;
class StaticCompiler;
class HeaderCache;
}
}
namespace clang
{
class HeaderSearchOptions;
class CompilerInstance;
}
class ngraph::codegen::module
{
public:
......@@ -38,39 +46,57 @@ private:
std::unique_ptr<llvm::Module> m_module;
};
class ngraph::codegen::execution_state : public llvm::SectionMemoryManager
class ngraph::codegen::Compiler
{
public:
execution_state();
~execution_state();
void set_precompiled_headers_enabled(bool state) { precompiled_headers_enabled = state; }
bool is_precompiled_headers_enabled() { return precompiled_headers_enabled; }
void set_debuginfo_enabled(bool state) { debuginfo_enabled = state; }
bool is_debuginfo_enabled() { return debuginfo_enabled; }
std::unique_ptr<llvm::Module> compile(const std::string& source, const std::string& name = "");
bool add_module(std::unique_ptr<llvm::Module>&);
Compiler();
~Compiler();
std::unique_ptr<llvm::Module> compile(const std::string& source);
void finalize();
private:
};
template <typename ftype>
std::function<ftype> find_function(const std::string& func_name)
{
auto f = m_execution_engine->getPointerToNamedFunction(func_name);
class ngraph::codegen::StaticCompiler : public llvm::SectionMemoryManager
{
public:
StaticCompiler();
~StaticCompiler();
return f_cast<ftype>(f);
}
void set_precompiled_headers_enabled(bool state) { m_precompiled_headers_enabled = state; }
bool is_precompiled_headers_enabled() { return m_precompiled_headers_enabled; }
void set_debuginfo_enabled(bool state) { m_debuginfo_enabled = state; }
bool is_debuginfo_enabled() { return m_debuginfo_enabled; }
void add_header_search_path(const std::string& path);
std::unique_ptr<llvm::Module> compile(const std::string& source);
private:
llvm::ExecutionEngine* m_execution_engine;
std::string jit_error;
bool precompiled_headers_enabled;
bool debuginfo_enabled;
std::unique_ptr<clang::CompilerInstance> m_compiler;
bool m_precompiled_headers_enabled;
bool m_debuginfo_enabled;
std::string m_source_name;
std::vector<std::string> m_extra_search_path_list;
template <typename signature>
std::function<signature> f_cast(void* f)
bool is_version_number(const std::string& path);
void use_cached_files();
};
class ngraph::codegen::HeaderCache
{
public:
bool is_valid() const { return m_headers_valid; }
bool set_valid() { return m_headers_valid = true; }
void add_path(const std::string& path) { m_include_paths.push_back(path); }
void add_file(const std::string& path, std::unique_ptr<llvm::MemoryBuffer>& code)
{
m_headers.insert(std::make_pair(path, std::move(code)));
}
const std::map<std::string, std::unique_ptr<llvm::MemoryBuffer>>& get_header_map() const
{
return static_cast<signature*>(reinterpret_cast<signature*>(f));
return m_headers;
}
const std::vector<std::string>& get_include_paths() const { return m_include_paths; }
private:
std::map<std::string, std::unique_ptr<llvm::MemoryBuffer>> m_headers;
std::vector<std::string> m_include_paths;
bool m_headers_valid;
};
// ----------------------------------------------------------------------------
// 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 <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
#include "ngraph/codegen/execution_engine.hpp"
using namespace ngraph;
codegen::ExecutionEngine::ExecutionEngine()
: m_execution_engine{nullptr}
{
}
codegen::ExecutionEngine::~ExecutionEngine()
{
}
bool codegen::ExecutionEngine::add_module(std::unique_ptr<llvm::Module>& module)
{
if (module)
{
if (!m_execution_engine)
{
m_execution_engine = llvm::EngineBuilder(move(module))
.setEngineKind(llvm::EngineKind::JIT)
.setOptLevel(llvm::CodeGenOpt::Aggressive)
.setErrorStr(&m_jit_error)
.create();
if (!m_execution_engine)
{
return false;
}
}
}
else
{
return false;
}
return true;
}
void codegen::ExecutionEngine::finalize()
{
if (m_execution_engine)
{
m_execution_engine->finalizeObject();
m_execution_engine->runStaticConstructorsDestructors(false);
}
else
{
throw std::runtime_error(
"Error in finalize: " +
(m_jit_error.empty() ? "Could not create an execution engine" : m_jit_error));
}
}
// ----------------------------------------------------------------------------
// 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 <llvm/ExecutionEngine/MCJIT.h> // forces JIT to link in
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
#include <llvm/Option/Arg.h>
namespace ngraph
{
namespace codegen
{
class ExecutionEngine;
}
}
class ngraph::codegen::ExecutionEngine
{
public:
ExecutionEngine();
~ExecutionEngine();
bool add_module(std::unique_ptr<llvm::Module>& module);
void finalize();
template <typename ftype>
std::function<ftype> find_function(const std::string& func_name)
{
auto f = m_execution_engine->getPointerToNamedFunction(func_name);
return f_cast<ftype>(f);
}
private:
llvm::ExecutionEngine* m_execution_engine;
std::string m_jit_error;
template <typename signature>
std::function<signature> f_cast(void* f)
{
return static_cast<signature*>(reinterpret_cast<signature*>(f));
}
};
/*
Copyright 2016 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
limitations under the License.
*/
// ----------------------------------------------------------------------------
// 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 <cassert>
#include <dirent.h>
......@@ -29,10 +28,37 @@
#include <unistd.h>
#include <vector>
#include "file_util.hpp"
#include "ngraph/file_util.hpp"
#include "ngraph/log.hpp"
using namespace std;
std::string ngraph::file_util::get_file_name(const std::string& s)
{
string rc = s;
auto pos = s.find_last_of('/');
if (pos != string::npos)
{
rc = s.substr(pos + 1);
}
return rc;
}
std::string ngraph::file_util::get_file_ext(const std::string& s)
{
string rc = get_file_name(s);
auto pos = rc.find_last_of('.');
if (pos != string::npos)
{
rc = rc.substr(pos);
}
else
{
rc = "";
}
return rc;
}
string ngraph::file_util::path_join(const string& s1, const string& s2)
{
string rc;
......@@ -79,20 +105,22 @@ size_t ngraph::file_util::get_file_size(const string& filename)
void ngraph::file_util::remove_directory(const string& dir)
{
struct stat status;
if (stat(dir.c_str(), &status) == -1)
if (stat(dir.c_str(), &status) != -1)
{
return;
iterate_files(dir,
[](const string& file, bool is_dir) {
if (is_dir)
{
rmdir(file.c_str());
}
else
{
remove(file.c_str());
}
},
true);
rmdir(dir.c_str());
}
file_util::iterate_files(dir,
[](const string& file, bool is_dir) {
if (is_dir)
rmdir(file.c_str());
else
remove(file.c_str());
},
true);
rmdir(dir.c_str());
}
void ngraph::file_util::remove_file(const string& file)
......@@ -117,7 +145,7 @@ bool ngraph::file_util::make_directory(const string& dir)
string ngraph::file_util::make_temp_directory(const string& path)
{
string fname = path.empty() ? file_util::get_temp_directory() : path;
string tmp_template = file_util::path_join(fname, "aeonXXXXXX");
string tmp_template = file_util::path_join(fname, "ngraph_XXXXXX");
char* tmpname = strdup(tmp_template.c_str());
mkdtemp(tmpname);
......@@ -129,7 +157,7 @@ string ngraph::file_util::make_temp_directory(const string& path)
std::string ngraph::file_util::get_temp_directory()
{
const vector<string> potential_tmps = {"NERVANA_AEON_TMP", "TMPDIR", "TMP", "TEMP", "TEMPDIR"};
const vector<string> potential_tmps = {"NGRAPH_TMP", "TMPDIR", "TMP", "TEMP", "TEMPDIR"};
const char* path = nullptr;
for (const string& var : potential_tmps)
......@@ -161,7 +189,7 @@ vector<char> ngraph::file_util::read_file_contents(const string& path)
char* p = data.data();
size_t remainder = file_size;
size_t offset = 0;
while (remainder > 0)
while (f && remainder > 0)
{
size_t rc = fread(&p[offset], 1, remainder, f);
offset += rc;
......@@ -197,12 +225,16 @@ void ngraph::file_util::iterate_files(const string& path,
else
files.push_back(file);
},
true);
recurse);
for (auto f : files)
{
func(f, false);
}
for (auto f : dirs)
{
func(f, true);
}
}
void ngraph::file_util::iterate_files_worker(
......@@ -218,18 +250,23 @@ void ngraph::file_util::iterate_files_worker(
switch (ent->d_type)
{
case DT_DIR:
if (recurse && name != "." && name != "..")
if (name != "." && name != "..")
{
string dir_path = file_util::path_join(path, name);
iterate_files(dir_path, func, recurse);
if (recurse)
{
iterate_files(dir_path, func, recurse);
}
func(dir_path, true);
}
break;
case DT_LNK: break;
case DT_REG:
name = file_util::path_join(path, name);
func(name, false);
{
string file_name = file_util::path_join(path, name);
func(file_name, false);
break;
}
default: break;
}
}
......
/*
Copyright 2016 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
limitations under the License.
*/
// ----------------------------------------------------------------------------
// 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
......@@ -27,6 +26,8 @@ namespace ngraph
class ngraph::file_util
{
public:
static std::string get_file_name(const std::string&);
static std::string get_file_ext(const std::string&);
static std::string path_join(const std::string& s1, const std::string& s2);
static size_t get_file_size(const std::string& filename);
static void remove_directory(const std::string& dir);
......
......@@ -14,8 +14,8 @@
#pragma once
#include <cinttypes>
#include <cstddef>
#include <cstdint>
// CBLAS types and wrappers
......
......@@ -16,7 +16,7 @@
#include <memory>
#include "ngraph/codegen/compiler.hpp"
#include "ngraph/codegen/execution_engine.hpp"
#include "ngraph/runtime/manager.hpp"
namespace ngraph
......@@ -33,7 +33,7 @@ namespace ngraph
class CPUManager : public Manager
{
protected:
ngraph::codegen::execution_state exec_state;
ngraph::codegen::ExecutionEngine exec_state;
public:
virtual std::shared_ptr<Backend> allocate_backend() override;
......
......@@ -89,7 +89,7 @@ namespace ngraph
};
}
// ET element type
// T element type
// FMT array format (fmt::V for vector, etc.)
// BASE select array/matrix
template <typename T,
......@@ -128,4 +128,4 @@ namespace ngraph
}
}
}
}
\ No newline at end of file
}
This diff is collapsed.
......@@ -94,6 +94,15 @@ namespace ngraph
void EMITTER_DECL(EmitAsin);
void EMITTER_DECL(EmitAcos);
void EMITTER_DECL(EmitAtan);
private:
void generate_call(const std::vector<TensorViewInfo>& inputs,
const std::vector<TensorViewInfo>& outputs,
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 = "");
};
}
}
......
......@@ -22,6 +22,7 @@
#include "ngraph/codegen/code_writer.hpp"
#include "ngraph/codegen/compiler.hpp"
#include "ngraph/codegen/execution_engine.hpp"
#include "ngraph/descriptor/input.hpp"
#include "ngraph/descriptor/layout/dense_tensor_view_layout.hpp"
#include "ngraph/descriptor/output.hpp"
......@@ -74,6 +75,7 @@
#include "ngraph/pass/memory_layout.hpp"
#include "ngraph/pass/topological_sort.hpp"
#include "ngraph/runtime/cpu/call_frame.hpp"
#include "ngraph/runtime/cpu/cpu_backend.hpp"
#include "ngraph/runtime/cpu/emitter.hpp"
#include "ngraph/runtime/cpu/external_function.hpp"
#include "ngraph/runtime/utils.hpp"
......@@ -81,26 +83,17 @@
using namespace std;
using namespace ngraph::runtime::cpu;
using ngraph::descriptor::layout::DenseTensorViewLayout;
static const std::string s_output_dir = "cpu_codegen";
extern "C" void
allocate_aligned_buffer(size_t size, size_t alignment, char** allocated, char** aligned_ptr)
class StaticInitializers
{
size_t allocation_size = size + alignment;
*allocated = static_cast<char*>(malloc(allocation_size));
*aligned_ptr = *allocated;
size_t mod = size_t(*aligned_ptr) % alignment;
public:
StaticInitializers() { ngraph::file_util::remove_directory(s_output_dir); }
};
if (mod != 0)
{
(*aligned_ptr) += (alignment - mod);
}
}
static StaticInitializers s_static_initializers;
extern "C" void free_aligned_buffer(void* allocated)
{
free(allocated);
}
using ngraph::descriptor::layout::DenseTensorViewLayout;
#define TI(x) type_index(typeid(x))
......@@ -192,37 +185,25 @@ void ExternalFunction::compile()
TU +=
R"(// Generated by the NGraph CPU backend
#include <algorithm>
#include <cmath>
#include <memory>
#include <vector>
#include <Eigen/Dense>
#include "ngraph/runtime/cpu/cpu_kernels.hpp"
#include "ngraph/runtime/cpu/eigen_utils.hpp"
#include "ngraph/runtime/cpu/memory_handler.hpp"
using namespace ngraph::runtime::cpu::eigen;
extern "C" void allocate_aligned_buffer(
size_t size,
size_t alignment,
char** allocated,
char** aligned_ptr);
extern "C" void free_aligned_buffer(void* allocated);
)";
TU << "// Declare any functions that are not main\n";
TU << "// Declare all functions\n";
for (shared_ptr<Function> f : pass_manager.get_state().get_functions())
{
if (f != m_function)
{
TU << "extern \"C\" void " << f->get_name() << "(\n";
TU << " const std::vector<void*>& inputs,\n";
TU << " const std::vector<void*>& outputs);\n";
}
TU << "extern \"C\" void " << f->get_name() << "(\n";
TU << " const std::vector<void*>& inputs,\n";
TU << " const std::vector<void*>& outputs);\n";
}
TU << "\n";
......@@ -232,27 +213,37 @@ extern "C" void free_aligned_buffer(void* allocated);
TU << " const std::vector<void*>& inputs,\n";
TU << " const std::vector<void*>& outputs)\n";
TU << "{\n";
TU.indent++;
TU << "// Allocate the memory pool\n";
size_t temp_pool_size = pass_manager.get_state().get_temporary_pool_size();
TU << "char* allocated_buffer_pool;\n";
TU << "char* aligned_buffer_pool;\n";
TU << "allocate_aligned_buffer(" << temp_pool_size << ", 64"
<< ", &allocated_buffer_pool, &aligned_buffer_pool);\n";
TU << "\n";
TU << "// Define temporary tensors\n";
bool temporaries_used = false;
for (shared_ptr<Node> node : current_function->get_ordered_ops())
{
for (descriptor::Tensor* tensor : node->liveness_new_list)
if (node->liveness_new_list.size() > 0)
{
TU << tensor->get_element_type() << "* " << tensor->get_name() << " = ("
<< tensor->get_element_type() << "*)(aligned_buffer_pool + "
<< tensor->get_pool_offset() << ");\n";
temporaries_used = true;
break;
}
}
TU << "\n";
if (temporaries_used)
{
size_t temp_pool_size = pass_manager.get_state().get_temporary_pool_size();
TU << "// Allocate the memory pool\n";
TU << "ngraph::runtime::cpu::MemoryHandler memory_handler(" << temp_pool_size << ", "
<< ngraph::runtime::cpu::alignment << ");\n";
TU << "\n";
TU << "// Define temporary tensors\n";
for (shared_ptr<Node> node : current_function->get_ordered_ops())
{
for (descriptor::Tensor* tensor : node->liveness_new_list)
{
TU << tensor->get_element_type() << "* " << tensor->get_name() << " = ("
<< tensor->get_element_type() << "*)(memory_handler.get_ptr("
<< tensor->get_pool_offset() << "));\n";
}
}
TU << "\n";
}
TU << "// Define inputs\n";
size_t arg_index = 0;
......@@ -283,13 +274,10 @@ extern "C" void free_aligned_buffer(void* allocated);
}
TU << "\n";
TU << "// Define tensor views\n";
TU << "\n";
for (shared_ptr<Node> node : current_function->get_ordered_ops())
{
auto& n = *node; // Work around a compiler warning (*node inside typeid may have effects
// with shared pointers, which is fine here but clang doesn't like it.)
// with shared pointers, which is fine here but clang doesn't like it.)
auto handler = dispatcher.find(type_index(typeid(n)));
if (handler == dispatcher.end())
{
......@@ -311,8 +299,6 @@ extern "C" void free_aligned_buffer(void* allocated);
handler->second(&emitter, node.get(), this, in, out);
}
TU << "\nfree_aligned_buffer(allocated_buffer_pool);\n";
TU.indent--;
// End TU
......@@ -321,34 +307,33 @@ extern "C" void free_aligned_buffer(void* allocated);
// TODO: Cleanup and make this a utility function
string output_dir = "cpu_codegen";
string function_name = m_function->get_name();
file_util::remove_directory(output_dir);
file_util::make_directory(output_dir);
string filename = file_util::path_join(output_dir, function_name + "_codegen.cpp");
file_util::make_directory(s_output_dir);
string filename = file_util::path_join(s_output_dir, function_name + "_codegen.cpp");
ofstream out(filename);
string code = TU.get_code();
out << code;
out.close();
ngraph::codegen::execution_state estate;
codegen::Compiler compiler;
codegen::ExecutionEngine execution_engine;
#if NGCPU_PCH
estate.set_precompiled_headers_enabled(true);
compiler.set_precompiled_headers_enabled(true);
#endif
#if NGCPU_DEBUGINFO
estate.set_debuginfo_enabled(true);
compiler.set_debuginfo_enabled(true);
#endif
auto llvm_module = estate.compile(code, function_name + "_codegen.cpp");
auto llvm_module = compiler.compile(code);
if (llvm_module == nullptr)
{
throw runtime_error("function failed to compile");
}
estate.add_module(llvm_module);
estate.finalize();
m_compiled_function = estate.find_function<EntryPoint_t>(function_name);
execution_engine.add_module(llvm_module);
execution_engine.finalize();
m_compiled_function = execution_engine.find_function<EntryPoint_t>(function_name);
assert(m_compiled_function);
m_is_compiled = true;
......
// ----------------------------------------------------------------------------
// 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/memory_handler.hpp"
using namespace ngraph;
runtime::cpu::MemoryHandler::MemoryHandler(size_t byte_size, size_t alignment)
: m_allocated_buffer_pool(nullptr)
, m_aligned_buffer_pool(nullptr)
{
if (byte_size > 0)
{
size_t allocation_size = byte_size + alignment;
m_allocated_buffer_pool = static_cast<char*>(malloc(allocation_size));
m_aligned_buffer_pool = m_allocated_buffer_pool;
size_t mod = size_t(m_aligned_buffer_pool) % alignment;
if (mod != 0)
{
m_aligned_buffer_pool += (alignment - mod);
}
}
}
runtime::cpu::MemoryHandler::~MemoryHandler()
{
if (m_allocated_buffer_pool != nullptr)
{
free(m_allocated_buffer_pool);
}
}
// ----------------------------------------------------------------------------
// 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 <cstddef>
#include <memory>
namespace ngraph
{
namespace runtime
{
namespace cpu
{
class MemoryHandler;
}
}
}
class ngraph::runtime::cpu::MemoryHandler
{
public:
MemoryHandler(size_t pool_size, size_t alignment);
~MemoryHandler();
void* get_ptr(size_t offset) const { return m_aligned_buffer_pool + offset; }
private:
char* m_allocated_buffer_pool;
char* m_aligned_buffer_pool;
};
......@@ -20,35 +20,47 @@
using namespace ngraph;
using namespace std;
extern "C" void
allocate_aligned_buffer(size_t size, size_t alignment, char** allocated, char** aligned_ptr);
extern "C" void free_aligned_buffer(void* allocated);
runtime::cpu::CPUTensorView::CPUTensorView(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", true, true))
, m_allocated_buffer_pool(nullptr)
, m_aligned_buffer_pool(nullptr)
{
m_descriptor->set_tensor_view_layout(
std::make_shared<ngraph::descriptor::layout::DenseTensorViewLayout>(*m_descriptor));
m_buffer_size = m_descriptor->get_tensor_view_layout()->get_size() * element_type.size();
allocate_aligned_buffer(m_buffer_size, runtime::cpu::alignment, &m_allocated, &m_buffer);
if (m_buffer_size > 0)
{
size_t allocation_size = m_buffer_size + runtime::cpu::alignment;
m_allocated_buffer_pool = static_cast<char*>(malloc(allocation_size));
m_aligned_buffer_pool = m_allocated_buffer_pool;
size_t mod = size_t(m_aligned_buffer_pool) % alignment;
if (mod != 0)
{
m_aligned_buffer_pool += (alignment - mod);
}
}
}
runtime::cpu::CPUTensorView::~CPUTensorView()
{
free_aligned_buffer(m_allocated);
if (m_allocated_buffer_pool != nullptr)
{
free(m_allocated_buffer_pool);
}
}
char* runtime::cpu::CPUTensorView::get_data_ptr()
{
return m_buffer;
return m_aligned_buffer_pool;
}
const char* runtime::cpu::CPUTensorView::get_data_ptr() const
{
return m_buffer;
return m_aligned_buffer_pool;
}
void runtime::cpu::CPUTensorView::write(const void* source, size_t tensor_offset, size_t n)
......
......@@ -52,7 +52,7 @@ public:
void read(void* p, size_t tensor_offset, size_t n) const override;
private:
char* m_allocated;
char* m_buffer;
char* m_allocated_buffer_pool;
char* m_aligned_buffer_pool;
size_t m_buffer_size;
};
......@@ -19,23 +19,26 @@
#include "gtest/gtest.h"
#include "ngraph/codegen/compiler.hpp"
#include "ngraph/codegen/execution_engine.hpp"
using namespace std;
using namespace ngraph;
TEST(codegen, simple_return)
{
constexpr auto name = "test.cpp";
constexpr auto source = R"(extern "C" int test() { return 2+5; })";
ngraph::codegen::execution_state estate;
auto module = estate.compile(source, name);
codegen::Compiler compiler;
codegen::ExecutionEngine execution_engine;
auto module = compiler.compile(source);
ASSERT_NE(nullptr, module);
estate.add_module(module);
execution_engine.add_module(module);
estate.finalize();
execution_engine.finalize();
auto func = estate.find_function<int()>("test");
auto func = execution_engine.find_function<int()>("test");
ASSERT_NE(nullptr, func);
int result = func();
......@@ -44,18 +47,19 @@ TEST(codegen, simple_return)
TEST(codegen, pass_args)
{
constexpr auto name = "test.cpp";
constexpr auto source = R"(extern "C" int test(int a, int b) { return a+b; })";
ngraph::codegen::execution_state estate;
auto module = estate.compile(source, name);
codegen::Compiler compiler;
codegen::ExecutionEngine execution_engine;
auto module = compiler.compile(source);
ASSERT_NE(nullptr, module);
estate.add_module(module);
execution_engine.add_module(module);
estate.finalize();
execution_engine.finalize();
auto func = estate.find_function<int(int, int)>("test");
auto func = execution_engine.find_function<int(int, int)>("test");
ASSERT_NE(nullptr, func);
int result = func(20, 22);
......@@ -64,7 +68,6 @@ TEST(codegen, pass_args)
TEST(codegen, include)
{
constexpr auto name = "test.cpp";
constexpr auto source =
R"(
#include <cmath>
......@@ -74,15 +77,17 @@ TEST(codegen, include)
}
)";
ngraph::codegen::execution_state estate;
auto module = estate.compile(source, name);
codegen::Compiler compiler;
codegen::ExecutionEngine execution_engine;
auto module = compiler.compile(source);
ASSERT_NE(nullptr, module);
estate.add_module(module);
execution_engine.add_module(module);
estate.finalize();
execution_engine.finalize();
auto func = estate.find_function<int(int, int)>("test");
auto func = execution_engine.find_function<int(int, int)>("test");
ASSERT_NE(nullptr, func);
int result = func(20, 2);
......
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