Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
gaoqiong
MIGraphX
Commits
c0154dca
Commit
c0154dca
authored
May 16, 2019
by
Shucai Xiao
Browse files
merge changes from the develop branch
parents
ca170b5c
b93f5320
Changes
140
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
647 additions
and
473 deletions
+647
-473
src/include/migraphx/op/unary.hpp
src/include/migraphx/op/unary.hpp
+33
-12
src/include/migraphx/op/unsqueeze.hpp
src/include/migraphx/op/unsqueeze.hpp
+8
-4
src/include/migraphx/operation.hpp
src/include/migraphx/operation.hpp
+13
-11
src/include/migraphx/operators.hpp
src/include/migraphx/operators.hpp
+1
-0
src/include/migraphx/pass_manager.hpp
src/include/migraphx/pass_manager.hpp
+25
-0
src/include/migraphx/program.hpp
src/include/migraphx/program.hpp
+13
-1
src/include/migraphx/propagate_constant.hpp
src/include/migraphx/propagate_constant.hpp
+4
-4
src/include/migraphx/ranges.hpp
src/include/migraphx/ranges.hpp
+1
-1
src/include/migraphx/reflect.hpp
src/include/migraphx/reflect.hpp
+61
-6
src/include/migraphx/stringutils.hpp
src/include/migraphx/stringutils.hpp
+3
-2
src/instruction.cpp
src/instruction.cpp
+30
-8
src/onnx/cifar10.cpp
src/onnx/cifar10.cpp
+1
-1
src/onnx/onnx.cpp
src/onnx/onnx.cpp
+63
-32
src/opt/memory_coloring_impl.cpp
src/opt/memory_coloring_impl.cpp
+7
-16
src/opt/memory_coloring_impl.hpp
src/opt/memory_coloring_impl.hpp
+17
-17
src/pass_manager.cpp
src/pass_manager.cpp
+42
-0
src/program.cpp
src/program.cpp
+113
-32
src/propagate_constant.cpp
src/propagate_constant.cpp
+54
-0
src/rewrite_rnn.cpp
src/rewrite_rnn.cpp
+31
-19
src/targets/cpu/lowering.cpp
src/targets/cpu/lowering.cpp
+127
-307
No files found.
src/include/migraphx/op/unary.hpp
View file @
c0154dca
#ifndef MIGRAPHX_GUARD_OPERATORS_UNARY_HPP
#ifndef MIGRAPHX_GUARD_OPERATORS_UNARY_HPP
#define MIGRAPHX_GUARD_OPERATORS_UNARY_HPP
#define MIGRAPHX_GUARD_OPERATORS_UNARY_HPP
#include <array>
#include <migraphx/op/name.hpp>
#include <migraphx/operation.hpp>
#include <migraphx/check_shapes.hpp>
#include <migraphx/stringutils.hpp>
#include <migraphx/streamutils.hpp>
#include <migraphx/literal.hpp>
#include <migraphx/shape_for_each.hpp>
#include <migraphx/config.hpp>
#include <cmath>
#include <utility>
namespace
migraphx
{
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
inline
namespace
MIGRAPHX_INLINE_NS
{
namespace
op
{
namespace
op
{
struct
unary
template
<
class
Derived
>
struct
unary
:
op_name
<
Derived
>
{
{
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
{
check_shapes
{
inputs
}.
has
(
1
);
check_shapes
{
inputs
}.
has
(
1
);
return
inputs
.
at
(
0
);
auto
s
=
inputs
.
at
(
0
);
if
(
s
.
packed
())
{
return
s
;
}
else
{
return
{
s
.
type
(),
s
.
lens
()};
}
}
argument
compute
(
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
argument
result
{
output_shape
};
visit_all
(
result
,
args
[
0
])([
&
](
auto
output
,
auto
input
)
{
if
(
input
.
get_shape
().
standard
())
{
std
::
transform
(
input
.
begin
(),
input
.
end
(),
output
.
begin
(),
static_cast
<
const
Derived
&>
(
*
this
).
apply
());
}
else
{
shape_for_each
(
output
.
get_shape
(),
[
&
](
const
auto
&
idx
)
{
output
(
idx
.
begin
(),
idx
.
end
())
=
static_cast
<
const
Derived
&>
(
*
this
).
apply
()(
input
(
idx
.
begin
(),
idx
.
end
()));
});
}
});
return
result
;
}
}
};
};
...
...
src/include/migraphx/op/unsqueeze.hpp
View file @
c0154dca
...
@@ -29,9 +29,13 @@ struct unsqueeze
...
@@ -29,9 +29,13 @@ struct unsqueeze
std
::
string
name
()
const
{
return
"unsqueeze"
;
}
std
::
string
name
()
const
{
return
"unsqueeze"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
{
auto
input_shape
=
inputs
[
0
];
auto
input_shape
=
inputs
[
0
];
auto
type
=
input_shape
.
type
();
auto
type
=
input_shape
.
type
();
auto
old_lens
=
input_shape
.
lens
();
auto
old_lens
=
input_shape
.
lens
();
if
(
input_shape
.
scalar
())
return
shape
{
type
,
old_lens
};
std
::
size_t
new_size
=
old_lens
.
size
()
+
axes
.
size
();
std
::
size_t
new_size
=
old_lens
.
size
()
+
axes
.
size
();
std
::
vector
<
std
::
size_t
>
new_lens
(
new_size
);
std
::
vector
<
std
::
size_t
>
new_lens
(
new_size
);
std
::
size_t
p
=
0
;
std
::
size_t
p
=
0
;
...
@@ -52,7 +56,7 @@ struct unsqueeze
...
@@ -52,7 +56,7 @@ struct unsqueeze
{
{
return
{
std
::
move
(
output_shape
),
std
::
move
(
args
.
front
().
data
)};
return
{
std
::
move
(
output_shape
),
std
::
move
(
args
.
front
().
data
)};
}
}
in
t
output_alias
(
const
std
::
vector
<
shape
>&
)
const
{
return
0
;
}
std
::
ptrdiff_
t
output_alias
(
const
std
::
vector
<
shape
>&
)
const
{
return
0
;
}
};
};
}
// namespace op
}
// namespace op
...
...
src/include/migraphx/operation.hpp
View file @
c0154dca
...
@@ -49,7 +49,7 @@ struct operation
...
@@ -49,7 +49,7 @@ struct operation
argument
compute
(
context
&
ctx
,
const
shape
&
output
,
const
std
::
vector
<
argument
>&
input
)
const
;
argument
compute
(
context
&
ctx
,
const
shape
&
output
,
const
std
::
vector
<
argument
>&
input
)
const
;
/// An optional method to return which argument the output will alias. If
/// An optional method to return which argument the output will alias. If
/// there is no aliased output then -1 can be returned.
/// there is no aliased output then -1 can be returned.
in
t
output_alias
(
const
std
::
vector
<
shape
>&
input
)
const
;
std
::
ptrdiff_
t
output_alias
(
const
std
::
vector
<
shape
>&
input
)
const
;
/// An optional stream operator to print the operation. When this is not
/// An optional stream operator to print the operation. When this is not
/// implemented, it will just print the operation's name.
/// implemented, it will just print the operation's name.
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
operation
&
op
);
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
operation
&
op
);
...
@@ -69,7 +69,7 @@ auto operator<<(std::ostream& os, const T& x) -> decltype(os << x.name())
...
@@ -69,7 +69,7 @@ auto operator<<(std::ostream& os, const T& x) -> decltype(os << x.name())
{
{
os
<<
x
.
name
();
os
<<
x
.
name
();
char
delim
=
'['
;
char
delim
=
'['
;
reflect_each
(
x
,
[
&
](
auto
&
y
,
auto
name
)
{
reflect_each
(
x
,
[
&
](
auto
&
&
y
,
auto
name
)
{
os
<<
delim
;
os
<<
delim
;
os
<<
name
<<
"="
;
os
<<
name
<<
"="
;
stream_write_value
(
os
,
y
);
stream_write_value
(
os
,
y
);
...
@@ -87,6 +87,8 @@ namespace operation_equal {
...
@@ -87,6 +87,8 @@ namespace operation_equal {
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
auto
operator
==
(
const
T
&
x
,
const
U
&
y
)
->
decltype
(
x
.
name
()
==
y
.
name
())
auto
operator
==
(
const
T
&
x
,
const
U
&
y
)
->
decltype
(
x
.
name
()
==
y
.
name
())
{
{
static_assert
(
is_reflectable
<
T
>
{}
or
sizeof
(
T
)
<=
1
,
"Missing equality operator or reflect method."
);
if
(
x
.
name
()
!=
y
.
name
())
if
(
x
.
name
()
!=
y
.
name
())
return
false
;
return
false
;
const
auto
&
yy
=
any_cast
<
T
>
(
y
);
const
auto
&
yy
=
any_cast
<
T
>
(
y
);
...
@@ -175,7 +177,7 @@ auto is_context_free_op(const T& x) -> decltype(is_context_free_op(
...
@@ -175,7 +177,7 @@ auto is_context_free_op(const T& x) -> decltype(is_context_free_op(
}
}
template
<
class
T
>
template
<
class
T
>
in
t
output_alias_op
(
rank
<
0
>
,
const
T
&
,
const
std
::
vector
<
shape
>&
)
std
::
ptrdiff_
t
output_alias_op
(
rank
<
0
>
,
const
T
&
,
const
std
::
vector
<
shape
>&
)
{
{
return
-
1
;
return
-
1
;
}
}
...
@@ -188,7 +190,7 @@ auto output_alias_op(rank<1>, const T& x, const std::vector<shape>& shapes)
...
@@ -188,7 +190,7 @@ auto output_alias_op(rank<1>, const T& x, const std::vector<shape>& shapes)
}
}
template
<
class
T
>
template
<
class
T
>
in
t
output_alias_op
(
const
T
&
x
,
const
std
::
vector
<
shape
>&
shapes
)
std
::
ptrdiff_
t
output_alias_op
(
const
T
&
x
,
const
std
::
vector
<
shape
>&
shapes
)
{
{
return
output_alias_op
(
rank
<
1
>
{},
x
,
shapes
);
return
output_alias_op
(
rank
<
1
>
{},
x
,
shapes
);
}
}
...
@@ -239,7 +241,7 @@ auto has_finalize_op(const T&) -> decltype(has_finalize_op(rank<1>{},
...
@@ -239,7 +241,7 @@ auto has_finalize_op(const T&) -> decltype(has_finalize_op(rank<1>{},
* std::string name() const;
* std::string name() const;
* bool is_context_free() const;
* bool is_context_free() const;
* bool has_finalize() const;
* bool has_finalize() const;
*
in
t output_alias(const std::vector<shape>& input) const;
*
std::ptrdiff_
t output_alias(const std::vector<shape>& input) const;
* void finalize(context& ctx,const shape& output,const std::vector<shape>& input) ;
* void finalize(context& ctx,const shape& output,const std::vector<shape>& input) ;
* shape compute_shape(const std::vector<shape>& input) const;
* shape compute_shape(const std::vector<shape>& input) const;
* argument compute(context& ctx,const shape& output,const std::vector<argument>& input) const;
* argument compute(context& ctx,const shape& output,const std::vector<argument>& input) const;
...
@@ -325,7 +327,7 @@ struct operation
...
@@ -325,7 +327,7 @@ struct operation
return
(
*
this
).
private_detail_te_get_handle
().
has_finalize
();
return
(
*
this
).
private_detail_te_get_handle
().
has_finalize
();
}
}
in
t
output_alias
(
const
std
::
vector
<
shape
>&
input
)
const
std
::
ptrdiff_
t
output_alias
(
const
std
::
vector
<
shape
>&
input
)
const
{
{
assert
((
*
this
).
private_detail_te_handle_mem_var
);
assert
((
*
this
).
private_detail_te_handle_mem_var
);
return
(
*
this
).
private_detail_te_get_handle
().
output_alias
(
input
);
return
(
*
this
).
private_detail_te_get_handle
().
output_alias
(
input
);
...
@@ -380,10 +382,10 @@ struct operation
...
@@ -380,10 +382,10 @@ struct operation
virtual
std
::
shared_ptr
<
private_detail_te_handle_base_type
>
clone
()
const
=
0
;
virtual
std
::
shared_ptr
<
private_detail_te_handle_base_type
>
clone
()
const
=
0
;
virtual
const
std
::
type_info
&
type
()
const
=
0
;
virtual
const
std
::
type_info
&
type
()
const
=
0
;
virtual
std
::
string
name
()
const
=
0
;
virtual
std
::
string
name
()
const
=
0
;
virtual
bool
is_context_free
()
const
=
0
;
virtual
bool
is_context_free
()
const
=
0
;
virtual
bool
has_finalize
()
const
=
0
;
virtual
bool
has_finalize
()
const
=
0
;
virtual
in
t
output_alias
(
const
std
::
vector
<
shape
>&
input
)
const
=
0
;
virtual
std
::
ptrdiff_
t
output_alias
(
const
std
::
vector
<
shape
>&
input
)
const
=
0
;
virtual
void
virtual
void
finalize
(
context
&
ctx
,
const
shape
&
output
,
const
std
::
vector
<
shape
>&
input
)
=
0
;
finalize
(
context
&
ctx
,
const
shape
&
output
,
const
std
::
vector
<
shape
>&
input
)
=
0
;
virtual
shape
compute_shape
(
const
std
::
vector
<
shape
>&
input
)
const
=
0
;
virtual
shape
compute_shape
(
const
std
::
vector
<
shape
>&
input
)
const
=
0
;
...
@@ -432,7 +434,7 @@ struct operation
...
@@ -432,7 +434,7 @@ struct operation
bool
has_finalize
()
const
override
{
return
has_finalize_op
(
private_detail_te_value
);
}
bool
has_finalize
()
const
override
{
return
has_finalize_op
(
private_detail_te_value
);
}
in
t
output_alias
(
const
std
::
vector
<
shape
>&
input
)
const
override
std
::
ptrdiff_
t
output_alias
(
const
std
::
vector
<
shape
>&
input
)
const
override
{
{
return
output_alias_op
(
private_detail_te_value
,
input
);
return
output_alias_op
(
private_detail_te_value
,
input
);
...
...
src/include/migraphx/operators.hpp
View file @
c0154dca
...
@@ -12,6 +12,7 @@
...
@@ -12,6 +12,7 @@
#include <migraphx/op/binary.hpp>
#include <migraphx/op/binary.hpp>
#include <migraphx/op/broadcast.hpp>
#include <migraphx/op/broadcast.hpp>
#include <migraphx/op/capture.hpp>
#include <migraphx/op/capture.hpp>
#include <migraphx/op/clip.hpp>
#include <migraphx/op/common.hpp>
#include <migraphx/op/common.hpp>
#include <migraphx/op/concat.hpp>
#include <migraphx/op/concat.hpp>
#include <migraphx/op/contiguous.hpp>
#include <migraphx/op/contiguous.hpp>
...
...
src/include/migraphx/pass_manager.hpp
0 → 100644
View file @
c0154dca
#ifndef MIGRAPHX_GUARD_MIGRAPHLIB_PASS_MANAGER_HPP
#define MIGRAPHX_GUARD_MIGRAPHLIB_PASS_MANAGER_HPP
#include <list>
#include <unordered_map>
#include <migraphx/operation.hpp>
#include <migraphx/literal.hpp>
#include <migraphx/builtin.hpp>
#include <migraphx/instruction_ref.hpp>
#include <migraphx/target.hpp>
#include <migraphx/tracer.hpp>
#include <migraphx/env.hpp>
#include <migraphx/config.hpp>
#include <algorithm>
#include <iostream>
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
void
run_passes
(
program
&
prog
,
const
std
::
vector
<
pass
>&
passes
,
tracer
trace
=
tracer
{});
}
// namespace MIGRAPHX_INLINE_NS
}
// namespace migraphx
#endif
src/include/migraphx/program.hpp
View file @
c0154dca
...
@@ -30,8 +30,16 @@ const operation& get_operation(instruction_ref ins);
...
@@ -30,8 +30,16 @@ const operation& get_operation(instruction_ref ins);
struct
program
struct
program
{
{
program
();
program
();
// move constructor
program
(
program
&&
)
noexcept
;
program
(
program
&&
)
noexcept
;
program
&
operator
=
(
program
&&
)
noexcept
;
// copy constructor
program
(
const
program
&
);
// copy assignment operator
program
&
operator
=
(
program
);
~
program
()
noexcept
;
~
program
()
noexcept
;
using
parameter_map
=
std
::
unordered_map
<
std
::
string
,
argument
>
;
using
parameter_map
=
std
::
unordered_map
<
std
::
string
,
argument
>
;
...
@@ -108,6 +116,7 @@ struct program
...
@@ -108,6 +116,7 @@ struct program
void
debug_print
()
const
;
void
debug_print
()
const
;
void
debug_print
(
instruction_ref
ins
)
const
;
void
debug_print
(
instruction_ref
ins
)
const
;
void
debug_print
(
const
std
::
vector
<
instruction_ref
>&
inss
)
const
;
void
debug_print
(
const
std
::
vector
<
instruction_ref
>&
inss
)
const
;
void
print_graph
(
std
::
ostream
&
os
)
const
;
void
dry_run
(
parameter_map
params
)
const
;
void
dry_run
(
parameter_map
params
)
const
;
...
@@ -117,6 +126,9 @@ struct program
...
@@ -117,6 +126,9 @@ struct program
friend
bool
operator
==
(
const
program
&
x
,
const
program
&
y
);
friend
bool
operator
==
(
const
program
&
x
,
const
program
&
y
);
friend
bool
operator
!=
(
const
program
&
x
,
const
program
&
y
)
{
return
!
(
x
==
y
);
}
friend
bool
operator
!=
(
const
program
&
x
,
const
program
&
y
)
{
return
!
(
x
==
y
);
}
private:
void
assign
(
const
program
&
p
);
private:
private:
std
::
unique_ptr
<
program_impl
>
impl
;
std
::
unique_ptr
<
program_impl
>
impl
;
};
};
...
...
src/include/migraphx/
constant_
propagate.hpp
→
src/include/migraphx/propagate
_constant
.hpp
View file @
c0154dca
#ifndef MIGRAPHX_GUARD_RTGLIB_
CONSTANT_
PROPAGATE_HPP
#ifndef MIGRAPHX_GUARD_RTGLIB_PROPAGATE
_CONSTANT
_HPP
#define MIGRAPHX_GUARD_RTGLIB_
CONSTANT_
PROPAGATE_HPP
#define MIGRAPHX_GUARD_RTGLIB_PROPAGATE
_CONSTANT
_HPP
#include <string>
#include <string>
#include <migraphx/config.hpp>
#include <migraphx/config.hpp>
...
@@ -12,9 +12,9 @@ struct program;
...
@@ -12,9 +12,9 @@ struct program;
/**
/**
* Replace instructions which take all literals with a literal of the computation.
* Replace instructions which take all literals with a literal of the computation.
*/
*/
struct
constant_
propagate
struct
propagate
_constant
{
{
std
::
string
name
()
const
{
return
"
constant_
propagate"
;
}
std
::
string
name
()
const
{
return
"propagate
_constant
"
;
}
void
apply
(
program
&
p
)
const
;
void
apply
(
program
&
p
)
const
;
};
};
...
...
src/include/migraphx/ranges.hpp
View file @
c0154dca
...
@@ -12,7 +12,7 @@ inline namespace MIGRAPHX_INLINE_NS {
...
@@ -12,7 +12,7 @@ inline namespace MIGRAPHX_INLINE_NS {
namespace
detail
{
namespace
detail
{
template
<
class
String
,
class
T
>
template
<
class
String
,
class
T
>
auto
generic_find_impl
(
rank
<
2
>
,
String
&&
s
,
const
T
&
x
)
->
decltype
(
s
.
begin
()
+
s
.
find
(
x
)
,
s
.
npos
)
auto
generic_find_impl
(
rank
<
2
>
,
String
&&
s
,
const
T
&
x
)
->
decltype
(
s
.
npos
,
s
.
begin
()
+
s
.
find
(
x
))
{
{
auto
index
=
s
.
find
(
x
);
auto
index
=
s
.
find
(
x
);
if
(
index
==
s
.
npos
)
if
(
index
==
s
.
npos
)
...
...
src/include/migraphx/reflect.hpp
View file @
c0154dca
...
@@ -11,6 +11,15 @@ inline namespace MIGRAPHX_INLINE_NS {
...
@@ -11,6 +11,15 @@ inline namespace MIGRAPHX_INLINE_NS {
namespace
detail
{
namespace
detail
{
struct
reflect_placeholder
{
template
<
class
...
Ts
>
int
operator
()(
Ts
&&
...)
const
{
return
0
;
}
};
template
<
class
T
,
class
Selector
>
template
<
class
T
,
class
Selector
>
auto
reflect_impl
(
rank
<
1
>
,
T
&
x
,
Selector
f
)
->
decltype
(
T
::
reflect
(
x
,
f
))
auto
reflect_impl
(
rank
<
1
>
,
T
&
x
,
Selector
f
)
->
decltype
(
T
::
reflect
(
x
,
f
))
{
{
...
@@ -23,8 +32,53 @@ auto reflect_impl(rank<0>, T&, Selector)
...
@@ -23,8 +32,53 @@ auto reflect_impl(rank<0>, T&, Selector)
return
pack
();
return
pack
();
}
}
template
<
class
T
>
auto
reflectable_impl
(
rank
<
1
>
,
T
&&
x
)
->
decltype
(
T
::
reflect
(
x
,
reflect_placeholder
{}),
std
::
true_type
{});
template
<
class
T
>
auto
reflectable_impl
(
rank
<
0
>
,
T
&&
)
->
decltype
(
std
::
false_type
{});
template
<
class
T
>
struct
remove_rvalue_reference
{
using
type
=
T
;
};
template
<
class
T
>
struct
remove_rvalue_reference
<
T
&&>
{
using
type
=
T
;
};
template
<
class
T
>
struct
wrapper
{
using
type
=
typename
remove_rvalue_reference
<
T
>::
type
;
type
data
;
type
get
()
const
{
return
data
;
}
};
template
<
class
T
>
wrapper
<
T
>
wrap
(
std
::
remove_reference_t
<
T
>&
x
)
{
return
wrapper
<
T
>
{
std
::
forward
<
T
>
(
x
)};
}
template
<
class
...
Ts
>
using
auto_tuple_t
=
std
::
tuple
<
typename
remove_rvalue_reference
<
Ts
>::
type
...
>
;
template
<
class
...
Ts
>
auto_tuple_t
<
Ts
...
>
auto_tuple
(
Ts
&&
...
xs
)
{
return
auto_tuple_t
<
Ts
...
>
{
std
::
forward
<
Ts
>
(
xs
)...};
}
}
// namespace detail
}
// namespace detail
template
<
class
T
>
using
is_reflectable
=
decltype
(
detail
::
reflectable_impl
(
rank
<
1
>
{},
std
::
declval
<
T
>
()));
template
<
class
T
,
class
Selector
>
template
<
class
T
,
class
Selector
>
auto
reflect
(
T
&
x
,
Selector
f
)
auto
reflect
(
T
&
x
,
Selector
f
)
{
{
...
@@ -34,17 +88,18 @@ auto reflect(T& x, Selector f)
...
@@ -34,17 +88,18 @@ auto reflect(T& x, Selector f)
template
<
class
T
>
template
<
class
T
>
auto
reflect_tie
(
T
&
x
)
auto
reflect_tie
(
T
&
x
)
{
{
return
reflect
(
x
,
[](
auto
&&
y
,
auto
&&
...)
{
return
std
::
ref
(
y
);
})(
return
reflect
(
x
,
[](
auto
&&
y
,
auto
&&
...)
{
return
detail
::
wrap
<
decltype
(
y
)
>
(
y
);
})(
[](
auto
&&
...
xs
)
{
return
std
::
ti
e
(
xs
.
get
()...);
});
[](
auto
&&
...
xs
)
{
return
detail
::
auto_tupl
e
(
xs
.
get
()...);
});
}
}
template
<
class
T
,
class
F
>
template
<
class
T
,
class
F
>
void
reflect_each
(
T
&
x
,
F
f
)
void
reflect_each
(
T
&
x
,
F
f
)
{
{
return
reflect
(
x
,
[](
auto
&&
y
,
auto
...
ys
)
{
return
pack
(
std
::
ref
(
y
),
ys
...);
})(
return
reflect
(
x
,
[](
auto
&&
y
,
auto
...
ys
)
{
[
&
](
auto
&&
...
xs
)
{
return
pack
(
detail
::
wrap
<
decltype
(
y
)
>
(
y
),
ys
...);
each_args
([
&
](
auto
p
)
{
p
([
&
](
auto
&&
y
,
auto
...
ys
)
{
f
(
y
.
get
(),
ys
...);
});
},
xs
...);
})([
&
](
auto
&&
...
xs
)
{
});
each_args
([
&
](
auto
p
)
{
p
([
&
](
auto
&&
y
,
auto
...
ys
)
{
f
(
y
.
get
(),
ys
...);
});
},
xs
...);
});
}
}
}
// namespace MIGRAPHX_INLINE_NS
}
// namespace MIGRAPHX_INLINE_NS
...
...
src/include/migraphx/stringutils.hpp
View file @
c0154dca
...
@@ -38,8 +38,9 @@ inline std::string join_strings(Strings strings, const std::string& delim)
...
@@ -38,8 +38,9 @@ inline std::string join_strings(Strings strings, const std::string& delim)
return
""
;
return
""
;
auto
nit
=
std
::
next
(
it
);
auto
nit
=
std
::
next
(
it
);
return
std
::
accumulate
(
return
std
::
accumulate
(
nit
,
strings
.
end
(),
*
it
,
[
&
](
std
::
string
x
,
std
::
string
y
)
{
nit
,
strings
.
end
(),
*
it
,
[
&
](
std
::
string
x
,
std
::
string
y
)
{
return
x
+
delim
+
y
;
});
return
std
::
move
(
x
)
+
delim
+
std
::
move
(
y
);
});
}
}
template
<
class
F
>
template
<
class
F
>
...
...
src/instruction.cpp
View file @
c0154dca
...
@@ -28,6 +28,12 @@ void instruction::replace(const shape& r)
...
@@ -28,6 +28,12 @@ void instruction::replace(const shape& r)
}
}
}
}
void
instruction
::
replace
(
operation
o
)
{
op
=
std
::
move
(
o
);
recompute_shape
();
}
void
instruction
::
recompute_shape
()
{
replace
(
compute_shape
(
op
,
arguments
));
}
void
instruction
::
recompute_shape
()
{
replace
(
compute_shape
(
op
,
arguments
));
}
void
instruction
::
clear_arguments
()
void
instruction
::
clear_arguments
()
...
@@ -162,7 +168,24 @@ void instruction::replace_argument(instruction_ref old, instruction_ref new_ins)
...
@@ -162,7 +168,24 @@ void instruction::replace_argument(instruction_ref old, instruction_ref new_ins)
old
->
remove_output
(
*
this
);
old
->
remove_output
(
*
this
);
}
}
argument
instruction
::
eval
()
const
bool
instruction
::
can_eval
()
const
{
if
(
op
.
name
()
==
"@literal"
)
{
return
true
;
}
else
if
(
is_context_free
(
op
))
{
return
std
::
all_of
(
this
->
inputs
().
begin
(),
this
->
inputs
().
end
(),
[](
auto
arg
)
{
return
arg
->
can_eval
();
});
}
else
{
return
false
;
}
}
argument
instruction
::
eval
(
bool
check_eval
)
const
{
{
if
(
op
.
name
()
==
"@literal"
)
if
(
op
.
name
()
==
"@literal"
)
{
{
...
@@ -170,14 +193,13 @@ argument instruction::eval() const
...
@@ -170,14 +193,13 @@ argument instruction::eval() const
}
}
if
(
is_context_free
(
op
))
if
(
is_context_free
(
op
))
{
{
if
(
check_eval
and
not
this
->
can_eval
())
return
{};
std
::
vector
<
argument
>
args
;
std
::
vector
<
argument
>
args
;
for
(
auto
&&
arg
:
this
->
inputs
())
std
::
transform
(
this
->
inputs
().
begin
(),
{
this
->
inputs
().
end
(),
argument
a
=
arg
->
eval
();
std
::
back_inserter
(
args
),
if
(
a
.
empty
())
[](
auto
arg
)
{
return
arg
->
eval
(
false
);
});
return
{};
args
.
push_back
(
a
);
}
return
op
.
compute
(
result
,
args
);
return
op
.
compute
(
result
,
args
);
}
}
return
{};
return
{};
...
...
src/onnx/cifar10.cpp
View file @
c0154dca
...
@@ -32,7 +32,7 @@ auto read_cifar10_images(const std::string& full_path)
...
@@ -32,7 +32,7 @@ auto read_cifar10_images(const std::string& full_path)
labels
[
i
]
=
*
pimage
++
;
labels
[
i
]
=
*
pimage
++
;
for
(
size_t
j
=
0
;
j
<
nbytes_per_image
;
j
++
)
for
(
size_t
j
=
0
;
j
<
nbytes_per_image
;
j
++
)
{
{
float
v
=
*
(
pimage
+
j
)
/
255.0
f
;
float
v
=
float
(
*
(
pimage
+
j
)
)
/
255.0
f
;
data
[
i
*
nbytes_per_image
+
j
]
=
v
;
data
[
i
*
nbytes_per_image
+
j
]
=
v
;
}
}
}
}
...
...
src/onnx/onnx.cpp
View file @
c0154dca
...
@@ -63,6 +63,7 @@ struct onnx_parser
...
@@ -63,6 +63,7 @@ struct onnx_parser
add_variadic_op
(
"Max"
,
op
::
max
{});
add_variadic_op
(
"Max"
,
op
::
max
{});
add_variadic_op
(
"Min"
,
op
::
min
{});
add_variadic_op
(
"Min"
,
op
::
min
{});
add_mem_op
(
"Clip"
,
&
onnx_parser
::
parse_clip
);
add_mem_op
(
"LRN"
,
&
onnx_parser
::
parse_lrn
);
add_mem_op
(
"LRN"
,
&
onnx_parser
::
parse_lrn
);
add_mem_op
(
"ImageScaler"
,
&
onnx_parser
::
parse_imagescaler
);
add_mem_op
(
"ImageScaler"
,
&
onnx_parser
::
parse_imagescaler
);
add_mem_op
(
"LeakyRelu"
,
&
onnx_parser
::
parse_leaky_relu
);
add_mem_op
(
"LeakyRelu"
,
&
onnx_parser
::
parse_leaky_relu
);
...
@@ -141,8 +142,8 @@ struct onnx_parser
...
@@ -141,8 +142,8 @@ struct onnx_parser
if
(
broadcasted
!=
0
)
if
(
broadcasted
!=
0
)
{
{
uint64_t
axis
=
parse_value
(
attributes
.
at
(
"axis"
)).
at
<
uint64_t
>
();
uint64_t
axis
=
parse_value
(
attributes
.
at
(
"axis"
)).
at
<
uint64_t
>
();
auto
l
=
auto
l
=
prog
.
add_instruction
(
op
::
broadcast
{
axis
,
args
[
0
]
->
get_shape
().
lens
()},
prog
.
add_instruction
(
op
::
broadcast
{
axis
,
args
[
0
]
->
get_shape
()},
args
[
1
]);
args
[
1
]);
return
prog
.
add_instruction
(
x
,
args
[
0
],
l
);
return
prog
.
add_instruction
(
x
,
args
[
0
],
l
);
}
}
return
prog
.
add_instruction
(
x
,
args
);
return
prog
.
add_instruction
(
x
,
args
);
...
@@ -207,7 +208,7 @@ struct onnx_parser
...
@@ -207,7 +208,7 @@ struct onnx_parser
template
<
class
T
>
template
<
class
T
>
void
add_generic_op
(
std
::
string
name
,
T
x
)
void
add_generic_op
(
std
::
string
name
,
T
x
)
{
{
add_op
(
name
,
[
this
,
x
](
attribute_map
,
std
::
vector
<
instruction_ref
>
args
)
{
add_op
(
name
,
[
this
,
x
](
const
attribute_map
&
,
std
::
vector
<
instruction_ref
>
args
)
{
return
prog
.
add_instruction
(
x
,
args
);
return
prog
.
add_instruction
(
x
,
args
);
});
});
}
}
...
@@ -215,7 +216,7 @@ struct onnx_parser
...
@@ -215,7 +216,7 @@ struct onnx_parser
template
<
class
T
>
template
<
class
T
>
void
add_variadic_op
(
std
::
string
name
,
T
x
)
void
add_variadic_op
(
std
::
string
name
,
T
x
)
{
{
add_op
(
name
,
[
this
,
x
](
attribute_map
,
std
::
vector
<
instruction_ref
>
args
)
{
add_op
(
name
,
[
this
,
x
](
const
attribute_map
&
,
std
::
vector
<
instruction_ref
>
args
)
{
return
std
::
accumulate
(
std
::
next
(
args
.
begin
()),
return
std
::
accumulate
(
std
::
next
(
args
.
begin
()),
args
.
end
(),
args
.
end
(),
args
.
front
(),
args
.
front
(),
...
@@ -225,6 +226,22 @@ struct onnx_parser
...
@@ -225,6 +226,22 @@ struct onnx_parser
});
});
}
}
instruction_ref
parse_clip
(
const
std
::
string
&
,
const
attribute_map
&
attributes
,
std
::
vector
<
instruction_ref
>
args
)
{
op
::
clip
op
;
if
(
contains
(
attributes
,
"max"
))
{
op
.
max_val
=
parse_value
(
attributes
.
at
(
"max"
)).
at
<
float
>
();
}
if
(
contains
(
attributes
,
"min"
))
{
op
.
min_val
=
parse_value
(
attributes
.
at
(
"min"
)).
at
<
float
>
();
}
return
prog
.
add_instruction
(
op
,
std
::
move
(
args
));
}
instruction_ref
instruction_ref
parse_softmax
(
const
std
::
string
&
,
const
attribute_map
&
,
std
::
vector
<
instruction_ref
>
args
)
parse_softmax
(
const
std
::
string
&
,
const
attribute_map
&
,
std
::
vector
<
instruction_ref
>
args
)
{
{
...
@@ -306,7 +323,7 @@ struct onnx_parser
...
@@ -306,7 +323,7 @@ struct onnx_parser
{
{
uint64_t
axis
=
1
;
uint64_t
axis
=
1
;
auto
l1
=
prog
.
add_instruction
(
op
,
args
[
0
],
args
[
1
]);
auto
l1
=
prog
.
add_instruction
(
op
,
args
[
0
],
args
[
1
]);
auto
l2
=
prog
.
add_instruction
(
op
::
broadcast
{
axis
,
l1
->
get_shape
()},
args
[
2
]);
auto
l2
=
prog
.
add_instruction
(
op
::
broadcast
{
axis
,
l1
->
get_shape
()
.
lens
()
},
args
[
2
]);
return
prog
.
add_instruction
(
op
::
add
{},
l1
,
l2
);
return
prog
.
add_instruction
(
op
::
add
{},
l1
,
l2
);
}
}
return
prog
.
add_instruction
(
op
,
l0
,
args
[
1
]);
return
prog
.
add_instruction
(
op
,
l0
,
args
[
1
]);
...
@@ -671,15 +688,15 @@ struct onnx_parser
...
@@ -671,15 +688,15 @@ struct onnx_parser
auto
&&
bias_floats
=
attributes
[
"bias"
].
floats
();
auto
&&
bias_floats
=
attributes
[
"bias"
].
floats
();
bias
=
std
::
vector
<
float
>
(
bias_floats
.
begin
(),
bias_floats
.
end
());
bias
=
std
::
vector
<
float
>
(
bias_floats
.
begin
(),
bias_floats
.
end
());
}
}
auto
input_
shape
=
args
.
front
()
->
get_shape
();
auto
input_
lens
=
args
.
front
()
->
get_shape
()
.
lens
()
;
auto
scale_val
=
prog
.
add_literal
(
scale
);
auto
scale_val
=
prog
.
add_literal
(
scale
);
auto
bias_vals
=
prog
.
add_literal
(
auto
bias_vals
=
prog
.
add_literal
(
migraphx
::
literal
{
migraphx
::
shape
{
migraphx
::
shape
::
float_type
,
{
bias
.
size
()}},
bias
});
migraphx
::
literal
{
migraphx
::
shape
{
migraphx
::
shape
::
float_type
,
{
bias
.
size
()}},
bias
});
auto
scale_tensor
=
prog
.
add_instruction
(
migraphx
::
op
::
scalar
{
input_
shape
},
scale_val
);
auto
scale_tensor
=
prog
.
add_instruction
(
migraphx
::
op
::
scalar
{
input_
lens
},
scale_val
);
auto
img_scaled
=
prog
.
add_instruction
(
migraphx
::
op
::
mul
{},
args
.
front
(),
scale_tensor
);
auto
img_scaled
=
prog
.
add_instruction
(
migraphx
::
op
::
mul
{},
args
.
front
(),
scale_tensor
);
auto
bias_bcast
=
prog
.
add_instruction
(
migraphx
::
op
::
broadcast
{
1
,
input_
shape
},
bias_vals
);
auto
bias_bcast
=
prog
.
add_instruction
(
migraphx
::
op
::
broadcast
{
1
,
input_
lens
},
bias_vals
);
return
prog
.
add_instruction
(
migraphx
::
op
::
add
{},
img_scaled
,
bias_bcast
);
return
prog
.
add_instruction
(
migraphx
::
op
::
add
{},
img_scaled
,
bias_bcast
);
}
}
...
@@ -1361,28 +1378,26 @@ struct onnx_parser
...
@@ -1361,28 +1378,26 @@ struct onnx_parser
static
literal
parse_tensor
(
const
onnx
::
TensorProto
&
t
)
static
literal
parse_tensor
(
const
onnx
::
TensorProto
&
t
)
{
{
std
::
vector
<
std
::
size_t
>
dims
(
t
.
dims
().
begin
(),
t
.
dims
().
end
());
std
::
vector
<
std
::
size_t
>
dims
(
t
.
dims
().
begin
(),
t
.
dims
().
end
());
// in case of scalar constants in onnx file, use dims=1 to fill initializer data
if
(
dims
.
empty
())
{
dims
=
{
1
};
}
if
(
t
.
has_raw_data
())
if
(
t
.
has_raw_data
())
{
{
const
std
::
string
&
s
=
t
.
raw_data
();
const
std
::
string
&
s
=
t
.
raw_data
();
switch
(
t
.
data_type
())
switch
(
t
.
data_type
())
{
{
case
onnx
::
TensorProto
::
UNDEFINED
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
UNDEFINED
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
FLOAT
:
return
literal
{{
shape
::
float_type
,
dims
}
,
s
.
data
()
}
;
case
onnx
::
TensorProto
::
FLOAT
:
return
create_
literal
(
shape
::
float_type
,
dims
,
s
.
data
()
)
;
case
onnx
::
TensorProto
::
UINT8
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
UINT8
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
INT8
:
return
literal
{{
shape
::
int32_type
,
dims
},
s
.
data
()};
case
onnx
::
TensorProto
::
INT8
:
return
create_literal
(
shape
::
int32_type
,
dims
,
s
.
data
());
case
onnx
::
TensorProto
::
UINT16
:
return
literal
{{
shape
::
int32_type
,
dims
},
s
.
data
()};
case
onnx
::
TensorProto
::
UINT16
:
case
onnx
::
TensorProto
::
INT16
:
return
literal
{{
shape
::
int32_type
,
dims
},
s
.
data
()};
return
create_literal
(
shape
::
int32_type
,
dims
,
s
.
data
());
case
onnx
::
TensorProto
::
INT32
:
return
literal
{{
shape
::
int32_type
,
dims
},
s
.
data
()};
case
onnx
::
TensorProto
::
INT16
:
return
create_literal
(
shape
::
int32_type
,
dims
,
s
.
data
());
case
onnx
::
TensorProto
::
INT64
:
return
literal
{{
shape
::
int64_type
,
dims
},
s
.
data
()};
case
onnx
::
TensorProto
::
INT32
:
return
create_literal
(
shape
::
int32_type
,
dims
,
s
.
data
());
case
onnx
::
TensorProto
::
INT64
:
return
create_literal
(
shape
::
int64_type
,
dims
,
s
.
data
());
case
onnx
::
TensorProto
::
STRING
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
STRING
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
BOOL
:
return
literal
{{
shape
::
int32_type
,
dims
},
s
.
data
()};
case
onnx
::
TensorProto
::
BOOL
:
return
create_literal
(
shape
::
int32_type
,
dims
,
s
.
data
());
case
onnx
::
TensorProto
::
FLOAT16
:
return
literal
{{
shape
::
half_type
,
dims
},
s
.
data
()};
case
onnx
::
TensorProto
::
FLOAT16
:
case
onnx
::
TensorProto
::
DOUBLE
:
return
literal
{{
shape
::
double_type
,
dims
},
s
.
data
()};
return
create_literal
(
shape
::
half_type
,
dims
,
s
.
data
());
case
onnx
::
TensorProto
::
DOUBLE
:
return
create_literal
(
shape
::
double_type
,
dims
,
s
.
data
());
case
onnx
::
TensorProto
::
UINT32
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
UINT32
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
UINT64
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
UINT64
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
COMPLEX64
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
COMPLEX64
:
throw
std
::
runtime_error
(
""
);
...
@@ -1394,21 +1409,21 @@ struct onnx_parser
...
@@ -1394,21 +1409,21 @@ struct onnx_parser
{
{
case
onnx
::
TensorProto
::
UNDEFINED
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
UNDEFINED
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
FLOAT
:
case
onnx
::
TensorProto
::
FLOAT
:
return
literal
{{
shape
::
float_type
,
dims
}
,
t
.
float_data
()
.
begin
(),
t
.
float_data
().
end
()}
;
return
create_
literal
(
shape
::
float_type
,
dims
,
t
.
float_data
()
)
;
case
onnx
::
TensorProto
::
UINT8
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
UINT8
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
INT8
:
case
onnx
::
TensorProto
::
INT8
:
return
literal
{{
shape
::
int32_type
,
dims
}
,
t
.
int32_data
()
.
begin
(),
t
.
int32_data
().
end
()}
;
return
create_
literal
(
shape
::
int32_type
,
dims
,
t
.
int32_data
()
)
;
case
onnx
::
TensorProto
::
UINT16
:
case
onnx
::
TensorProto
::
UINT16
:
return
literal
{{
shape
::
int32_type
,
dims
}
,
t
.
int32_data
()
.
begin
(),
t
.
int32_data
().
end
()}
;
return
create_
literal
(
shape
::
int32_type
,
dims
,
t
.
int32_data
()
)
;
case
onnx
::
TensorProto
::
INT16
:
case
onnx
::
TensorProto
::
INT16
:
return
literal
{{
shape
::
int32_type
,
dims
}
,
t
.
int32_data
()
.
begin
(),
t
.
int32_data
().
end
()}
;
return
create_
literal
(
shape
::
int32_type
,
dims
,
t
.
int32_data
()
)
;
case
onnx
::
TensorProto
::
INT32
:
case
onnx
::
TensorProto
::
INT32
:
return
literal
{{
shape
::
int32_type
,
dims
}
,
t
.
int32_data
()
.
begin
(),
t
.
int32_data
().
end
()}
;
return
create_
literal
(
shape
::
int32_type
,
dims
,
t
.
int32_data
()
)
;
case
onnx
::
TensorProto
::
INT64
:
case
onnx
::
TensorProto
::
INT64
:
return
literal
{{
shape
::
int64_type
,
dims
}
,
t
.
int64_data
()
.
begin
(),
t
.
int64_data
().
end
()}
;
return
create_
literal
(
shape
::
int64_type
,
dims
,
t
.
int64_data
()
)
;
case
onnx
::
TensorProto
::
STRING
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
STRING
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
BOOL
:
case
onnx
::
TensorProto
::
BOOL
:
return
literal
{{
shape
::
int32_type
,
dims
}
,
t
.
int32_data
()
.
begin
(),
t
.
int32_data
().
end
()}
;
return
create_
literal
(
shape
::
int32_type
,
dims
,
t
.
int32_data
()
)
;
case
onnx
::
TensorProto
::
FLOAT16
:
case
onnx
::
TensorProto
::
FLOAT16
:
{
{
std
::
vector
<
uint16_t
>
data_uint16
(
t
.
int32_data
().
begin
(),
t
.
int32_data
().
end
());
std
::
vector
<
uint16_t
>
data_uint16
(
t
.
int32_data
().
begin
(),
t
.
int32_data
().
end
());
...
@@ -1417,11 +1432,10 @@ struct onnx_parser
...
@@ -1417,11 +1432,10 @@ struct onnx_parser
data_uint16
.
end
(),
data_uint16
.
end
(),
std
::
back_inserter
(
data_half
),
std
::
back_inserter
(
data_half
),
[](
uint16_t
raw_val
)
{
return
*
reinterpret_cast
<
half
*>
(
&
raw_val
);
});
[](
uint16_t
raw_val
)
{
return
*
reinterpret_cast
<
half
*>
(
&
raw_val
);
});
return
literal
{{
shape
::
half_type
,
dims
}
,
data_half
.
begin
(),
data_half
.
end
()}
;
return
create_
literal
(
shape
::
half_type
,
dims
,
data_half
)
;
}
}
case
onnx
::
TensorProto
::
DOUBLE
:
case
onnx
::
TensorProto
::
DOUBLE
:
return
literal
{
return
create_literal
(
shape
::
double_type
,
dims
,
t
.
double_data
());
{
shape
::
double_type
,
dims
},
t
.
double_data
().
begin
(),
t
.
double_data
().
end
()};
case
onnx
::
TensorProto
::
UINT32
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
UINT32
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
UINT64
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
UINT64
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
COMPLEX64
:
throw
std
::
runtime_error
(
""
);
case
onnx
::
TensorProto
::
COMPLEX64
:
throw
std
::
runtime_error
(
""
);
...
@@ -1430,6 +1444,23 @@ struct onnx_parser
...
@@ -1430,6 +1444,23 @@ struct onnx_parser
MIGRAPHX_THROW
(
"Invalid tensor type"
);
MIGRAPHX_THROW
(
"Invalid tensor type"
);
}
}
static
literal
create_literal
(
shape
::
type_t
shape_type
,
const
std
::
vector
<
size_t
>&
dims
,
const
char
*
data
)
{
// in case of scalar constants in onnx file, use dims=1 to fill initializer data
if
(
dims
.
empty
())
return
literal
{{
shape_type
},
data
};
return
literal
{{
shape_type
,
dims
},
data
};
}
template
<
class
T
,
MIGRAPHX_REQUIRES
(
not
std
::
is_pointer
<
T
>{})
>
static
literal
create_literal
(
shape
::
type_t
shape_type
,
const
std
::
vector
<
size_t
>&
dims
,
T
data
)
{
if
(
dims
.
empty
())
return
literal
{{
shape_type
},
data
.
begin
(),
data
.
end
()};
return
literal
{{
shape_type
,
dims
},
data
.
begin
(),
data
.
end
()};
}
static
shape
parse_type
(
const
onnx
::
TypeProto
&
t
)
static
shape
parse_type
(
const
onnx
::
TypeProto
&
t
)
{
{
shape
::
type_t
shape_type
{};
shape
::
type_t
shape_type
{};
...
...
src/opt/memory_coloring_impl.cpp
View file @
c0154dca
...
@@ -63,11 +63,11 @@ bool memory_coloring_impl::allocate(interval_ptr interval)
...
@@ -63,11 +63,11 @@ bool memory_coloring_impl::allocate(interval_ptr interval)
}
}
}
}
long
long
offset
=
0
;
std
::
size_t
offset
=
0
;
while
(
!
conflict_queue
.
empty
())
while
(
!
conflict_queue
.
empty
())
{
{
live_range
*
range
=
conflict_queue
.
top
();
live_range
*
range
=
conflict_queue
.
top
();
long
long
iter_offset
=
range
->
offset
;
std
::
size_t
iter_offset
=
range
->
offset
;
if
(
offset
>
iter_offset
)
if
(
offset
>
iter_offset
)
{
{
offset
=
std
::
max
(
offset
,
iter_offset
+
range
->
size
);
offset
=
std
::
max
(
offset
,
iter_offset
+
range
->
size
);
...
@@ -97,7 +97,7 @@ void memory_coloring_impl::build()
...
@@ -97,7 +97,7 @@ void memory_coloring_impl::build()
if
(
num_of_instrs
==
0
)
if
(
num_of_instrs
==
0
)
return
;
return
;
int
cur_points
=
num_of_instrs
*
2
;
auto
cur_points
=
num_of_instrs
*
2
;
instruction_ref
iter
=
p_program
->
end
();
instruction_ref
iter
=
p_program
->
end
();
instruction_ref
begin
=
p_program
->
begin
();
instruction_ref
begin
=
p_program
->
begin
();
std
::
vector
<
instruction_ref
>
dead_instrs
;
std
::
vector
<
instruction_ref
>
dead_instrs
;
...
@@ -193,13 +193,13 @@ void memory_coloring_impl::rewrite()
...
@@ -193,13 +193,13 @@ void memory_coloring_impl::rewrite()
continue
;
continue
;
std
::
size_t
offset
=
0
;
std
::
size_t
offset
=
0
;
if
(
interval
->
get_offset
()
=
=
invalid_offset
)
if
(
interval
->
get_offset
()
!
=
invalid_offset
)
{
{
assert
(
interval
->
result
.
bytes
()
==
0
);
offset
=
interval
->
get_offset
(
);
}
}
else
else
{
{
offset
=
interval
->
get_offset
(
);
assert
(
interval
->
result
.
bytes
()
==
0
);
}
}
if
(
is_allocate
(
ins
))
if
(
is_allocate
(
ins
))
...
@@ -207,15 +207,6 @@ void memory_coloring_impl::rewrite()
...
@@ -207,15 +207,6 @@ void memory_coloring_impl::rewrite()
p_program
->
replace_instruction
(
p_program
->
replace_instruction
(
ins
,
op
::
load
{
ins
->
get_shape
(),
offset
},
scratch_param
);
ins
,
op
::
load
{
ins
->
get_shape
(),
offset
},
scratch_param
);
}
}
else
if
(
is_literal
(
ins
))
{
#if 0
auto pre = p_program->add_literal(ins->lit);
bool pre_copy = (interval->get_begin() < earliest_end_point);
p_program->replace_instruction(
ins, write_literal{offset, pre_copy}, scratch_param, pre);
#endif
}
}
}
}
}
MIGRAPHX_DEBUG
(
dump
(
"---After rewrite---"
));
MIGRAPHX_DEBUG
(
dump
(
"---After rewrite---"
));
...
...
src/opt/memory_coloring_impl.hpp
View file @
c0154dca
...
@@ -21,15 +21,15 @@
...
@@ -21,15 +21,15 @@
namespace
migraphx
{
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
inline
namespace
MIGRAPHX_INLINE_NS
{
static
const
in
t
invalid_offset
=
-
1
;
static
const
std
::
size_
t
invalid_offset
=
std
::
numeric_limits
<
std
::
size_t
>::
max
()
;
struct
live_range
struct
live_range
{
{
in
t
begin
;
// begin point in the instruction stream.
std
::
size_
t
begin
;
// begin point in the instruction stream.
int
end
;
// end point in the instruction stream.
std
::
size_t
end
;
// end point in the instruction stream.
long
long
offset
;
// offset to base pointer of allocated memory trunk.
std
::
size_t
offset
;
// offset to base pointer of allocated memory trunk.
int
vn
;
// value number that identifies this live_range.
std
::
size_t
vn
;
// value number that identifies this live_range.
long
long
size
;
// size of required memory in bytes
std
::
size_t
size
;
// size of required memory in bytes
#ifdef MIGRAPHX_DEBUG_OPT
#ifdef MIGRAPHX_DEBUG_OPT
void
dump
();
void
dump
();
#endif
#endif
...
@@ -45,9 +45,9 @@ struct live_interval
...
@@ -45,9 +45,9 @@ struct live_interval
is_live_on_entry
=
false
;
is_live_on_entry
=
false
;
}
}
void
add_use
(
in
t
use
)
{
use_points
.
push_front
(
use
);
}
void
add_use
(
std
::
size_
t
use
)
{
use_points
.
push_front
(
use
);
}
in
t
get_begin
()
const
{
return
segment
.
begin
;
}
std
::
size_
t
get_begin
()
const
{
return
segment
.
begin
;
}
in
t
get_end
()
const
{
return
segment
.
end
;
}
std
::
size_
t
get_end
()
const
{
return
segment
.
end
;
}
long
long
get_offset
()
const
{
return
segment
.
offset
;
}
long
long
get_offset
()
const
{
return
segment
.
offset
;
}
#ifdef MIGRAPHX_DEBUG_OPT
#ifdef MIGRAPHX_DEBUG_OPT
...
@@ -55,9 +55,9 @@ struct live_interval
...
@@ -55,9 +55,9 @@ struct live_interval
#endif
#endif
live_range
segment
;
live_range
segment
;
in
t
id
;
std
::
size_
t
id
;
std
::
list
<
in
t
>
use_points
;
std
::
list
<
std
::
size_
t
>
use_points
;
in
t
def_point
;
std
::
size_
t
def_point
;
shape
result
;
shape
result
;
bool
is_literal
;
bool
is_literal
;
bool
is_live_on_entry
;
bool
is_live_on_entry
;
...
@@ -111,8 +111,8 @@ struct memory_coloring_impl
...
@@ -111,8 +111,8 @@ struct memory_coloring_impl
{
{
if
((
range1
.
size
==
0
)
||
(
range2
.
size
==
0
))
if
((
range1
.
size
==
0
)
||
(
range2
.
size
==
0
))
return
false
;
return
false
;
long
long
end1
=
range1
.
offset
+
range1
.
size
-
1
;
auto
end1
=
range1
.
offset
+
range1
.
size
-
1
;
long
long
end2
=
range2
.
offset
+
range2
.
size
-
1
;
auto
end2
=
range2
.
offset
+
range2
.
size
-
1
;
return
((
end1
<
range2
.
offset
)
||
(
end2
<
range1
.
offset
));
return
((
end1
<
range2
.
offset
)
||
(
end2
<
range1
.
offset
));
}
}
void
verify
();
void
verify
();
...
@@ -125,8 +125,8 @@ struct memory_coloring_impl
...
@@ -125,8 +125,8 @@ struct memory_coloring_impl
{
{
bool
operator
()(
const
interval_ptr
i1
,
const
interval_ptr
i2
)
const
bool
operator
()(
const
interval_ptr
i1
,
const
interval_ptr
i2
)
const
{
{
int
len1
=
i1
->
get_end
()
-
i1
->
get_begin
();
auto
len1
=
i1
->
get_end
()
-
i1
->
get_begin
();
int
len2
=
i2
->
get_end
()
-
i2
->
get_begin
();
auto
len2
=
i2
->
get_end
()
-
i2
->
get_begin
();
if
(
len1
!=
len2
)
if
(
len1
!=
len2
)
{
{
return
(
len1
<
len2
);
return
(
len1
<
len2
);
...
@@ -158,7 +158,7 @@ struct memory_coloring_impl
...
@@ -158,7 +158,7 @@ struct memory_coloring_impl
int
num_of_lives
;
int
num_of_lives
;
int
max_value_number
;
int
max_value_number
;
long
long
required_bytes
;
std
::
size_t
required_bytes
;
// The earliest program point where an live interval ends.
// The earliest program point where an live interval ends.
int
earliest_end_point
;
int
earliest_end_point
;
// The latest program point where an live interval ends.
// The latest program point where an live interval ends.
...
...
src/pass_manager.cpp
0 → 100644
View file @
c0154dca
#include <migraphx/program.hpp>
#include <migraphx/pass_manager.hpp>
#include <migraphx/stringutils.hpp>
#include <migraphx/instruction.hpp>
#include <migraphx/operators.hpp>
#include <migraphx/target.hpp>
#include <migraphx/env.hpp>
#include <migraphx/ranges.hpp>
#include <migraphx/time.hpp>
#include <migraphx/iterator_for.hpp>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <utility>
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
void
run_passes
(
program
&
prog
,
const
std
::
vector
<
pass
>&
passes
,
tracer
trace
)
{
for
(
auto
&
p
:
passes
)
{
trace
(
"Pass: "
,
p
.
name
());
p
.
apply
(
prog
);
trace
(
prog
);
#ifndef NDEBUG
trace
(
"Validate ..."
);
auto
invalid
=
prog
.
validate
();
if
(
invalid
!=
prog
.
end
())
{
auto
index
=
std
::
distance
(
prog
.
begin
(),
invalid
);
MIGRAPHX_THROW
(
p
.
name
()
+
" pass produces invalid program at instruction "
+
std
::
to_string
(
index
)
+
": "
+
invalid
->
name
());
}
trace
();
#endif
}
}
}
// namespace MIGRAPHX_INLINE_NS
}
// namespace migraphx
src/program.cpp
View file @
c0154dca
...
@@ -7,6 +7,7 @@
...
@@ -7,6 +7,7 @@
#include <migraphx/ranges.hpp>
#include <migraphx/ranges.hpp>
#include <migraphx/time.hpp>
#include <migraphx/time.hpp>
#include <migraphx/iterator_for.hpp>
#include <migraphx/iterator_for.hpp>
#include <migraphx/pass_manager.hpp>
#include <iostream>
#include <iostream>
#include <sstream>
#include <sstream>
#include <algorithm>
#include <algorithm>
...
@@ -55,18 +56,23 @@ static void print_instruction(std::ostream& os,
...
@@ -55,18 +56,23 @@ static void print_instruction(std::ostream& os,
}
}
template
<
class
F
>
template
<
class
F
>
static
void
print_program
(
std
::
ostream
&
os
,
const
program
&
p
,
F
annonate
)
static
void
print_program
(
const
program
&
p
,
F
print_func
)
{
{
std
::
unordered_map
<
instruction_ref
,
std
::
string
>
names
;
std
::
unordered_map
<
instruction_ref
,
std
::
string
>
names
;
int
count
=
0
;
int
count
=
0
;
for
(
auto
ins
:
iterator_for
(
p
))
for
(
auto
ins
:
iterator_for
(
p
))
{
{
std
::
string
var_name
=
"@"
+
std
::
to_string
(
count
)
;
std
::
string
var_name
;
if
(
ins
->
name
()
==
"@param"
)
if
(
ins
->
name
()
==
"@param"
)
{
{
var_name
=
any_cast
<
builtin
::
param
>
(
ins
->
get_operator
()).
parameter
;
var_name
=
any_cast
<
builtin
::
param
>
(
ins
->
get_operator
()).
parameter
;
}
}
else
{
var_name
=
"@"
+
std
::
to_string
(
count
);
count
++
;
}
names
.
emplace
(
ins
,
var_name
);
names
.
emplace
(
ins
,
var_name
);
// TODO: Use all_of
// TODO: Use all_of
...
@@ -76,21 +82,77 @@ static void print_program(std::ostream& os, const program& p, F annonate)
...
@@ -76,21 +82,77 @@ static void print_program(std::ostream& os, const program& p, F annonate)
(
void
)
arg
;
(
void
)
arg
;
}
}
print_instruction
(
os
,
ins
,
names
);
print_func
(
ins
,
names
);
annonate
(
ins
,
names
);
os
<<
std
::
endl
;
count
++
;
}
}
}
}
program
::
program
()
:
impl
(
std
::
make_unique
<
program_impl
>
())
{}
program
::
program
()
:
impl
(
std
::
make_unique
<
program_impl
>
())
{}
program
::
program
(
program
&&
)
noexcept
=
default
;
program
::
program
(
program
&&
)
noexcept
=
default
;
program
&
program
::
operator
=
(
program
&&
)
noexcept
=
default
;
program
::~
program
()
noexcept
=
default
;
program
::~
program
()
noexcept
=
default
;
// copy constructor
program
::
program
(
const
program
&
p
)
{
assign
(
p
);
}
// copy assignment operator
program
&
program
::
operator
=
(
program
p
)
{
std
::
swap
(
p
.
impl
,
this
->
impl
);
return
*
this
;
}
void
program
::
assign
(
const
program
&
p
)
{
// clean the current program
if
(
!
impl
)
{
impl
=
std
::
make_unique
<
program_impl
>
();
}
else
if
(
!
impl
->
instructions
.
empty
())
{
impl
->
instructions
.
clear
();
}
impl
->
ctx
=
p
.
impl
->
ctx
;
std
::
unordered_map
<
instruction_ref
,
instruction_ref
>
ins_map
;
for
(
auto
ins
:
iterator_for
(
p
))
{
instruction_ref
copy_ins
{};
if
(
ins
->
name
()
==
"@literal"
)
{
auto
l
=
ins
->
get_literal
();
copy_ins
=
impl
->
instructions
.
insert
(
impl
->
instructions
.
end
(),
instruction
{
l
});
}
else
if
(
ins
->
name
()
==
"@param"
)
{
auto
&&
name
=
any_cast
<
builtin
::
param
>
(
ins
->
get_operator
()).
parameter
;
auto
s
=
ins
->
get_shape
();
copy_ins
=
impl
->
instructions
.
insert
(
impl
->
instructions
.
end
(),
{
builtin
::
param
{
name
},
std
::
move
(
s
),
{}});
}
else
if
(
ins
->
name
()
==
"@outline"
)
{
auto
s
=
ins
->
get_shape
();
copy_ins
=
impl
->
instructions
.
insert
(
impl
->
instructions
.
end
(),
{
builtin
::
outline
{
s
},
s
,
{}});
}
else
{
// retrieve its mapped input
auto
inputs
=
ins
->
inputs
();
// ensure all inputs have its corresponding copy instructions
assert
(
std
::
all_of
(
inputs
.
begin
(),
inputs
.
end
(),
[
&
](
auto
i
)
{
return
ins_map
.
count
(
i
)
>
0
;
}));
std
::
vector
<
instruction_ref
>
copy_inputs
(
inputs
.
size
());
std
::
transform
(
inputs
.
begin
(),
inputs
.
end
(),
copy_inputs
.
begin
(),
[
&
](
auto
i
)
{
return
ins_map
[
i
];
});
copy_ins
=
add_instruction
(
ins
->
get_operator
(),
copy_inputs
);
}
ins_map
[
ins
]
=
copy_ins
;
}
}
instruction_ref
program
::
add_instruction
(
const
operation
&
op
,
std
::
vector
<
instruction_ref
>
args
)
instruction_ref
program
::
add_instruction
(
const
operation
&
op
,
std
::
vector
<
instruction_ref
>
args
)
{
{
...
@@ -291,23 +353,7 @@ void program::compile(const target& t, tracer trace)
...
@@ -291,23 +353,7 @@ void program::compile(const target& t, tracer trace)
trace
=
tracer
{
std
::
cout
};
trace
=
tracer
{
std
::
cout
};
trace
(
*
this
);
trace
(
*
this
);
trace
();
trace
();
for
(
auto
&&
p
:
t
.
get_passes
(
this
->
impl
->
ctx
))
run_passes
(
*
this
,
t
.
get_passes
(
this
->
impl
->
ctx
),
trace
);
{
trace
(
"Pass: "
,
p
.
name
());
p
.
apply
(
*
this
);
trace
(
*
this
);
#ifndef NDEBUG
trace
(
"Validate ..."
);
auto
invalid
=
this
->
validate
();
if
(
invalid
!=
impl
->
instructions
.
end
())
{
auto
index
=
std
::
distance
(
impl
->
instructions
.
begin
(),
invalid
);
MIGRAPHX_THROW
(
p
.
name
()
+
" pass produces invalid program at instruction "
+
std
::
to_string
(
index
)
+
": "
+
invalid
->
name
());
}
trace
();
#endif
}
auto
invalid
=
this
->
validate
();
auto
invalid
=
this
->
validate
();
if
(
invalid
!=
impl
->
instructions
.
end
())
if
(
invalid
!=
impl
->
instructions
.
end
())
{
{
...
@@ -475,10 +521,12 @@ void program::perf_report(std::ostream& os, std::size_t n, parameter_map params)
...
@@ -475,10 +521,12 @@ void program::perf_report(std::ostream& os, std::size_t n, parameter_map params)
double
calculate_overhead_time
=
total_time
-
total_instruction_time
;
double
calculate_overhead_time
=
total_time
-
total_instruction_time
;
double
calculate_overhead_percent
=
calculate_overhead_time
*
100.0
/
total_time
;
double
calculate_overhead_percent
=
calculate_overhead_time
*
100.0
/
total_time
;
print_program
(
os
,
*
this
,
[
&
](
auto
ins
,
auto
&&
)
{
print_program
(
*
this
,
[
&
](
auto
ins
,
const
auto
&
names
)
{
print_instruction
(
std
::
cout
,
ins
,
names
);
double
avg
=
common_average
(
ins_vec
[
ins
]);
double
avg
=
common_average
(
ins_vec
[
ins
]);
double
percent
=
std
::
ceil
(
100.0
*
avg
/
total_instruction_time
);
double
percent
=
std
::
ceil
(
100.0
*
avg
/
total_instruction_time
);
os
<<
": "
<<
avg
<<
"ms, "
<<
percent
<<
"%"
;
os
<<
": "
<<
avg
<<
"ms, "
<<
percent
<<
"%"
;
os
<<
std
::
endl
;
});
});
os
<<
std
::
endl
;
os
<<
std
::
endl
;
...
@@ -516,7 +564,7 @@ void program::debug_print(instruction_ref ins) const
...
@@ -516,7 +564,7 @@ void program::debug_print(instruction_ref ins) const
return
;
return
;
}
}
std
::
stringstream
ss
;
std
::
stringstream
ss
;
print_program
(
ss
,
*
this
,
[
&
](
auto
x
,
auto
&
&
names
)
{
print_program
(
*
this
,
[
&
](
auto
x
,
const
auto
&
names
)
{
if
(
x
==
ins
)
if
(
x
==
ins
)
{
{
print_instruction
(
std
::
cout
,
x
,
names
);
print_instruction
(
std
::
cout
,
x
,
names
);
...
@@ -531,6 +579,32 @@ void program::debug_print(const std::vector<instruction_ref>& inss) const
...
@@ -531,6 +579,32 @@ void program::debug_print(const std::vector<instruction_ref>& inss) const
std
::
cout
<<
std
::
endl
;
std
::
cout
<<
std
::
endl
;
}
}
static
std
::
string
enclose_name
(
const
std
::
string
&
name
)
{
return
'"'
+
replace_string
(
name
,
"
\"
"
,
"
\\\"
"
)
+
'"'
;
}
void
program
::
print_graph
(
std
::
ostream
&
os
)
const
{
os
<<
"digraph {"
<<
std
::
endl
;
os
<<
"
\t
rankdir=LR;"
<<
std
::
endl
;
print_program
(
*
this
,
[
&
](
auto
ins
,
const
auto
&
names
)
{
os
<<
"
\t
"
<<
enclose_name
(
names
.
at
(
ins
))
<<
"[label="
<<
enclose_name
(
to_string
(
ins
->
get_operator
()))
<<
"];"
;
os
<<
std
::
endl
;
if
(
!
ins
->
inputs
().
empty
())
{
for
(
auto
&&
arg
:
ins
->
inputs
())
{
os
<<
"
\t
"
<<
enclose_name
(
names
.
at
(
arg
))
<<
" -> "
<<
enclose_name
(
names
.
at
(
ins
));
os
<<
"[label="
<<
enclose_name
(
to_string
(
ins
->
get_shape
()))
<<
"];"
;
os
<<
std
::
endl
;
}
}
});
os
<<
"}"
<<
std
::
endl
;
}
void
program
::
dry_run
(
std
::
unordered_map
<
std
::
string
,
argument
>
params
)
const
void
program
::
dry_run
(
std
::
unordered_map
<
std
::
string
,
argument
>
params
)
const
{
{
auto
&
ctx
=
this
->
impl
->
ctx
;
auto
&
ctx
=
this
->
impl
->
ctx
;
...
@@ -539,14 +613,21 @@ void program::dry_run(std::unordered_map<std::string, argument> params) const
...
@@ -539,14 +613,21 @@ void program::dry_run(std::unordered_map<std::string, argument> params) const
void
program
::
annotate
(
std
::
ostream
&
os
,
std
::
function
<
void
(
instruction_ref
)
>
a
)
const
void
program
::
annotate
(
std
::
ostream
&
os
,
std
::
function
<
void
(
instruction_ref
)
>
a
)
const
{
{
print_program
(
os
,
*
this
,
[
&
](
auto
ins
,
auto
&&
)
{
a
(
ins
);
});
print_program
(
*
this
,
[
&
](
auto
ins
,
const
auto
&
names
)
{
print_instruction
(
os
,
ins
,
names
);
a
(
ins
);
os
<<
std
::
endl
;
});
}
}
bool
operator
==
(
const
program
&
x
,
const
program
&
y
)
{
return
to_string
(
x
)
==
to_string
(
y
);
}
bool
operator
==
(
const
program
&
x
,
const
program
&
y
)
{
return
to_string
(
x
)
==
to_string
(
y
);
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
program
&
p
)
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
program
&
p
)
{
{
print_program
(
os
,
p
,
[](
auto
&&
...)
{});
print_program
(
p
,
[
&
](
auto
ins
,
const
auto
&
names
)
{
print_instruction
(
os
,
ins
,
names
);
os
<<
std
::
endl
;
});
return
os
;
return
os
;
}
}
...
...
src/propagate_constant.cpp
0 → 100644
View file @
c0154dca
#include <migraphx/propagate_constant.hpp>
#include <migraphx/program.hpp>
#include <migraphx/matcher.hpp>
#include <migraphx/literal.hpp>
#include <migraphx/functional.hpp>
#include <unordered_set>
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
bool
skip_propogate
(
instruction_ref
ins
)
{
if
(
ins
->
name
()
==
"@literal"
)
return
true
;
auto
&&
s
=
ins
->
get_shape
();
if
(
s
.
broadcasted
()
and
not
s
.
scalar
())
return
true
;
if
(
s
.
scalar
()
and
s
.
elements
()
!=
1
)
return
true
;
return
false
;
}
void
propagate_constant
::
apply
(
program
&
p
)
const
{
for
(
auto
i
:
iterator_for
(
p
))
{
if
(
i
->
name
()
!=
"@literal"
)
continue
;
if
(
i
->
outputs
().
empty
())
continue
;
fix
([
&
](
auto
self
,
auto
ins
)
{
std
::
unordered_set
<
instruction_ref
>
children
(
ins
->
outputs
().
begin
(),
ins
->
outputs
().
end
());
for
(
auto
child
:
children
)
{
if
(
skip_propogate
(
child
))
{
self
(
child
);
continue
;
}
auto
r
=
child
->
eval
();
if
(
not
r
.
empty
())
{
assert
(
r
.
get_shape
()
==
child
->
get_shape
());
auto
l
=
p
.
add_literal
(
r
.
get_shape
(),
r
.
data
());
self
(
p
.
replace_instruction
(
child
,
l
));
}
}
})(
i
);
}
}
}
// namespace MIGRAPHX_INLINE_NS
}
// namespace migraphx
src/rewrite_rnn.cpp
View file @
c0154dca
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
#include <migraphx/operators.hpp>
#include <migraphx/operators.hpp>
#include <migraphx/iterator_for.hpp>
#include <migraphx/iterator_for.hpp>
#include <migraphx/dfor.hpp>
#include <migraphx/dfor.hpp>
#include <migraphx/op/common.hpp>
namespace
migraphx
{
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
inline
namespace
MIGRAPHX_INLINE_NS
{
...
@@ -213,7 +214,7 @@ std::vector<instruction_ref> rewrite_rnn::vanilla_rnn_cell(bool is_forward,
...
@@ -213,7 +214,7 @@ std::vector<instruction_ref> rewrite_rnn::vanilla_rnn_cell(bool is_forward,
auto
wb
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
0
},
{
hs
}},
sbias
);
auto
wb
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
0
},
{
hs
}},
sbias
);
auto
rb
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
hs
},
{
2
*
hs
}},
sbias
);
auto
rb
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
hs
},
{
2
*
hs
}},
sbias
);
auto
b
=
prog
.
insert_instruction
(
ins
,
op
::
add
{},
wb
,
rb
);
auto
b
=
prog
.
insert_instruction
(
ins
,
op
::
add
{},
wb
,
rb
);
bias
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
sih
->
get_shape
()},
b
);
bias
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
sih
->
get_shape
()
.
lens
()
},
b
);
}
}
instruction_ref
hidden_out
=
prog
.
end
();
instruction_ref
hidden_out
=
prog
.
end
();
...
@@ -520,25 +521,26 @@ std::vector<instruction_ref> rewrite_rnn::gru_cell(bool is_forward,
...
@@ -520,25 +521,26 @@ std::vector<instruction_ref> rewrite_rnn::gru_cell(bool is_forward,
instruction_ref
brcst_bh
{};
instruction_ref
brcst_bh
{};
if
(
bias
!=
prog
.
end
())
if
(
bias
!=
prog
.
end
())
{
{
auto
sbias
=
prog
.
insert_instruction
(
ins
,
op
::
squeeze
{{
0
}},
bias
);
auto
broadcast_lens
=
sih
->
get_shape
().
lens
();
auto
wbz
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
0
},
{
hs
}},
sbias
);
auto
sbias
=
prog
.
insert_instruction
(
ins
,
op
::
squeeze
{{
0
}},
bias
);
auto
wbr
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
hs
},
{
2
*
hs
}},
sbias
);
auto
wbz
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
0
},
{
hs
}},
sbias
);
auto
wbh
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
2
*
hs
},
{
3
*
hs
}},
sbias
);
auto
wbr
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
hs
},
{
2
*
hs
}},
sbias
);
brcst_wbh
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
sih
->
get_shape
()},
wbh
);
auto
wbh
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
2
*
hs
},
{
3
*
hs
}},
sbias
);
brcst_wbh
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
broadcast_lens
},
wbh
);
auto
rbz
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
3
*
hs
},
{
4
*
hs
}},
sbias
);
auto
rbz
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
3
*
hs
},
{
4
*
hs
}},
sbias
);
auto
rbr
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
4
*
hs
},
{
5
*
hs
}},
sbias
);
auto
rbr
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
4
*
hs
},
{
5
*
hs
}},
sbias
);
auto
rbh
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
5
*
hs
},
{
6
*
hs
}},
sbias
);
auto
rbh
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
5
*
hs
},
{
6
*
hs
}},
sbias
);
brcst_rbh
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
sih
->
get_shape
()
},
rbh
);
brcst_rbh
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
broadcast_lens
},
rbh
);
auto
bz
=
prog
.
insert_instruction
(
ins
,
op
::
add
{},
wbz
,
rbz
);
auto
bz
=
prog
.
insert_instruction
(
ins
,
op
::
add
{},
wbz
,
rbz
);
brcst_bz
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
sih
->
get_shape
()
},
bz
);
brcst_bz
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
broadcast_lens
},
bz
);
auto
br
=
prog
.
insert_instruction
(
ins
,
op
::
add
{},
wbr
,
rbr
);
auto
br
=
prog
.
insert_instruction
(
ins
,
op
::
add
{},
wbr
,
rbr
);
brcst_br
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
sih
->
get_shape
()
},
br
);
brcst_br
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
broadcast_lens
},
br
);
auto
bh
=
prog
.
insert_instruction
(
ins
,
op
::
add
{},
wbh
,
rbh
);
auto
bh
=
prog
.
insert_instruction
(
ins
,
op
::
add
{},
wbh
,
rbh
);
brcst_bh
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
sih
->
get_shape
()
},
bh
);
brcst_bh
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
broadcast_lens
},
bh
);
}
}
for
(
long
i
=
0
;
i
<
seq_len
;
i
++
)
for
(
long
i
=
0
;
i
<
seq_len
;
i
++
)
...
@@ -945,8 +947,8 @@ std::vector<instruction_ref> rewrite_rnn::lstm_cell(bool is_forward,
...
@@ -945,8 +947,8 @@ std::vector<instruction_ref> rewrite_rnn::lstm_cell(bool is_forward,
auto
sih
=
prog
.
insert_instruction
(
ins
,
op
::
squeeze
{{
0
}},
ih
);
auto
sih
=
prog
.
insert_instruction
(
ins
,
op
::
squeeze
{{
0
}},
ih
);
// initial cell state
// initial cell state
auto
sic
=
prog
.
insert_instruction
(
ins
,
op
::
squeeze
{{
0
}},
ic
);
auto
sic
=
prog
.
insert_instruction
(
ins
,
op
::
squeeze
{{
0
}},
ic
);
auto
ic_
shape
=
sic
->
get_shape
();
auto
ic_
lens
=
sic
->
get_shape
()
.
lens
()
;
// bias
// bias
instruction_ref
bi_brcst
{};
instruction_ref
bi_brcst
{};
...
@@ -955,26 +957,27 @@ std::vector<instruction_ref> rewrite_rnn::lstm_cell(bool is_forward,
...
@@ -955,26 +957,27 @@ std::vector<instruction_ref> rewrite_rnn::lstm_cell(bool is_forward,
instruction_ref
bc_brcst
{};
instruction_ref
bc_brcst
{};
if
(
bias
!=
prog
.
end
())
if
(
bias
!=
prog
.
end
())
{
{
auto
sbias
=
prog
.
insert_instruction
(
ins
,
op
::
squeeze
{{
0
}},
bias
);
auto
sbias
=
prog
.
insert_instruction
(
ins
,
op
::
squeeze
{{
0
}},
bias
);
auto
bxi
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
0
},
{
hs
}},
sbias
);
auto
bxi
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
0
},
{
hs
}},
sbias
);
auto
bhi
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
4
*
hs
},
{
5
*
hs
}},
sbias
);
auto
bhi
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
4
*
hs
},
{
5
*
hs
}},
sbias
);
auto
bi
=
prog
.
insert_instruction
(
ins
,
op
::
add
{},
bxi
,
bhi
);
auto
bi
=
prog
.
insert_instruction
(
ins
,
op
::
add
{},
bxi
,
bhi
);
bi_brcst
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
ic_
shape
},
bi
);
bi_brcst
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
ic_
lens
},
bi
);
auto
bxo
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
hs
},
{
2
*
hs
}},
sbias
);
auto
bxo
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
hs
},
{
2
*
hs
}},
sbias
);
auto
bho
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
5
*
hs
},
{
6
*
hs
}},
sbias
);
auto
bho
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
5
*
hs
},
{
6
*
hs
}},
sbias
);
auto
bo
=
prog
.
insert_instruction
(
ins
,
op
::
add
{},
bxo
,
bho
);
auto
bo
=
prog
.
insert_instruction
(
ins
,
op
::
add
{},
bxo
,
bho
);
bo_brcst
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
ic_
shape
},
bo
);
bo_brcst
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
ic_
lens
},
bo
);
auto
bxf
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
2
*
hs
},
{
3
*
hs
}},
sbias
);
auto
bxf
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
2
*
hs
},
{
3
*
hs
}},
sbias
);
auto
bhf
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
6
*
hs
},
{
7
*
hs
}},
sbias
);
auto
bhf
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
6
*
hs
},
{
7
*
hs
}},
sbias
);
auto
bf
=
prog
.
insert_instruction
(
ins
,
op
::
add
{},
bxf
,
bhf
);
auto
bf
=
prog
.
insert_instruction
(
ins
,
op
::
add
{},
bxf
,
bhf
);
bf_brcst
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
ic_
shape
},
bf
);
bf_brcst
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
ic_
lens
},
bf
);
auto
bxc
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
3
*
hs
},
{
4
*
hs
}},
sbias
);
auto
bxc
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
3
*
hs
},
{
4
*
hs
}},
sbias
);
auto
bhc
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
7
*
hs
},
{
8
*
hs
}},
sbias
);
auto
bhc
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
7
*
hs
},
{
8
*
hs
}},
sbias
);
auto
bc
=
prog
.
insert_instruction
(
ins
,
op
::
add
{},
bxc
,
bhc
);
auto
bc
=
prog
.
insert_instruction
(
ins
,
op
::
add
{},
bxc
,
bhc
);
bc_brcst
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
ic_
shape
},
bc
);
bc_brcst
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
ic_
lens
},
bc
);
}
}
// peep hole
// peep hole
...
@@ -986,13 +989,13 @@ std::vector<instruction_ref> rewrite_rnn::lstm_cell(bool is_forward,
...
@@ -986,13 +989,13 @@ std::vector<instruction_ref> rewrite_rnn::lstm_cell(bool is_forward,
{
{
auto
spph
=
prog
.
insert_instruction
(
ins
,
op
::
squeeze
{{
0
}},
pph
);
auto
spph
=
prog
.
insert_instruction
(
ins
,
op
::
squeeze
{{
0
}},
pph
);
auto
pphi
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
0
},
{
hs
}},
spph
);
auto
pphi
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
0
},
{
hs
}},
spph
);
pphi_brcst
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
ic_
shape
},
pphi
);
pphi_brcst
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
ic_
lens
},
pphi
);
auto
ppho
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
hs
},
{
2
*
hs
}},
spph
);
auto
ppho
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
hs
},
{
2
*
hs
}},
spph
);
ppho_brcst
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
ic_
shape
},
ppho
);
ppho_brcst
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
ic_
lens
},
ppho
);
auto
pphf
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
2
*
hs
},
{
3
*
hs
}},
spph
);
auto
pphf
=
prog
.
insert_instruction
(
ins
,
op
::
slice
{{
0
},
{
2
*
hs
},
{
3
*
hs
}},
spph
);
pphf_brcst
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
ic_
shape
},
pphf
);
pphf_brcst
=
prog
.
insert_instruction
(
ins
,
op
::
broadcast
{
1
,
ic_
lens
},
pphf
);
}
}
for
(
long
i
=
0
;
i
<
seq_len
;
++
i
)
for
(
long
i
=
0
;
i
<
seq_len
;
++
i
)
...
@@ -1166,5 +1169,14 @@ std::vector<operation> rewrite_rnn::lstm_actv_funcs(instruction_ref ins) const
...
@@ -1166,5 +1169,14 @@ std::vector<operation> rewrite_rnn::lstm_actv_funcs(instruction_ref ins) const
}
}
}
}
namespace
op
{
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
rnn_direction
v
)
{
std
::
vector
<
std
::
string
>
rnn_direction_str
=
{
"forward"
,
"reverse"
,
"bidirectional"
};
os
<<
rnn_direction_str
[
static_cast
<
std
::
underlying_type
<
rnn_direction
>::
type
>
(
v
)];
return
os
;
}
}
// namespace op
}
// namespace MIGRAPHX_INLINE_NS
}
// namespace MIGRAPHX_INLINE_NS
}
// namespace migraphx
}
// namespace migraphx
src/targets/cpu/lowering.cpp
View file @
c0154dca
...
@@ -48,6 +48,12 @@ struct cpu_batch_norm_inference
...
@@ -48,6 +48,12 @@ struct cpu_batch_norm_inference
{
{
op
::
batch_norm_inference
op
;
op
::
batch_norm_inference
op
;
template
<
class
Self
,
class
F
>
static
auto
reflect
(
Self
&
self
,
F
f
)
{
return
migraphx
::
reflect
(
self
.
op
,
f
);
}
std
::
string
name
()
const
{
return
"cpu::batch_norm_inference"
;
}
std
::
string
name
()
const
{
return
"cpu::batch_norm_inference"
;
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
...
@@ -107,6 +113,12 @@ struct cpu_lrn
...
@@ -107,6 +113,12 @@ struct cpu_lrn
{
{
op
::
lrn
op
;
op
::
lrn
op
;
template
<
class
Self
,
class
F
>
static
auto
reflect
(
Self
&
self
,
F
f
)
{
return
migraphx
::
reflect
(
self
.
op
,
f
);
}
std
::
string
name
()
const
{
return
"cpu::lrn"
;
}
std
::
string
name
()
const
{
return
"cpu::lrn"
;
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
...
@@ -117,7 +129,7 @@ struct cpu_lrn
...
@@ -117,7 +129,7 @@ struct cpu_lrn
int
channels
=
output_shape
.
lens
()[
1
];
int
channels
=
output_shape
.
lens
()[
1
];
int
height
=
output_shape
.
lens
()[
2
];
int
height
=
output_shape
.
lens
()[
2
];
int
width
=
output_shape
.
lens
()[
3
];
int
width
=
output_shape
.
lens
()[
3
];
float
alphaoverarea
=
op
.
alpha
/
op
.
size
;
float
alphaoverarea
=
op
.
alpha
/
float
(
op
.
size
)
;
int
radius
=
(
op
.
size
-
1
)
/
2
;
int
radius
=
(
op
.
size
-
1
)
/
2
;
par_dfor
(
n_batch
,
height
,
width
)([
&
](
int
b
,
int
h
,
int
w
)
{
par_dfor
(
n_batch
,
height
,
width
)([
&
](
int
b
,
int
h
,
int
w
)
{
...
@@ -144,6 +156,12 @@ struct cpu_convolution
...
@@ -144,6 +156,12 @@ struct cpu_convolution
{
{
op
::
convolution
op
;
op
::
convolution
op
;
template
<
class
Self
,
class
F
>
static
auto
reflect
(
Self
&
self
,
F
f
)
{
return
migraphx
::
reflect
(
self
.
op
,
f
);
}
std
::
string
name
()
const
{
return
"cpu::convolution"
;
}
std
::
string
name
()
const
{
return
"cpu::convolution"
;
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
...
@@ -165,15 +183,15 @@ struct cpu_convolution
...
@@ -165,15 +183,15 @@ struct cpu_convolution
output_shape
.
lens
()[
2
],
output_shape
.
lens
()[
2
],
output_shape
.
lens
()[
3
])(
output_shape
.
lens
()[
3
])(
[
&
](
std
::
size_t
o
,
std
::
size_t
w
,
std
::
size_t
i
,
std
::
size_t
j
)
{
[
&
](
std
::
size_t
o
,
std
::
size_t
w
,
std
::
size_t
i
,
std
::
size_t
j
)
{
const
int
start_x
=
i
*
op
.
stride
[
0
]
-
op
.
padding
[
0
];
const
auto
start_x
=
i
*
op
.
stride
[
0
]
-
op
.
padding
[
0
];
const
int
start_y
=
j
*
op
.
stride
[
1
]
-
op
.
padding
[
1
];
const
auto
start_y
=
j
*
op
.
stride
[
1
]
-
op
.
padding
[
1
];
const
int
group_id
=
w
/
(
wei_n
/
op
.
group
);
const
auto
group_id
=
w
/
(
wei_n
/
op
.
group
);
double
acc
=
0
;
double
acc
=
0
;
dfor
(
wei_c
,
wei_h
,
wei_w
)([
&
](
std
::
size_t
k
,
std
::
size_t
x
,
std
::
size_t
y
)
{
dfor
(
wei_c
,
wei_h
,
wei_w
)([
&
](
std
::
size_t
k
,
std
::
size_t
x
,
std
::
size_t
y
)
{
const
int
in_x
=
start_x
+
x
;
const
auto
in_x
=
start_x
+
x
;
const
int
in_y
=
start_y
+
y
;
const
auto
in_y
=
start_y
+
y
;
const
int
in_ch
=
group_id
*
wei_c
+
k
;
const
auto
in_ch
=
group_id
*
wei_c
+
k
;
if
(
in_x
>=
0
&&
in_x
<
in_h
&&
in_y
>=
0
&&
in_y
<
in_w
)
if
(
in_x
>=
0
&&
in_x
<
in_h
&&
in_y
>=
0
&&
in_y
<
in_w
)
{
{
acc
+=
input
(
o
,
in_ch
,
in_x
,
in_y
)
*
weights
(
w
,
k
,
x
,
y
);
acc
+=
input
(
o
,
in_ch
,
in_x
,
in_y
)
*
weights
(
w
,
k
,
x
,
y
);
...
@@ -190,6 +208,12 @@ struct cpu_im2col
...
@@ -190,6 +208,12 @@ struct cpu_im2col
{
{
op
::
im2col
op
;
op
::
im2col
op
;
template
<
class
Self
,
class
F
>
static
auto
reflect
(
Self
&
self
,
F
f
)
{
return
migraphx
::
reflect
(
self
.
op
,
f
);
}
static
std
::
string
name
()
{
return
"cpu::im2col"
;
}
static
std
::
string
name
()
{
return
"cpu::im2col"
;
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
...
@@ -209,10 +233,8 @@ struct cpu_im2col
...
@@ -209,10 +233,8 @@ struct cpu_im2col
const
std
::
size_t
&
stride_h
=
op
.
stride
[
0
];
const
std
::
size_t
&
stride_h
=
op
.
stride
[
0
];
const
std
::
size_t
&
stride_w
=
op
.
stride
[
1
];
const
std
::
size_t
&
stride_w
=
op
.
stride
[
1
];
int
kdiv2_h
;
auto
kdiv2_h
=
kernel_h
/
2
;
int
kdiv2_w
;
auto
kdiv2_w
=
kernel_w
/
2
;
kdiv2_h
=
kernel_h
/
2
;
kdiv2_w
=
kernel_w
/
2
;
// calculate output sizes
// calculate output sizes
const
std
::
size_t
col_height
=
(
height
-
kernel_h
+
2
*
pad_h
)
/
stride_h
+
1
;
const
std
::
size_t
col_height
=
(
height
-
kernel_h
+
2
*
pad_h
)
/
stride_h
+
1
;
const
std
::
size_t
col_width
=
(
width
-
kernel_w
+
2
*
pad_w
)
/
stride_w
+
1
;
const
std
::
size_t
col_width
=
(
width
-
kernel_w
+
2
*
pad_w
)
/
stride_w
+
1
;
...
@@ -230,8 +252,8 @@ struct cpu_im2col
...
@@ -230,8 +252,8 @@ struct cpu_im2col
dfor
(
channels
,
dfor
(
channels
,
kernel_h
,
kernel_h
,
kernel_w
)([
&
](
std
::
size_t
c
,
std
::
size_t
koffset
,
std
::
size_t
loffset
)
{
kernel_w
)([
&
](
std
::
size_t
c
,
std
::
size_t
koffset
,
std
::
size_t
loffset
)
{
int
idx
=
iinput
+
koffset
-
kdiv2_h
;
auto
idx
=
iinput
+
koffset
-
kdiv2_h
;
int
jdx
=
jinput
+
loffset
-
kdiv2_w
;
auto
jdx
=
jinput
+
loffset
-
kdiv2_w
;
col
(
ldx
,
p
)
=
((
idx
>=
0
)
&&
(
idx
<
height
)
&&
(
jdx
>=
0
)
&&
(
jdx
<
width
))
col
(
ldx
,
p
)
=
((
idx
>=
0
)
&&
(
idx
<
height
)
&&
(
jdx
>=
0
)
&&
(
jdx
<
width
))
?
input
(
0
,
c
,
idx
,
jdx
)
?
input
(
0
,
c
,
idx
,
jdx
)
:
0
;
:
0
;
...
@@ -273,6 +295,12 @@ struct cpu_pooling
...
@@ -273,6 +295,12 @@ struct cpu_pooling
{
{
op
::
pooling
op
;
op
::
pooling
op
;
template
<
class
Self
,
class
F
>
static
auto
reflect
(
Self
&
self
,
F
f
)
{
return
migraphx
::
reflect
(
self
.
op
,
f
);
}
std
::
string
name
()
const
{
return
"cpu::pooling_"
+
Op
::
name
();
}
std
::
string
name
()
const
{
return
"cpu::pooling_"
+
Op
::
name
();
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
argument
compute
(
context
&
,
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
context
&
,
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
...
@@ -317,20 +345,35 @@ struct cpu_pooling
...
@@ -317,20 +345,35 @@ struct cpu_pooling
}
}
};
};
struct
cpu_
contiguous
struct
cpu_
op
{
{
op
::
contiguous
op
;
op
eration
op
;
std
::
string
name
()
const
{
return
"cpu::
contiguous"
;
}
std
::
string
name
()
const
{
return
"cpu::
"
+
op
.
name
()
;
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
argument
compute
(
context
&
,
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
context
&
,
const
shape
&
output_shape
,
const
std
::
vector
<
argument
>&
args
)
const
{
return
op
.
compute
(
output_shape
,
args
);
}
friend
bool
operator
==
(
const
cpu_op
&
x
,
const
cpu_op
&
y
)
{
return
x
.
op
==
y
.
op
;
}
friend
bool
operator
==
(
const
cpu_op
&
x
,
const
operation
&
y
)
{
{
return
op
.
compute
(
output_shape
,
std
::
move
(
args
));
if
(
x
.
name
()
!=
y
.
name
())
return
false
;
return
x
==
any_cast
<
cpu_op
>
(
y
);
}
}
friend
bool
operator
==
(
const
operation
&
x
,
const
cpu_op
&
y
)
{
return
y
==
x
;
}
};
};
struct
cpu_pad
struct
cpu_pad
{
{
op
::
pad
op
;
op
::
pad
op
;
template
<
class
Self
,
class
F
>
static
auto
reflect
(
Self
&
self
,
F
f
)
{
return
migraphx
::
reflect
(
self
.
op
,
f
);
}
std
::
string
name
()
const
{
return
"cpu::contiguous"
;
}
std
::
string
name
()
const
{
return
"cpu::contiguous"
;
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
argument
compute
(
context
&
,
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
context
&
,
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
...
@@ -354,20 +397,15 @@ struct cpu_pad
...
@@ -354,20 +397,15 @@ struct cpu_pad
}
}
};
};
struct
cpu_concat
{
op
::
concat
op
;
std
::
string
name
()
const
{
return
"cpu::concat"
;
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
argument
compute
(
context
&
,
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
return
op
.
compute
(
output_shape
,
std
::
move
(
args
));
}
};
struct
cpu_gemm
struct
cpu_gemm
{
{
op
::
dot
op
;
op
::
dot
op
;
template
<
class
Self
,
class
F
>
static
auto
reflect
(
Self
&
self
,
F
f
)
{
return
migraphx
::
reflect
(
self
.
op
,
f
);
}
std
::
string
name
()
const
{
return
"cpu::dot"
;
}
std
::
string
name
()
const
{
return
"cpu::dot"
;
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
{
...
@@ -410,162 +448,6 @@ struct cpu_gemm
...
@@ -410,162 +448,6 @@ struct cpu_gemm
}
}
};
};
struct
cpu_gather
{
op
::
gather
op
;
std
::
string
name
()
const
{
return
"cpu::gather"
;
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
argument
compute
(
context
&
,
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
return
op
.
compute
(
output_shape
,
std
::
move
(
args
));
}
};
struct
identity_op
{
std
::
string
name
()
const
{
return
"cpu::identity"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
x
;
};
}
};
struct
abs_op
{
std
::
string
name
()
const
{
return
"cpu::abs"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
abs
(
make_signed
(
x
));
};
}
};
struct
exp_op
{
std
::
string
name
()
const
{
return
"cpu::exp"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
exp
(
x
);
};
}
};
struct
log_op
{
std
::
string
name
()
const
{
return
"cpu::log"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
log
(
x
);
};
}
};
struct
sin_op
{
std
::
string
name
()
const
{
return
"cpu::sin"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
sin
(
x
);
};
}
};
struct
cos_op
{
std
::
string
name
()
const
{
return
"cpu::cos"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
cos
(
x
);
};
}
};
struct
tan_op
{
std
::
string
name
()
const
{
return
"cpu::tan"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
tan
(
x
);
};
}
};
struct
asin_op
{
std
::
string
name
()
const
{
return
"cpu::asin"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
asin
(
x
);
};
}
};
struct
acos_op
{
std
::
string
name
()
const
{
return
"cpu::acos"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
acos
(
x
);
};
}
};
struct
atan_op
{
std
::
string
name
()
const
{
return
"cpu::atan"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
atan
(
x
);
};
}
};
struct
sinh_op
{
std
::
string
name
()
const
{
return
"cpu::sinh"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
sinh
(
x
);
};
}
};
struct
cosh_op
{
std
::
string
name
()
const
{
return
"cpu::cosh"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
cosh
(
x
);
};
}
};
struct
tanh_op
{
std
::
string
name
()
const
{
return
"cpu::tanh"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
tanh
(
x
);
};
}
};
struct
sigmoid_op
{
std
::
string
name
()
const
{
return
"cpu::sigmoid"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
1.
f
/
(
1.
f
+
std
::
exp
(
-
x
));
};
}
};
struct
neg_op
{
std
::
string
name
()
const
{
return
"cpu::neg"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
-
x
;
};
}
};
struct
relu_op
{
std
::
string
name
()
const
{
return
"cpu::relu"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
max
(
decltype
(
x
){
0
},
x
);
};
}
};
struct
leaky_relu_op
struct
leaky_relu_op
{
{
op
::
leaky_relu
op
;
op
::
leaky_relu
op
;
...
@@ -592,16 +474,45 @@ template <typename Op>
...
@@ -592,16 +474,45 @@ template <typename Op>
struct
cpu_unary
struct
cpu_unary
{
{
Op
op
;
Op
op
;
template
<
class
Self
,
class
F
>
static
auto
reflect
(
Self
&
self
,
F
f
)
{
return
migraphx
::
reflect
(
self
.
op
.
op
,
f
);
}
std
::
string
name
()
const
{
return
op
.
name
();
}
std
::
string
name
()
const
{
return
op
.
name
();
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
inputs
.
front
();
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
check_shapes
{
inputs
}.
has
(
1
);
auto
s
=
inputs
.
at
(
0
);
if
(
s
.
packed
())
{
return
s
;
}
else
{
return
{
s
.
type
(),
s
.
lens
()};
}
}
argument
compute
(
context
&
,
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
context
&
,
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
{
argument
result
{
output_shape
};
argument
result
{
output_shape
};
result
.
visit
([
&
](
auto
output
)
{
result
.
visit
([
&
](
auto
output
)
{
args
[
0
].
visit
([
&
](
auto
input
)
{
args
[
0
].
visit
([
&
](
auto
input
)
{
std
::
transform
(
input
.
begin
(),
input
.
end
(),
output
.
begin
(),
op
.
fcn
());
if
(
input
.
get_shape
().
standard
())
{
std
::
transform
(
input
.
begin
(),
input
.
end
(),
output
.
begin
(),
op
.
fcn
());
}
else
{
shape_for_each
(
output
.
get_shape
(),
[
&
](
const
auto
&
idx
)
{
output
(
idx
.
begin
(),
idx
.
end
())
=
op
.
fcn
()(
input
(
idx
.
begin
(),
idx
.
end
()));
});
}
});
});
});
});
return
result
;
return
result
;
}
}
};
};
...
@@ -621,20 +532,20 @@ struct softmax2d
...
@@ -621,20 +532,20 @@ struct softmax2d
auto
nw
=
input
.
get_shape
().
lens
()[
3
];
auto
nw
=
input
.
get_shape
().
lens
()[
3
];
dfor
(
nb
,
nh
,
nw
)([
&
](
std
::
size_t
b
,
std
::
size_t
i
,
std
::
size_t
j
)
{
dfor
(
nb
,
nh
,
nw
)([
&
](
std
::
size_t
b
,
std
::
size_t
i
,
std
::
size_t
j
)
{
value_type
cmax
=
std
::
numeric_limits
<
value_type
>::
lowest
();
value_type
cmax
=
std
::
numeric_limits
<
value_type
>::
lowest
();
for
(
in
t
c
=
0
;
c
<
nc
;
c
++
)
for
(
std
::
size_
t
c
=
0
;
c
<
nc
;
c
++
)
{
{
cmax
=
std
::
max
(
cmax
,
input
(
b
,
c
,
i
,
j
));
cmax
=
std
::
max
(
cmax
,
input
(
b
,
c
,
i
,
j
));
}
}
for
(
in
t
c
=
0
;
c
<
nc
;
c
++
)
for
(
std
::
size_
t
c
=
0
;
c
<
nc
;
c
++
)
{
{
output
(
b
,
c
,
i
,
j
)
=
std
::
exp
(
input
(
b
,
c
,
i
,
j
)
-
cmax
);
output
(
b
,
c
,
i
,
j
)
=
std
::
exp
(
input
(
b
,
c
,
i
,
j
)
-
cmax
);
}
}
value_type
sum
=
value_type
(
0
);
value_type
sum
=
value_type
(
0
);
for
(
in
t
c
=
0
;
c
<
nc
;
c
++
)
for
(
std
::
size_
t
c
=
0
;
c
<
nc
;
c
++
)
{
{
sum
+=
output
(
b
,
c
,
i
,
j
);
sum
+=
output
(
b
,
c
,
i
,
j
);
}
}
for
(
in
t
c
=
0
;
c
<
nc
;
c
++
)
for
(
std
::
size_
t
c
=
0
;
c
<
nc
;
c
++
)
{
{
output
(
b
,
c
,
i
,
j
)
=
output
(
b
,
c
,
i
,
j
)
/
sum
;
output
(
b
,
c
,
i
,
j
)
=
output
(
b
,
c
,
i
,
j
)
/
sum
;
}
}
...
@@ -647,6 +558,13 @@ struct softmax2d
...
@@ -647,6 +558,13 @@ struct softmax2d
struct
cpu_logsoftmax
struct
cpu_logsoftmax
{
{
op
::
logsoftmax
op
;
op
::
logsoftmax
op
;
template
<
class
Self
,
class
F
>
static
auto
reflect
(
Self
&
self
,
F
f
)
{
return
migraphx
::
reflect
(
self
.
op
,
f
);
}
std
::
string
name
()
const
{
return
"cpu::logsoftmax"
;
}
std
::
string
name
()
const
{
return
"cpu::logsoftmax"
;
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
...
@@ -713,87 +631,6 @@ struct cpu_logsoftmax
...
@@ -713,87 +631,6 @@ struct cpu_logsoftmax
}
}
};
};
struct
add_op
{
std
::
string
name
()
const
{
return
"add"
;
}
auto
fcn
()
const
{
return
[](
auto
x
,
auto
y
)
{
return
x
+
y
;
};
}
};
struct
sub_op
{
std
::
string
name
()
const
{
return
"sub"
;
}
auto
fcn
()
const
{
return
[](
auto
x
,
auto
y
)
{
return
x
-
y
;
};
}
};
struct
mul_op
{
std
::
string
name
()
const
{
return
"mul"
;
}
auto
fcn
()
const
{
return
[](
auto
x
,
auto
y
)
{
return
x
*
y
;
};
}
};
struct
div_op
{
std
::
string
name
()
const
{
return
"div"
;
}
auto
fcn
()
const
{
return
[](
auto
x
,
auto
y
)
{
return
x
/
y
;
};
}
};
struct
max_op
{
std
::
string
name
()
const
{
return
"max"
;
}
auto
fcn
()
const
{
return
[](
auto
x
,
auto
y
)
{
return
std
::
max
(
x
,
y
);
};
}
};
struct
min_op
{
std
::
string
name
()
const
{
return
"min"
;
}
auto
fcn
()
const
{
return
[](
auto
x
,
auto
y
)
{
return
std
::
min
(
x
,
y
);
};
}
};
template
<
typename
Op
>
struct
cpu_binary
{
Op
op
;
std
::
string
name
()
const
{
return
op
.
name
();
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
inputs
.
front
();
}
argument
compute
(
context
&
,
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
argument
result
{
output_shape
};
visit_all
(
result
,
args
[
0
],
args
[
1
])([
&
](
auto
output
,
auto
input1
,
auto
input2
)
{
if
(
input1
.
get_shape
().
packed
()
and
input2
.
get_shape
().
packed
())
{
std
::
transform
(
input1
.
begin
(),
input1
.
end
(),
input2
.
begin
(),
output
.
begin
(),
op
.
fcn
());
}
else
{
shape_for_each
(
output
.
get_shape
(),
[
&
](
const
auto
&
idx
)
{
output
(
idx
.
begin
(),
idx
.
end
())
=
op
.
fcn
()(
input1
(
idx
.
begin
(),
idx
.
end
()),
input2
(
idx
.
begin
(),
idx
.
end
()));
});
}
});
return
result
;
}
};
struct
cpu_apply
struct
cpu_apply
{
{
program
*
prog
;
program
*
prog
;
...
@@ -813,43 +650,17 @@ struct cpu_apply
...
@@ -813,43 +650,17 @@ struct cpu_apply
void
init
()
void
init
()
{
{
apply_map
[
"im2col"
]
=
extend_op
<
cpu_im2col
,
op
::
im2col
>
();
apply_map
[
"convolution"
]
=
extend_op
<
cpu_convolution
,
op
::
convolution
>
();
apply_map
[
"dot"
]
=
extend_op
<
cpu_gemm
,
op
::
dot
>
();
apply_map
[
"batch_norm_inference"
]
=
apply_map
[
"batch_norm_inference"
]
=
extend_op
<
cpu_batch_norm_inference
,
op
::
batch_norm_inference
>
();
extend_op
<
cpu_batch_norm_inference
,
op
::
batch_norm_inference
>
();
apply_map
[
"lrn"
]
=
extend_op
<
cpu_lrn
,
op
::
lrn
>
();
apply_map
[
"convolution"
]
=
extend_op
<
cpu_convolution
,
op
::
convolution
>
();
apply_map
[
"contiguous"
]
=
extend_op
<
cpu_contiguous
,
op
::
contiguous
>
();
apply_map
[
"dot"
]
=
extend_op
<
cpu_gemm
,
op
::
dot
>
();
apply_map
[
"pad"
]
=
extend_op
<
cpu_pad
,
op
::
pad
>
();
apply_map
[
"elu"
]
=
extend_op
<
cpu_unary
<
elu_op
>
,
op
::
elu
>
();
apply_map
[
"concat"
]
=
extend_op
<
cpu_concat
,
op
::
concat
>
();
apply_map
[
"im2col"
]
=
extend_op
<
cpu_im2col
,
op
::
im2col
>
();
apply_map
[
"gather"
]
=
extend_op
<
cpu_gather
,
op
::
gather
>
();
apply_map
[
"leaky_relu"
]
=
extend_op
<
cpu_unary
<
leaky_relu_op
>
,
op
::
leaky_relu
>
();
apply_map
[
"logsoftmax"
]
=
extend_op
<
cpu_logsoftmax
,
op
::
logsoftmax
>
();
apply_map
[
"logsoftmax"
]
=
extend_op
<
cpu_logsoftmax
,
op
::
logsoftmax
>
();
apply_map
[
"leaky_relu"
]
=
extend_op
<
cpu_unary
<
leaky_relu_op
>
,
op
::
leaky_relu
>
();
apply_map
[
"lrn"
]
=
extend_op
<
cpu_lrn
,
op
::
lrn
>
();
apply_map
[
"elu"
]
=
extend_op
<
cpu_unary
<
elu_op
>
,
op
::
elu
>
();
apply_map
[
"pad"
]
=
extend_op
<
cpu_pad
,
op
::
pad
>
();
apply_map
[
"identity"
]
=
simple_op
<
cpu_unary
<
identity_op
>>
();
apply_map
[
"softmax"
]
=
simple_op
<
softmax2d
>
();
apply_map
[
"abs"
]
=
simple_op
<
cpu_unary
<
abs_op
>>
();
apply_map
[
"sinh"
]
=
simple_op
<
cpu_unary
<
sinh_op
>>
();
apply_map
[
"cosh"
]
=
simple_op
<
cpu_unary
<
cosh_op
>>
();
apply_map
[
"tanh"
]
=
simple_op
<
cpu_unary
<
tanh_op
>>
();
apply_map
[
"sigmoid"
]
=
simple_op
<
cpu_unary
<
sigmoid_op
>>
();
apply_map
[
"exp"
]
=
simple_op
<
cpu_unary
<
exp_op
>>
();
apply_map
[
"log"
]
=
simple_op
<
cpu_unary
<
log_op
>>
();
apply_map
[
"neg"
]
=
simple_op
<
cpu_unary
<
neg_op
>>
();
apply_map
[
"sin"
]
=
simple_op
<
cpu_unary
<
sin_op
>>
();
apply_map
[
"cos"
]
=
simple_op
<
cpu_unary
<
cos_op
>>
();
apply_map
[
"tan"
]
=
simple_op
<
cpu_unary
<
tan_op
>>
();
apply_map
[
"asin"
]
=
simple_op
<
cpu_unary
<
asin_op
>>
();
apply_map
[
"acos"
]
=
simple_op
<
cpu_unary
<
acos_op
>>
();
apply_map
[
"atan"
]
=
simple_op
<
cpu_unary
<
atan_op
>>
();
apply_map
[
"relu"
]
=
simple_op
<
cpu_unary
<
relu_op
>>
();
apply_map
[
"add"
]
=
simple_op
<
cpu_binary
<
add_op
>>
();
apply_map
[
"sub"
]
=
simple_op
<
cpu_binary
<
sub_op
>>
();
apply_map
[
"mul"
]
=
simple_op
<
cpu_binary
<
mul_op
>>
();
apply_map
[
"div"
]
=
simple_op
<
cpu_binary
<
div_op
>>
();
apply_map
[
"max"
]
=
simple_op
<
cpu_binary
<
max_op
>>
();
apply_map
[
"min"
]
=
simple_op
<
cpu_binary
<
min_op
>>
();
apply_map
[
"softmax"
]
=
simple_op
<
softmax2d
>
();
}
}
void
apply
()
void
apply
()
...
@@ -865,9 +676,18 @@ struct cpu_apply
...
@@ -865,9 +676,18 @@ struct cpu_apply
{
{
apply_map
.
at
(
it
->
name
())(
it
);
apply_map
.
at
(
it
->
name
())(
it
);
}
}
else
if
(
is_context_free
(
it
->
get_operator
()))
{
apply_cpu_op
(
it
);
}
}
}
}
}
void
apply_cpu_op
(
instruction_ref
ins
)
{
prog
->
replace_instruction
(
ins
,
cpu_op
{
ins
->
get_operator
()},
ins
->
inputs
());
}
template
<
class
T
>
template
<
class
T
>
void
apply_simple_op
(
instruction_ref
ins
)
void
apply_simple_op
(
instruction_ref
ins
)
{
{
...
...
Prev
1
2
3
4
5
6
7
Next
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