Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
N
ngraph
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
ngraph
Commits
0ef1c2f9
Unverified
Commit
0ef1c2f9
authored
Nov 16, 2017
by
Jai Menon
Committed by
GitHub
Nov 16, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #243 from NervanaSystems/bob/static_compiler
Bob/static compiler
parents
7b9b35d3
1ac8d820
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
460 additions
and
173 deletions
+460
-173
CMakeLists.txt
src/ngraph/CMakeLists.txt
+2
-0
compiler.cpp
src/ngraph/codegen/compiler.cpp
+0
-0
compiler.hpp
src/ngraph/codegen/compiler.hpp
+52
-26
execution_engine.cpp
src/ngraph/codegen/execution_engine.cpp
+70
-0
execution_engine.hpp
src/ngraph/codegen/execution_engine.hpp
+57
-0
file_util.cpp
src/ngraph/file_util.cpp
+72
-35
file_util.hpp
src/ngraph/file_util.hpp
+15
-14
cpu_kernels.hpp
src/ngraph/runtime/cpu/cpu_kernels.hpp
+1
-1
cpu_manager.hpp
src/ngraph/runtime/cpu/cpu_manager.hpp
+2
-2
eigen_utils.hpp
src/ngraph/runtime/cpu/eigen_utils.hpp
+2
-3
emitter.cpp
src/ngraph/runtime/cpu/emitter.cpp
+0
-0
emitter.hpp
src/ngraph/runtime/cpu/emitter.hpp
+9
-0
external_function.cpp
src/ngraph/runtime/cpu/external_function.cpp
+49
-64
memory_handler.cpp
src/ngraph/runtime/cpu/memory_handler.cpp
+43
-0
memory_handler.hpp
src/ngraph/runtime/cpu/memory_handler.hpp
+41
-0
tensor_view.cpp
src/ngraph/runtime/cpu/tensor_view.cpp
+20
-8
tensor_view.hpp
src/ngraph/runtime/cpu/tensor_view.hpp
+2
-2
codegen.cpp
test/codegen.cpp
+23
-18
No files found.
src/ngraph/CMakeLists.txt
View file @
0ef1c2f9
...
...
@@ -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
...
...
src/ngraph/codegen/compiler.cpp
View file @
0ef1c2f9
This diff is collapsed.
Click to expand it.
src/ngraph/codegen/compiler.hpp
View file @
0ef1c2f9
...
...
@@ -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
::
SectionMemoryManag
er
class
ngraph
::
codegen
::
Compil
er
{
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
;
};
src/ngraph/codegen/execution_engine.cpp
0 → 100644
View file @
0ef1c2f9
// ----------------------------------------------------------------------------
// 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
));
}
}
src/ngraph/codegen/execution_engine.hpp
0 → 100644
View file @
0ef1c2f9
// ----------------------------------------------------------------------------
// 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
));
}
};
src/ngraph/file_util.cpp
View file @
0ef1c2f9
/*
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
,
"
aeon
XXXXXX"
);
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
=
{
"N
ERVANA_AEON
_TMP"
,
"TMPDIR"
,
"TMP"
,
"TEMP"
,
"TEMPDIR"
};
const
vector
<
string
>
potential_tmps
=
{
"N
GRAPH
_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
);
},
tru
e
);
recurs
e
);
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
;
}
}
...
...
src/ngraph/file_util.hpp
View file @
0ef1c2f9
/*
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
);
...
...
src/ngraph/runtime/cpu/cpu_kernels.hpp
View file @
0ef1c2f9
...
...
@@ -14,8 +14,8 @@
#pragma once
#include <cinttypes>
#include <cstddef>
#include <cstdint>
// CBLAS types and wrappers
...
...
src/ngraph/runtime/cpu/cpu_manager.hpp
View file @
0ef1c2f9
...
...
@@ -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_stat
e
exec_state
;
ngraph
::
codegen
::
ExecutionEngin
e
exec_state
;
public
:
virtual
std
::
shared_ptr
<
Backend
>
allocate_backend
()
override
;
...
...
src/ngraph/runtime/cpu/eigen_utils.hpp
View file @
0ef1c2f9
...
...
@@ -89,7 +89,7 @@ namespace ngraph
};
}
//
E
T 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
}
src/ngraph/runtime/cpu/emitter.cpp
View file @
0ef1c2f9
This diff is collapsed.
Click to expand it.
src/ngraph/runtime/cpu/emitter.hpp
View file @
0ef1c2f9
...
...
@@ -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
=
""
);
};
}
}
...
...
src/ngraph/runtime/cpu/external_function.cpp
View file @
0ef1c2f9
...
...
@@ -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 a
ny functions that are not main
\n
"
;
TU
<<
"// Declare a
ll 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
<<
"
\n
free_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"
);
}
e
stat
e
.
add_module
(
llvm_module
);
e
stat
e
.
finalize
();
m_compiled_function
=
e
stat
e
.
find_function
<
EntryPoint_t
>
(
function_name
);
e
xecution_engin
e
.
add_module
(
llvm_module
);
e
xecution_engin
e
.
finalize
();
m_compiled_function
=
e
xecution_engin
e
.
find_function
<
EntryPoint_t
>
(
function_name
);
assert
(
m_compiled_function
);
m_is_compiled
=
true
;
...
...
src/ngraph/runtime/cpu/memory_handler.cpp
0 → 100644
View file @
0ef1c2f9
// ----------------------------------------------------------------------------
// 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
);
}
}
src/ngraph/runtime/cpu/memory_handler.hpp
0 → 100644
View file @
0ef1c2f9
// ----------------------------------------------------------------------------
// 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
;
};
src/ngraph/runtime/cpu/tensor_view.cpp
View file @
0ef1c2f9
...
...
@@ -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
)
...
...
src/ngraph/runtime/cpu/tensor_view.hpp
View file @
0ef1c2f9
...
...
@@ -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
;
};
test/codegen.cpp
View file @
0ef1c2f9
...
...
@@ -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
);
e
stat
e
.
add_module
(
module
);
e
xecution_engin
e
.
add_module
(
module
);
e
stat
e
.
finalize
();
e
xecution_engin
e
.
finalize
();
auto
func
=
e
stat
e
.
find_function
<
int
()
>
(
"test"
);
auto
func
=
e
xecution_engin
e
.
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
);
e
stat
e
.
add_module
(
module
);
e
xecution_engin
e
.
add_module
(
module
);
e
stat
e
.
finalize
();
e
xecution_engin
e
.
finalize
();
auto
func
=
e
stat
e
.
find_function
<
int
(
int
,
int
)
>
(
"test"
);
auto
func
=
e
xecution_engin
e
.
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
);
e
stat
e
.
add_module
(
module
);
e
xecution_engin
e
.
add_module
(
module
);
e
stat
e
.
finalize
();
e
xecution_engin
e
.
finalize
();
auto
func
=
e
stat
e
.
find_function
<
int
(
int
,
int
)
>
(
"test"
);
auto
func
=
e
xecution_engin
e
.
find_function
<
int
(
int
,
int
)
>
(
"test"
);
ASSERT_NE
(
nullptr
,
func
);
int
result
=
func
(
20
,
2
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment