Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
T
tic
Overview
Overview
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
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wenyuanbo
tic
Commits
2e0dbaa6
Commit
2e0dbaa6
authored
Oct 24, 2019
by
雾雨魔理沙
Committed by
Haichen Shen
Oct 24, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Relay] Fix memory leak in the interpreter (#4155)
* save lint * address reviewer comment
parent
b08fe810
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
59 additions
and
7 deletions
+59
-7
include/tvm/relay/interpreter.h
+26
-0
python/tvm/relay/backend/interpreter.py
+5
-0
src/relay/backend/interpreter.cc
+28
-7
No files found.
include/tvm/relay/interpreter.h
View file @
2e0dbaa6
...
...
@@ -119,6 +119,32 @@ class ClosureNode : public ValueNode {
RELAY_DEFINE_NODE_REF
(
Closure
,
ClosureNode
,
Value
);
/*! \brief A Relay Recursive Closure. A closure that has a name. */
class
RecClosure
;
/*! \brief The container type of RecClosure. */
class
RecClosureNode
:
public
ValueNode
{
public
:
/*! \brief The closure. */
Closure
clos
;
/*! \brief variable the closure bind to. */
Var
bind
;
RecClosureNode
()
{}
void
VisitAttrs
(
tvm
::
AttrVisitor
*
v
)
final
{
v
->
Visit
(
"clos"
,
&
clos
);
v
->
Visit
(
"bind"
,
&
bind
);
}
TVM_DLL
static
RecClosure
make
(
Closure
clos
,
Var
bind
);
static
constexpr
const
char
*
_type_key
=
"relay.RecClosure"
;
TVM_DECLARE_NODE_TYPE_INFO
(
RecClosureNode
,
ValueNode
);
};
RELAY_DEFINE_NODE_REF
(
RecClosure
,
RecClosureNode
,
Value
);
/*! \brief A tuple value. */
class
TupleValue
;
...
...
python/tvm/relay/backend/interpreter.py
View file @
2e0dbaa6
...
...
@@ -73,6 +73,11 @@ class Closure(Value):
@register_relay_node
class
RecClosure
(
Value
):
"""A recursive closure produced by the interpreter."""
@register_relay_node
class
ConstructorValue
(
Value
):
def
__init__
(
self
,
tag
,
fields
,
constructor
):
self
.
__init_handle_by_constructor__
(
...
...
src/relay/backend/interpreter.cc
View file @
2e0dbaa6
...
...
@@ -56,9 +56,27 @@ TVM_REGISTER_API("relay._make.Closure")
TVM_STATIC_IR_FUNCTOR_REGISTER
(
IRPrinter
,
vtable
)
.
set_dispatch
<
ClosureNode
>
([](
const
ClosureNode
*
node
,
tvm
::
IRPrinter
*
p
)
{
p
->
stream
<<
"ClosureNode("
<<
node
->
func
<<
")"
;
p
->
stream
<<
"ClosureNode("
<<
node
->
func
<<
"
, "
<<
node
->
env
<<
"
)"
;
});
// TODO(@jroesch): this doesn't support mutual letrec
/* Value Implementation */
RecClosure
RecClosureNode
::
make
(
Closure
clos
,
Var
bind
)
{
NodePtr
<
RecClosureNode
>
n
=
make_node
<
RecClosureNode
>
();
n
->
clos
=
std
::
move
(
clos
);
n
->
bind
=
std
::
move
(
bind
);
return
RecClosure
(
n
);
}
TVM_REGISTER_API
(
"relay._make.RecClosure"
)
.
set_body_typed
(
RecClosureNode
::
make
);
TVM_STATIC_IR_FUNCTOR_REGISTER
(
IRPrinter
,
vtable
)
.
set_dispatch
<
RecClosureNode
>
([](
const
RecClosureNode
*
node
,
tvm
::
IRPrinter
*
p
)
{
p
->
stream
<<
"RecClosureNode("
<<
node
->
clos
<<
")"
;
});
TupleValue
TupleValueNode
::
make
(
tvm
::
Array
<
Value
>
value
)
{
NodePtr
<
TupleValueNode
>
n
=
make_node
<
TupleValueNode
>
();
n
->
fields
=
value
;
...
...
@@ -281,7 +299,6 @@ class Interpreter :
return
TupleValueNode
::
make
(
values
);
}
// TODO(@jroesch): this doesn't support mutual letrec
inline
Value
MakeClosure
(
const
Function
&
func
,
Var
letrec_name
=
Var
())
{
tvm
::
Map
<
Var
,
Value
>
captured_mod
;
Array
<
Var
>
free_vars
=
FreeVars
(
func
);
...
...
@@ -298,10 +315,8 @@ class Interpreter :
// We must use mutation here to build a self referential closure.
auto
closure
=
ClosureNode
::
make
(
captured_mod
,
func
);
auto
mut_closure
=
static_cast
<
ClosureNode
*>
(
const_cast
<
Node
*>
(
closure
.
get
()));
if
(
letrec_name
.
defined
())
{
mut_closure
->
env
.
Set
(
letrec_name
,
closur
e
);
return
RecClosureNode
::
make
(
closure
,
letrec_nam
e
);
}
return
std
::
move
(
closure
);
}
...
...
@@ -559,7 +574,7 @@ class Interpreter :
}
// Invoke the closure
Value
Invoke
(
const
Closure
&
closure
,
const
tvm
::
Array
<
Value
>&
args
)
{
Value
Invoke
(
const
Closure
&
closure
,
const
tvm
::
Array
<
Value
>&
args
,
const
Var
&
bind
=
Var
()
)
{
// Get a reference to the function inside the closure.
if
(
closure
->
func
->
IsPrimitive
())
{
return
InvokePrimitiveOp
(
closure
->
func
,
args
);
...
...
@@ -575,12 +590,16 @@ class Interpreter :
locals
.
Set
(
func
->
params
[
i
],
args
[
i
]);
}
// Add the var to value mappings from the Closure's
mod
ironment.
// Add the var to value mappings from the Closure's
env
ironment.
for
(
auto
it
=
closure
->
env
.
begin
();
it
!=
closure
->
env
.
end
();
++
it
)
{
CHECK_EQ
(
locals
.
count
((
*
it
).
first
),
0
);
locals
.
Set
((
*
it
).
first
,
(
*
it
).
second
);
}
if
(
bind
.
defined
())
{
locals
.
Set
(
bind
,
RecClosureNode
::
make
(
closure
,
bind
));
}
return
WithFrame
<
Value
>
(
Frame
(
locals
),
[
&
]()
{
return
Eval
(
func
->
body
);
});
}
...
...
@@ -607,6 +626,8 @@ class Interpreter :
if
(
const
ClosureNode
*
closure_node
=
fn_val
.
as
<
ClosureNode
>
())
{
auto
closure
=
GetRef
<
Closure
>
(
closure_node
);
return
this
->
Invoke
(
closure
,
args
);
}
else
if
(
const
RecClosureNode
*
closure_node
=
fn_val
.
as
<
RecClosureNode
>
())
{
return
this
->
Invoke
(
closure_node
->
clos
,
args
,
closure_node
->
bind
);
}
else
{
LOG
(
FATAL
)
<<
"internal error: type error, expected function value in the call "
<<
"position"
;
...
...
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