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
264a7647
Commit
264a7647
authored
Jul 26, 2023
by
Brian Pickrell
Browse files
Merge branch 'develop' into multinomial_parse_merge
parents
d99729f8
8e18544f
Changes
269
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
374 additions
and
246 deletions
+374
-246
src/include/migraphx/stream_model.hpp
src/include/migraphx/stream_model.hpp
+3
-3
src/include/migraphx/target.hpp
src/include/migraphx/target.hpp
+8
-3
src/include/migraphx/tf.hpp
src/include/migraphx/tf.hpp
+4
-2
src/include/migraphx/tmp_dir.hpp
src/include/migraphx/tmp_dir.hpp
+1
-1
src/include/migraphx/value.hpp
src/include/migraphx/value.hpp
+9
-8
src/include/migraphx/verify.hpp
src/include/migraphx/verify.hpp
+2
-0
src/include/migraphx/verify_args.hpp
src/include/migraphx/verify_args.hpp
+1
-0
src/instruction.cpp
src/instruction.cpp
+3
-1
src/module.cpp
src/module.cpp
+4
-3
src/normalize_attributes.cpp
src/normalize_attributes.cpp
+32
-12
src/normalize_ops.cpp
src/normalize_ops.cpp
+1
-1
src/onnx/CMakeLists.txt
src/onnx/CMakeLists.txt
+2
-1
src/onnx/parse_batchnorm.cpp
src/onnx/parse_batchnorm.cpp
+11
-13
src/onnx/parse_conv_transpose.cpp
src/onnx/parse_conv_transpose.cpp
+39
-30
src/onnx/parse_instancenorm.cpp
src/onnx/parse_instancenorm.cpp
+9
-4
src/onnx/parse_shape.cpp
src/onnx/parse_shape.cpp
+53
-9
src/program.cpp
src/program.cpp
+139
-134
src/py/migraphx_py.cpp
src/py/migraphx_py.cpp
+7
-0
src/quantization.cpp
src/quantization.cpp
+5
-11
src/shape.cpp
src/shape.cpp
+41
-10
No files found.
src/include/migraphx/stream_model.hpp
View file @
264a7647
...
...
@@ -62,7 +62,7 @@ struct stream_model
#ifdef TYPE_ERASED_DECLARATION
// Type-erased interface for:
struct
stream_model
struct
MIGRAPHX_EXPORT
stream_model
{
//
std
::
size_t
get_nstream
()
const
;
...
...
@@ -100,7 +100,7 @@ struct stream_model
{
using
std
::
swap
;
auto
*
derived
=
this
->
any_cast
<
PrivateDetailTypeErasedT
>
();
if
(
derived
and
private_detail_te_handle_mem_var
.
u
nique
()
)
if
(
derived
and
private_detail_te_handle_mem_var
.
u
se_count
()
==
1
)
{
*
derived
=
std
::
forward
<
PrivateDetailTypeErasedT
>
(
value
);
}
...
...
@@ -288,7 +288,7 @@ struct stream_model
private_detail_te_handle_base_type
&
private_detail_te_get_handle
()
{
assert
(
private_detail_te_handle_mem_var
!=
nullptr
);
if
(
not
private_detail_te_handle_mem_var
.
u
nique
()
)
if
(
private_detail_te_handle_mem_var
.
u
se_count
()
>
1
)
private_detail_te_handle_mem_var
=
private_detail_te_handle_mem_var
->
clone
();
return
*
private_detail_te_handle_mem_var
;
}
...
...
src/include/migraphx/target.hpp
View file @
264a7647
...
...
@@ -45,6 +45,8 @@
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
struct
value
;
#ifdef DOXYGEN
/// An interface for a compilation target
...
...
@@ -125,7 +127,7 @@ supported_segments target_find_supported(T&, const_module_ref, support_metric)
#ifdef TYPE_ERASED_DECLARATION
// Type-erased interface for:
struct
target
struct
MIGRAPHX_EXPORT
target
{
//
std
::
string
name
()
const
;
...
...
@@ -165,7 +167,7 @@ struct target
{
using
std
::
swap
;
auto
*
derived
=
this
->
any_cast
<
PrivateDetailTypeErasedT
>
();
if
(
derived
and
private_detail_te_handle_mem_var
.
u
nique
()
)
if
(
derived
and
private_detail_te_handle_mem_var
.
u
se_count
()
==
1
)
{
*
derived
=
std
::
forward
<
PrivateDetailTypeErasedT
>
(
value
);
}
...
...
@@ -426,7 +428,7 @@ struct target
private_detail_te_handle_base_type
&
private_detail_te_get_handle
()
{
assert
(
private_detail_te_handle_mem_var
!=
nullptr
);
if
(
not
private_detail_te_handle_mem_var
.
u
nique
()
)
if
(
private_detail_te_handle_mem_var
.
u
se_count
()
>
1
)
private_detail_te_handle_mem_var
=
private_detail_te_handle_mem_var
->
clone
();
return
*
private_detail_te_handle_mem_var
;
}
...
...
@@ -467,6 +469,9 @@ inline const ValueType& any_cast(const target& x)
#endif
void
migraphx_to_value
(
value
&
v
,
const
target
&
t
);
void
migraphx_from_value
(
const
value
&
v
,
target
&
t
);
}
// namespace MIGRAPHX_INLINE_NS
}
// namespace migraphx
...
...
src/include/migraphx/tf.hpp
View file @
264a7647
...
...
@@ -26,6 +26,7 @@
#include <migraphx/program.hpp>
#include <migraphx/config.hpp>
#include <migraphx/tf/export.h>
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
...
...
@@ -41,9 +42,10 @@ struct tf_options
};
/// Create a program from a tf pb file (default is nhwc format)
program
parse_tf
(
const
std
::
string
&
name
,
const
tf_options
&
options
=
tf_options
{});
MIGRAPHX_TF_EXPORT
program
parse_tf
(
const
std
::
string
&
name
,
const
tf_options
&
options
=
tf_options
{});
std
::
vector
<
std
::
string
>
get_tf_operators
();
MIGRAPHX_TF_EXPORT
std
::
vector
<
std
::
string
>
get_tf_operators
();
}
// namespace MIGRAPHX_INLINE_NS
}
// namespace migraphx
...
...
src/include/migraphx/tmp_dir.hpp
View file @
264a7647
...
...
@@ -30,7 +30,7 @@
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
struct
tmp_dir
struct
MIGRAPHX_EXPORT
tmp_dir
{
fs
::
path
path
;
tmp_dir
(
const
std
::
string
&
prefix
=
""
);
...
...
src/include/migraphx/value.hpp
View file @
264a7647
...
...
@@ -32,6 +32,7 @@
#include <algorithm>
#include <cassert>
#include <memory>
#include <cstdint>
#include <sstream>
#include <type_traits>
#include <tuple>
...
...
@@ -140,7 +141,7 @@ To try_convert_value(const From& x)
return
detail
::
try_convert_value_impl
<
To
>
(
rank
<
3
>
{},
x
);
}
struct
value
struct
MIGRAPHX_EXPORT
value
{
// clang-format off
#define MIGRAPHX_VISIT_VALUE_TYPES(m) \
...
...
@@ -452,14 +453,14 @@ struct value
std
::
vector
<
literal_to_string
<
To
>>
{
default_value
.
begin
(),
default_value
.
end
()});
}
friend
bool
operator
==
(
const
value
&
x
,
const
value
&
y
);
friend
bool
operator
!=
(
const
value
&
x
,
const
value
&
y
);
friend
bool
operator
<
(
const
value
&
x
,
const
value
&
y
);
friend
bool
operator
<=
(
const
value
&
x
,
const
value
&
y
);
friend
bool
operator
>
(
const
value
&
x
,
const
value
&
y
);
friend
bool
operator
>=
(
const
value
&
x
,
const
value
&
y
);
MIGRAPHX_EXPORT
friend
bool
operator
==
(
const
value
&
x
,
const
value
&
y
);
MIGRAPHX_EXPORT
friend
bool
operator
!=
(
const
value
&
x
,
const
value
&
y
);
MIGRAPHX_EXPORT
friend
bool
operator
<
(
const
value
&
x
,
const
value
&
y
);
MIGRAPHX_EXPORT
friend
bool
operator
<=
(
const
value
&
x
,
const
value
&
y
);
MIGRAPHX_EXPORT
friend
bool
operator
>
(
const
value
&
x
,
const
value
&
y
);
MIGRAPHX_EXPORT
friend
bool
operator
>=
(
const
value
&
x
,
const
value
&
y
);
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
value
&
d
);
MIGRAPHX_EXPORT
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
value
&
d
);
std
::
size_t
hash
()
const
;
...
...
src/include/migraphx/verify.hpp
View file @
264a7647
...
...
@@ -35,6 +35,7 @@
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
namespace
verify
{
// Compute the value of a range
template
<
class
R
>
...
...
@@ -196,6 +197,7 @@ bool verify_range(const R1& r1, const R2& r2, double tolerance = 80, double* out
return
error
<=
threshold
;
}
}
// namespace verify
}
// namespace MIGRAPHX_INLINE_NS
}
// namespace migraphx
#endif
src/include/migraphx/verify_args.hpp
View file @
264a7647
...
...
@@ -31,6 +31,7 @@
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
MIGRAPHX_EXPORT
bool
verify_args
(
const
std
::
string
&
name
,
const
argument
&
ref_arg
,
const
argument
&
target_arg
,
...
...
src/instruction.cpp
View file @
264a7647
...
...
@@ -467,13 +467,15 @@ operation instruction::normalized_operator() const
if
(
this
->
need_normalization
())
{
auto
s
=
this
->
inputs
().
front
()
->
get_shape
();
if
(
not
normalize_attributes
(
o
,
s
.
max_lens
()
))
if
(
not
normalize_attributes
(
o
,
s
))
return
this
->
get_operator
();
}
return
o
;
}
std
::
size_t
instruction
::
get_target_id
()
const
{
return
target_id
;
}
void
instruction
::
set_target_id
(
std
::
size_t
tid
)
{
this
->
target_id
=
tid
;
}
std
::
vector
<
shape
>
to_shapes
(
const
std
::
vector
<
instruction_ref
>&
args
)
{
std
::
vector
<
shape
>
shapes
(
args
.
size
());
...
...
src/module.cpp
View file @
264a7647
...
...
@@ -652,8 +652,9 @@ instruction_ref module::find_dangling_reference() const
return
end
();
}
void
module
::
finalize
(
context
&
c
tx
)
void
module
::
finalize
(
std
::
vector
<
context
>
&
c
ontexts
)
{
assert
(
not
contexts
.
empty
());
const
bool
trace
=
enabled
(
MIGRAPHX_TRACE_FINALIZE
{});
for
(
auto
ins
:
iterator_for
(
*
this
))
{
...
...
@@ -662,10 +663,10 @@ void module::finalize(context& ctx)
std
::
cout
<<
"Finalize: "
;
this
->
debug_print
(
ins
);
}
ins
->
finalize
(
c
tx
);
ins
->
finalize
(
c
ontexts
[
ins
->
get_target_id
()]
);
for
(
const
auto
&
smod
:
ins
->
module_inputs
())
{
smod
->
finalize
(
c
tx
);
smod
->
finalize
(
c
ontexts
);
}
}
...
...
src/normalize_attributes.cpp
View file @
264a7647
/*
* The MIT License (MIT)
*
* Copyright (c) 2015-202
2
Advanced Micro Devices, Inc. All rights reserved.
* Copyright (c) 2015-202
3
Advanced Micro Devices, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
...
...
@@ -35,8 +35,9 @@ inline namespace MIGRAPHX_INLINE_NS {
* vec: the vector attribute to normalize
* axes: the operator's axes attribute if it exists, empty otherwise
* val: the normalize_axes key and options. Ex: normalize["axes"] =
* value::array{normalize_attribute::include_min}; lens: shape dimensions passed when calling
* normalize_attributes(op&, lens)
* value::array{normalize_attribute::include_min};
* input_shape: input shape passed when calling
* normalize_attributes(op&, input_shape)
*
* See normalize_attribute.hpp for explaining the options.
*/
...
...
@@ -44,11 +45,11 @@ template <class Message>
auto
tune_attribute
(
const
std
::
vector
<
int64_t
>&
vec
,
const
std
::
vector
<
int64_t
>&
axes
,
const
value
&
val
,
const
s
td
::
vector
<
std
::
size_t
>&
lens
,
const
s
hape
&
input_shape
,
Message
m
)
{
std
::
vector
<
int64_t
>
result
(
vec
);
int64_t
n_rank
=
lens
.
size
();
int64_t
n_rank
=
input_shape
.
ndim
();
std
::
vector
<
op
::
normalize_attribute
>
vec_attrs
=
val
.
to_vector
<
op
::
normalize_attribute
>
();
if
(
contains
(
vec_attrs
,
op
::
normalize_attribute
::
use_output
))
{
...
...
@@ -56,9 +57,28 @@ auto tune_attribute(const std::vector<int64_t>& vec,
}
std
::
vector
<
int64_t
>
max_vals
(
vec
.
size
(),
n_rank
);
if
(
contains
(
vec_attrs
,
op
::
normalize_attribute
::
use_len
))
{
std
::
transform
(
axes
.
begin
(),
axes
.
end
(),
max_vals
.
begin
(),
[
&
](
auto
i
)
{
return
lens
[
i
];
});
if
(
input_shape
.
dynamic
())
{
std
::
transform
(
axes
.
begin
(),
axes
.
end
(),
max_vals
.
begin
(),
[
&
](
auto
i
)
{
const
auto
&
dd
=
input_shape
.
dyn_dims
().
at
(
i
);
if
(
not
dd
.
is_fixed
())
{
MIGRAPHX_THROW
(
"NORMALIZE_ATTR: 'use_lens' on a non-fixed dynamic dimension, axis="
+
std
::
to_string
(
i
));
}
return
dd
.
max
;
});
}
else
{
std
::
transform
(
axes
.
begin
(),
axes
.
end
(),
max_vals
.
begin
(),
[
&
](
auto
i
)
{
return
input_shape
.
lens
().
at
(
i
);
});
}
}
if
(
contains
(
vec_attrs
,
op
::
normalize_attribute
::
clip_max
))
...
...
@@ -159,9 +179,9 @@ auto tune_pad_attribute(const value& val)
/**
* Assumptions:
* Dimensions to pad start from the third dimension (index 2).
* Called by compute_shape_op() with the
`lens`
of the first input.
* Called by compute_shape_op() with the
shape
of the first input.
*/
bool
normalize_attributes
(
operation
&
op
,
const
s
td
::
vector
<
std
::
size_t
>&
lens
)
bool
normalize_attributes
(
operation
&
op
,
const
s
hape
&
input_shape
)
{
bool
tuned
=
false
;
auto
attrs
=
op
.
attributes
();
...
...
@@ -172,9 +192,9 @@ bool normalize_attributes(operation& op, const std::vector<std::size_t>& lens)
auto
padding_size
=
padding
.
size
();
auto
padding_start
=
2
;
if
(
padding_size
==
2
*
(
lens
.
size
()
-
padding_start
))
if
(
padding_size
==
2
*
(
input_shape
.
ndim
()
-
padding_start
))
tuned
=
true
;
else
if
(
padding_size
!=
(
lens
.
size
()
-
padding_start
))
else
if
(
padding_size
!=
(
input_shape
.
ndim
()
-
padding_start
))
MIGRAPHX_THROW
(
"inconsistent padding size"
);
else
{
...
...
@@ -205,7 +225,7 @@ bool normalize_attributes(operation& op, const std::vector<std::size_t>& lens)
axes
=
val
.
at
(
"axes"
).
without_key
().
to_vector
<
int64_t
>
();
}
auto
vec
=
vv
.
to_vector
<
int64_t
>
();
auto
result
=
tune_attribute
(
vec
,
axes
,
rv
.
without_key
(),
lens
,
message
);
auto
result
=
tune_attribute
(
vec
,
axes
,
rv
.
without_key
(),
input_shape
,
message
);
val
[
key
]
=
result
;
op
.
from_value
(
val
);
val
=
op
.
to_value
();
...
...
@@ -214,7 +234,7 @@ bool normalize_attributes(operation& op, const std::vector<std::size_t>& lens)
else
{
auto
num
=
vv
.
to
<
int64_t
>
();
auto
result
=
tune_attribute
({
num
},
{
num
},
rv
.
without_key
(),
lens
,
message
);
auto
result
=
tune_attribute
({
num
},
{
num
},
rv
.
without_key
(),
input_shape
,
message
);
val
[
key
]
=
result
.
front
();
op
.
from_value
(
val
);
val
=
op
.
to_value
();
...
...
src/normalize_ops.cpp
View file @
264a7647
...
...
@@ -45,7 +45,7 @@ void normalize_ops::apply(module& m) const
auto
s
=
inputs
[
0
]
->
get_shape
();
migraphx
::
operation
tuned_op
=
ins
->
get_operator
();
if
(
normalize_attributes
(
tuned_op
,
s
.
max_lens
()
))
if
(
normalize_attributes
(
tuned_op
,
s
))
{
m
.
replace_instruction
(
ins
,
tuned_op
,
inputs
);
ins
->
set_normalized
();
...
...
src/onnx/CMakeLists.txt
View file @
264a7647
...
...
@@ -30,10 +30,11 @@ target_compile_options(onnx-proto PRIVATE -w)
target_link_libraries
(
onnx-proto PRIVATE
${
PROTOBUF_LIBRARY
}
)
set_target_properties
(
onnx-proto PROPERTIES POSITION_INDEPENDENT_CODE On
)
file
(
GLOB ONNX_SRCS
${
CONFIGURE_DEPENDS
}
*.cpp
)
file
(
GLOB ONNX_SRCS CONFIGURE_DEPENDS *.cpp
)
add_library
(
migraphx_onnx
${
ONNX_SRCS
}
)
target_include_directories
(
migraphx_onnx PRIVATE include
)
set_target_properties
(
migraphx_onnx PROPERTIES EXPORT_NAME onnx
)
migraphx_generate_export_header
(
migraphx_onnx
)
rocm_set_soversion
(
migraphx_onnx
${
MIGRAPHX_SO_VERSION
}
)
rocm_clang_tidy_check
(
migraphx_onnx
)
target_link_libraries
(
migraphx_onnx PRIVATE onnx-proto
"-Wl,--exclude-libs,ALL"
)
...
...
src/onnx/parse_batchnorm.cpp
View file @
264a7647
...
...
@@ -57,13 +57,12 @@ struct parse_batchnorm : op_parser<parse_batchnorm>
auto
x_rank
=
x_lens
.
size
();
if
(
x_rank
==
1
or
x_rank
==
2
)
{
auto
rt
=
info
.
add_literal
(
migraphx
::
literal
{
migraphx
::
shape
{
x_type
},
{
0.5
}});
auto
eps
=
info
.
add_literal
(
migraphx
::
literal
{
migraphx
::
shape
{
x_type
},
{
epsilon
}});
auto
numer
=
info
.
add_broadcastable_binary_op
(
"sub"
,
args
[
0
],
args
[
3
]);
auto
var_eps
=
info
.
add_broadcastable_binary_op
(
"add"
,
args
[
4
],
eps
);
auto
denom
=
info
.
add_broadcastable_binary_op
(
"pow"
,
var_eps
,
rt
);
auto
div0
=
info
.
add_broadcastable_binary_op
(
"div"
,
numer
,
denom
);
auto
r0
=
info
.
add_broadcastable_binary_op
(
"mul"
,
div0
,
args
[
1
]);
auto
eps
=
info
.
add_literal
(
migraphx
::
literal
{
migraphx
::
shape
{
x_type
},
{
epsilon
}});
auto
x_sub_mean
=
info
.
add_broadcastable_binary_op
(
"sub"
,
args
[
0
],
args
[
3
]);
auto
var_eps
=
info
.
add_broadcastable_binary_op
(
"add"
,
args
[
4
],
eps
);
auto
rsqrt
=
info
.
add_instruction
(
make_op
(
"rsqrt"
),
var_eps
);
auto
mul0
=
info
.
add_broadcastable_binary_op
(
"mul"
,
args
[
1
],
rsqrt
);
auto
r0
=
info
.
add_broadcastable_binary_op
(
"mul"
,
x_sub_mean
,
mul0
);
return
info
.
add_broadcastable_binary_op
(
"add"
,
r0
,
args
[
2
]);
}
else
if
(
x_rank
>
2
)
...
...
@@ -71,7 +70,6 @@ struct parse_batchnorm : op_parser<parse_batchnorm>
// unsqueeze tensors of shape (C) to broadcast correctly
std
::
vector
<
int64_t
>
unsqueeze_axes
(
x_lens
.
size
()
-
2
);
std
::
iota
(
unsqueeze_axes
.
begin
(),
unsqueeze_axes
.
end
(),
1
);
auto
rt
=
info
.
add_literal
(
migraphx
::
literal
{
migraphx
::
shape
{
x_type
},
{
0.5
}});
auto
eps
=
info
.
add_literal
(
migraphx
::
literal
{
migraphx
::
shape
{
x_type
},
{
epsilon
}});
auto
scale_unsqueeze
=
info
.
add_instruction
(
migraphx
::
make_op
(
"unsqueeze"
,
{{
"axes"
,
unsqueeze_axes
}}),
args
[
1
]);
...
...
@@ -81,11 +79,11 @@ struct parse_batchnorm : op_parser<parse_batchnorm>
migraphx
::
make_op
(
"unsqueeze"
,
{{
"axes"
,
unsqueeze_axes
}}),
args
[
3
]);
auto
var_unsqueeze
=
info
.
add_instruction
(
migraphx
::
make_op
(
"unsqueeze"
,
{{
"axes"
,
unsqueeze_axes
}}),
args
[
4
]);
auto
numer
=
info
.
add_broadcastable_binary_op
(
"sub"
,
args
[
0
],
mean_unsqueeze
);
auto
var_eps
=
info
.
add_broadcastable_binary_op
(
"add"
,
var_unsqueeze
,
eps
);
auto
denom
=
info
.
add_
broadcastable_binary_op
(
"pow"
,
var_eps
,
rt
);
auto
div0
=
info
.
add_broadcastable_binary_op
(
"
div"
,
numer
,
denom
);
auto
r0
=
info
.
add_broadcastable_binary_op
(
"mul"
,
div0
,
scale_unsqueeze
);
auto
x_sub_mean
=
info
.
add_broadcastable_binary_op
(
"sub"
,
args
[
0
],
mean_unsqueeze
);
auto
var_eps
=
info
.
add_broadcastable_binary_op
(
"add"
,
var_unsqueeze
,
eps
);
auto
rsqrt
=
info
.
add_
instruction
(
make_op
(
"rsqrt"
)
,
var_eps
);
auto
mul0
=
info
.
add_broadcastable_binary_op
(
"
mul"
,
scale_unsqueeze
,
rsqrt
);
auto
r0
=
info
.
add_broadcastable_binary_op
(
"mul"
,
x_sub_mean
,
mul0
);
return
info
.
add_broadcastable_binary_op
(
"add"
,
r0
,
bias_unsqueeze
);
}
else
...
...
src/onnx/parse_
de
conv
olution
.cpp
→
src/onnx/parse_conv
_transpose
.cpp
View file @
264a7647
...
...
@@ -42,7 +42,7 @@ std::vector<int64_t> to_int64_vector(const std::vector<T>& input_vector)
return
output_vector
;
}
struct
parse_
de
conv
olution
:
op_parser
<
parse_
de
conv
olution
>
struct
parse_conv
_transpose
:
op_parser
<
parse_conv
_transpose
>
{
std
::
vector
<
op_desc
>
operators
()
const
{
return
{{
"ConvTranspose"
}};
}
...
...
@@ -51,17 +51,15 @@ struct parse_deconvolution : op_parser<parse_deconvolution>
onnx_parser
::
node_info
info
,
std
::
vector
<
instruction_ref
>
args
)
const
{
operation
op
=
make_op
(
"
de
convolution"
);
operation
op
=
make_op
(
"convolution
_backwards
"
);
value
values
=
op
.
to_value
();
// op::deconvolution op;
auto
l0
=
args
[
0
];
auto
l0
=
args
[
0
];
std
::
vector
<
std
::
int64_t
>
padding
;
bool
asym_padding
=
false
;
auto
in_lens
=
l0
->
get_shape
().
lens
();
assert
(
in_lens
.
size
()
>
2
);
auto
kdims
=
in_lens
.
size
()
-
2
;
assert
(
l0
->
get_shape
().
ndim
()
>
2
);
auto
kdims
=
l0
->
get_shape
().
ndim
()
-
2
;
// ensure pads availabe only when auto_pad is "NOT_SET"
// ensure pads availab
l
e only when auto_pad is "NOT_SET"
check_padding_mode
(
info
,
"CONV_TRANSPOSE"
);
if
(
contains
(
info
.
attributes
,
"pads"
))
...
...
@@ -70,9 +68,9 @@ struct parse_deconvolution : op_parser<parse_deconvolution>
asym_padding
=
is_asym_padding
(
padding
);
size_t
pad_ndims
=
padding
.
size
()
/
2
;
if
(
not
asym_padding
)
{
size_t
pad_ndims
=
padding
.
size
()
/
2
;
check_attr_sizes
(
kdims
,
pad_ndims
,
"PARSE_CONV_TRANSPOSE: inconsistent paddings"
);
values
[
"padding"
].
clear
();
std
::
transform
(
padding
.
begin
(),
...
...
@@ -80,7 +78,19 @@ struct parse_deconvolution : op_parser<parse_deconvolution>
std
::
back_inserter
(
values
[
"padding"
]),
[](
auto
pad_val
)
{
return
pad_val
;
});
}
else
if
(
l0
->
get_shape
().
dynamic
())
{
MIGRAPHX_THROW
(
"PARSE_CONV_TRANSPOSE: asymmetric padding (padding_L != padding_R) "
"not supported with dynamic shapes"
);
}
else
{
// set padding to 0s, asym_padding handled by parser with slice
// TODO changing parser and op to do asym padding in op
values
[
"padding"
]
=
std
::
vector
<
std
::
size_t
>
(
pad_ndims
,
0
);
}
}
if
(
contains
(
info
.
attributes
,
"strides"
))
{
values
[
"stride"
].
clear
();
...
...
@@ -88,6 +98,7 @@ struct parse_deconvolution : op_parser<parse_deconvolution>
check_attr_sizes
(
kdims
,
values
[
"stride"
].
size
(),
"PARSE_CONV_TRANSPOSE: inconsistent strides"
);
}
if
(
contains
(
info
.
attributes
,
"dilations"
))
{
values
[
"dilation"
].
clear
();
...
...
@@ -97,21 +108,10 @@ struct parse_deconvolution : op_parser<parse_deconvolution>
}
// TODO: auto padding needs to be implemented for this parser and operator
if
(
contains
(
info
.
attributes
,
"auto_pad"
))
if
(
contains
(
info
.
attributes
,
"auto_pad"
)
and
to_upper
(
info
.
attributes
.
at
(
"auto_pad"
).
s
())
!=
"NOTSET"
)
{
auto
s
=
info
.
attributes
[
"auto_pad"
].
s
();
if
(
contains
(
info
.
attributes
,
"pads"
)
and
to_upper
(
s
)
!=
"NOTSET"
)
{
MIGRAPHX_THROW
(
"PARSE_CONV_TRANSPOSE: auto_pad and padding cannot be specified "
"simultaneously"
);
}
if
(
s
.
find
(
"SAME"
)
!=
std
::
string
::
npos
)
{
bool
is_same_upper
=
(
s
.
find
(
"SAME_UPPER"
)
!=
std
::
string
::
npos
);
values
[
"padding_mode"
]
=
is_same_upper
?
to_value
(
op
::
padding_mode_t
::
same_upper
)
:
to_value
(
op
::
padding_mode_t
::
same_lower
);
}
MIGRAPHX_THROW
(
"PARSE_CONV_TRANSPOSE: auto padding not supported"
);
}
if
(
contains
(
info
.
attributes
,
"group"
))
...
...
@@ -122,11 +122,11 @@ struct parse_deconvolution : op_parser<parse_deconvolution>
recalc_conv_attributes
(
values
,
kdims
);
op
.
from_value
(
values
);
auto
l1
=
info
.
add_instruction
(
op
,
l0
,
args
[
1
]);
std
::
vector
<
int64_t
>
dims
=
to_int64_vector
(
l1
->
get_shape
().
lens
());
std
::
vector
<
int64_t
>
curr_shape
(
dims
.
begin
()
+
2
,
dims
.
end
());
auto
l1
=
info
.
add_instruction
(
op
,
l0
,
args
[
1
]);
if
(
asym_padding
)
{
std
::
vector
<
int64_t
>
dims
=
to_int64_vector
(
l1
->
get_shape
().
lens
());
std
::
vector
<
int64_t
>
curr_shape
(
dims
.
begin
()
+
2
,
dims
.
end
());
std
::
vector
<
int64_t
>
axes
(
kdims
);
std
::
iota
(
axes
.
begin
(),
axes
.
end
(),
2
);
// ignore first 2 dims
...
...
@@ -144,9 +144,11 @@ struct parse_deconvolution : op_parser<parse_deconvolution>
make_op
(
"slice"
,
{{
"axes"
,
axes
},
{
"starts"
,
starts
},
{
"ends"
,
ends
}}),
l1
);
}
if
(
contains
(
info
.
attributes
,
"output_padding"
))
// TODO, should check output_padding < (strides or dilations)
if
(
contains
(
info
.
attributes
,
"output_padding"
)
and
not
contains
(
info
.
attributes
,
"output_shape"
))
{
size_t
non_kdims
=
dims
.
size
()
*
2
-
kdims
;
size_t
non_kdims
=
l1
->
get_shape
().
ndim
()
*
2
-
kdims
;
std
::
vector
<
int64_t
>
output_padding
(
non_kdims
,
0
);
copy
(
info
.
attributes
[
"output_padding"
].
ints
(),
std
::
back_inserter
(
output_padding
));
check_attr_sizes
(
kdims
,
...
...
@@ -155,14 +157,21 @@ struct parse_deconvolution : op_parser<parse_deconvolution>
l1
=
info
.
add_instruction
(
make_op
(
"pad"
,
{{
"pads"
,
output_padding
}}),
l1
);
}
// TODO, doing unnecessary calcuations with this. Could instead
// calculate the padding to conv_transpose that would give the output_shape.
if
(
contains
(
info
.
attributes
,
"output_shape"
))
{
if
(
l1
->
get_shape
().
dynamic
())
{
MIGRAPHX_THROW
(
"PARSE_CONV_TRANSPOSE: output_shape attribute and dynamic shapes "
"not supported"
);
}
std
::
vector
<
int64_t
>
dims
=
to_int64_vector
(
l1
->
get_shape
().
lens
());
std
::
vector
<
int64_t
>
curr_shape
(
dims
.
begin
()
+
2
,
dims
.
end
());
std
::
vector
<
int64_t
>
output_shape
;
copy
(
info
.
attributes
[
"output_shape"
].
ints
(),
std
::
back_inserter
(
output_shape
));
check_attr_sizes
(
kdims
,
output_shape
.
size
(),
"PARSE_CONV_TRANSPOSE: inconsistent output shape"
);
dims
=
to_int64_vector
(
l1
->
get_shape
().
lens
());
copy
(
dims
.
begin
()
+
2
,
dims
.
end
(),
curr_shape
.
begin
());
if
(
curr_shape
!=
output_shape
)
{
std
::
vector
<
int64_t
>
target_padding
(
dims
.
size
()
*
2
-
kdims
,
0
);
...
...
src/onnx/parse_instancenorm.cpp
View file @
264a7647
...
...
@@ -79,13 +79,11 @@ struct parse_instancenorm : op_parser<parse_instancenorm>
auto
x
=
args
[
0
];
auto
scale
=
args
[
1
];
auto
bias
=
args
[
2
];
auto
dims
=
x
->
get_shape
().
lens
();
if
(
not
contains
(
valid_types
,
dtype
))
MIGRAPHX_THROW
(
opd
.
op_name
+
": invalid output type: "
+
std
::
to_string
(
dtype
)
+
". Valid types are 1 (float), 10 (half), and 11 (double)."
);
bool
dyn_input
=
x
->
get_shape
().
dynamic
();
auto
ndims
=
x
->
get_shape
().
ndim
();
auto
ndims
=
x
->
get_shape
().
ndim
();
assert
(
ndims
>=
2
);
auto
kdims
=
ndims
-
2
;
std
::
vector
<
int64_t
>
axes
(
kdims
);
...
...
@@ -102,6 +100,12 @@ struct parse_instancenorm : op_parser<parse_instancenorm>
(
dtype
==
shape
::
half_type
and
not
convert_fp16
)
?
"reduce_sum"
:
"reduce_mean"
;
if
(
dtype
==
shape
::
half_type
and
not
convert_fp16
)
{
if
(
x
->
get_shape
().
dynamic
())
{
MIGRAPHX_THROW
(
"PARSE_INSTANCENORM: half type not supported with dynamic shape "
"unless convert_fp16 is TRUE"
);
}
auto
dims
=
x
->
get_shape
().
lens
();
double
n
=
std
::
accumulate
(
dims
.
begin
()
+
2
,
dims
.
end
(),
1
,
[
&
](
const
auto
&
i
,
const
auto
&
j
)
{
return
i
*
j
;
...
...
@@ -122,13 +126,14 @@ struct parse_instancenorm : op_parser<parse_instancenorm>
// both scale and bias.
instruction_ref
scale_bcast
;
instruction_ref
bias_bcast
;
if
(
dyn_input
)
if
(
x
->
get_shape
().
dynamic
()
)
{
scale_bcast
=
info
.
add_instruction
(
make_op
(
"broadcast"
,
{{
"axis"
,
1
}}),
scale
,
x
);
bias_bcast
=
info
.
add_instruction
(
make_op
(
"broadcast"
,
{{
"axis"
,
1
}}),
bias
,
x
);
}
else
{
auto
dims
=
x
->
get_shape
().
lens
();
scale_bcast
=
info
.
add_instruction
(
make_op
(
"broadcast"
,
{{
"axis"
,
1
},
{
"out_lens"
,
dims
}}),
scale
);
bias_bcast
=
...
...
src/onnx/parse_shape.cpp
View file @
264a7647
...
...
@@ -30,8 +30,11 @@ namespace migraphx {
inline
namespace
MIGRAPHX_INLINE_NS
{
namespace
onnx
{
// Use a literal instruction to replace the shape since, output of
// shape operator are literals in migraphx
/**
* If static shape input, creates a literal in migraphx.
* If dynamic shape input, creates a dimensions_of operator in migraphx (runtime evaluation of
* shape).
*/
struct
parse_shape
:
op_parser
<
parse_shape
>
{
std
::
vector
<
op_desc
>
operators
()
const
{
return
{{
"Shape"
}};
}
...
...
@@ -43,13 +46,54 @@ struct parse_shape : op_parser<parse_shape>
{
if
(
args
.
size
()
!=
1
)
MIGRAPHX_THROW
(
"Shape: operator should have 1 operand"
);
std
::
vector
<
std
::
size_t
>
arg_shape
=
args
[
0
]
->
get_shape
().
lens
();
std
::
vector
<
int64_t
>
vec_shape
(
arg_shape
.
size
());
migraphx
::
shape
s
(
migraphx
::
shape
::
int64_type
,
{
arg_shape
.
size
()});
std
::
transform
(
arg_shape
.
begin
(),
arg_shape
.
end
(),
vec_shape
.
begin
(),
[](
auto
i
)
{
return
int64_t
(
i
);
});
return
info
.
add_literal
(
migraphx
::
literal
{
s
,
vec_shape
});
auto
input_shape
=
args
[
0
]
->
get_shape
();
int
input_ndim
=
input_shape
.
ndim
();
std
::
size_t
start
=
0
;
std
::
size_t
end
=
input_ndim
;
// Normalizing the start and end is handled here because of how the static shape version
// works. Clamping to [-r, r], where r is ndim of input and then making positive.
auto
normalize_ind
=
[
&
](
int64_t
ind
)
{
if
(
ind
<
(
-
1
*
input_ndim
))
{
ind
=
-
1
*
input_ndim
;
}
if
(
ind
>
input_ndim
)
{
ind
=
input_ndim
;
}
return
(
ind
>=
0
)
?
ind
:
input_ndim
+
ind
;
};
if
(
contains
(
info
.
attributes
,
"end"
))
{
end
=
normalize_ind
(
info
.
attributes
.
at
(
"end"
).
i
());
}
if
(
contains
(
info
.
attributes
,
"start"
))
{
start
=
normalize_ind
(
info
.
attributes
.
at
(
"start"
).
i
());
}
if
(
end
<=
start
)
{
MIGRAPHX_THROW
(
"PARSE_SHAPE: ending axis <= starting axis, end: "
+
std
::
to_string
(
end
)
+
" start: "
+
std
::
to_string
(
start
));
}
if
(
input_shape
.
dynamic
())
{
return
info
.
add_instruction
(
make_op
(
"dimensions_of"
,
{{
"start"
,
start
},
{
"end"
,
end
}}),
args
[
0
]);
}
else
{
std
::
size_t
output_ndim
=
end
-
start
;
std
::
vector
<
int64_t
>
vec_shape
(
output_ndim
);
migraphx
::
shape
s
(
migraphx
::
shape
::
int64_type
,
{
output_ndim
});
std
::
vector
<
std
::
size_t
>
input_lens
=
input_shape
.
lens
();
std
::
transform
(
input_lens
.
begin
()
+
start
,
input_lens
.
begin
()
+
end
,
vec_shape
.
begin
(),
[](
auto
i
)
{
return
int64_t
(
i
);
});
return
info
.
add_literal
(
migraphx
::
literal
{
s
,
vec_shape
});
}
}
};
...
...
src/program.cpp
View file @
264a7647
...
...
@@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <migraphx/version.h>
#include <migraphx/compile_options.hpp>
#include <migraphx/program.hpp>
#include <migraphx/stringutils.hpp>
...
...
@@ -70,9 +71,8 @@ struct program_impl
{
// A map is used to keep references to modules of the program
std
::
unordered_map
<
std
::
string
,
module
>
modules
;
context
ctx
;
std
::
string
target_name
;
std
::
vector
<
context
>
contexts
;
std
::
vector
<
target
>
targets
;
};
program
::
program
()
:
impl
(
std
::
make_unique
<
program_impl
>
())
{
this
->
create_module
(
"main"
);
}
...
...
@@ -96,14 +96,8 @@ void program::assign(const program& p)
{
impl
=
std
::
make_unique
<
program_impl
>
();
}
else
if
(
not
impl
->
modules
.
empty
())
{
impl
->
modules
.
clear
();
}
impl
->
ctx
=
p
.
impl
->
ctx
;
impl
->
target_name
=
p
.
impl
->
target_name
;
impl
->
modules
=
p
.
impl
->
modules
;
*
impl
=
*
p
.
impl
;
// build a map from old ins to new ins
// Build a map from old module to new module
...
...
@@ -166,7 +160,11 @@ std::vector<shape> program::get_output_shapes() const
return
mm
->
get_output_shapes
();
}
context
&
program
::
get_context
()
const
{
return
impl
->
ctx
;
}
context
&
program
::
get_context
()
const
{
assert
(
impl
->
contexts
.
size
()
==
1
);
return
impl
->
contexts
.
front
();
}
instruction_ref
program
::
validate
()
const
{
...
...
@@ -217,7 +215,7 @@ target_assignments program::get_target_assignments(const std::vector<target>& ta
return
p
;
}
bool
program
::
is_compiled
()
const
{
return
not
this
->
impl
->
target_name
.
empty
();
}
bool
program
::
is_compiled
()
const
{
return
not
this
->
impl
->
contexts
.
empty
();
}
void
program
::
compile
(
const
std
::
vector
<
target
>&
targets
,
std
::
vector
<
compile_options
>
compile_opts
)
{
...
...
@@ -299,24 +297,24 @@ void program::compile(const std::vector<target>& targets, std::vector<compile_op
MIGRAPHX_THROW
(
"Dangling reference in module "
+
current_mod
->
name
()
+
" from instruction "
+
std
::
to_string
(
index
));
}
current_mod
->
finalize
(
this
->
impl
->
contexts
[
root_target_id
]);
}
}
this
->
finalize
();
}
void
program
::
compile
(
const
target
&
t
,
compile_options
options
)
{
// todo: combine with multi-target compile method
assert
(
not
this
->
is_compiled
());
this
->
impl
->
target
_name
=
t
.
name
()
;
this
->
impl
->
c
tx
=
t
.
get_context
();
this
->
impl
->
target
s
=
{
t
}
;
this
->
impl
->
c
ontexts
=
{
t
.
get_context
()
}
;
if
(
enabled
(
MIGRAPHX_TRACE_COMPILE
{}))
options
.
trace
=
tracer
{
std
::
cout
};
options
.
trace
(
*
this
);
options
.
trace
();
auto
&&
passes
=
t
.
get_passes
(
this
->
impl
->
c
tx
,
options
);
auto
&&
passes
=
t
.
get_passes
(
this
->
impl
->
c
ontexts
.
front
()
,
options
);
run_passes
(
*
this
,
passes
,
options
.
trace
);
auto
mods
=
this
->
get_modules
();
// Validate and finalize
...
...
@@ -335,14 +333,14 @@ void program::compile(const target& t, compile_options options)
MIGRAPHX_THROW
(
"Dangling reference in module "
+
mod
->
name
()
+
" from instruction "
+
std
::
to_string
(
index
));
}
mod
->
finalize
(
this
->
impl
->
c
tx
);
mod
->
finalize
(
this
->
impl
->
c
ontexts
);
}
}
void
program
::
finalize
()
{
auto
*
mm
=
this
->
get_main_module
();
mm
->
finalize
(
this
->
impl
->
c
tx
);
mm
->
finalize
(
this
->
impl
->
c
ontexts
);
}
template
<
class
T
>
...
...
@@ -429,16 +427,15 @@ void preview_argument(std::ostream& os, const argument& a)
template
<
class
F
>
std
::
vector
<
argument
>
generic_eval
(
const
module
*
mod
,
context
&
ctx
,
std
::
vector
<
context
>
&
ctx
,
std
::
unordered_map
<
std
::
string
,
argument
>
params
,
std
::
unordered_map
<
instruction_ref
,
argument
>
results
,
F
make_
trace
)
F
trace
)
{
assert
(
mod
->
validate
()
==
mod
->
end
());
results
.
reserve
(
mod
->
size
()
*
2
);
std
::
vector
<
argument
>
values
;
values
.
reserve
(
16
);
auto
trace
=
make_trace
(
mod
);
for
(
auto
ins
:
iterator_for
(
*
mod
))
{
assert
(
results
.
find
(
ins
)
==
results
.
end
());
...
...
@@ -494,14 +491,19 @@ std::vector<argument> generic_eval(const module* mod,
const
auto
&
mod_args
=
ins
->
module_inputs
();
auto
module_eval
=
[
&
](
module_ref
smod
,
const
std
::
unordered_map
<
std
::
string
,
argument
>&
inputs
)
{
auto
ssctx
=
ctx
;
return
generic_eval
(
smod
,
ssctx
,
inputs
,
results
,
make_trace
);
return
generic_eval
(
smod
,
ctx
,
inputs
,
results
,
trace
);
};
results
.
emplace
(
ins
,
trace
(
ins
,
[
&
]
{
return
ins
->
normalized_operator
().
compute
(
ctx
,
ins
->
get_shape
(),
values
,
mod_args
,
module_eval
);
}));
results
.
emplace
(
ins
,
trace
(
ins
,
[
&
]
{
auto
op
=
ins
->
normalized_operator
();
if
(
op
.
is_context_free
())
return
op
.
compute
(
ins
->
get_shape
(),
values
,
mod_args
,
module_eval
);
if
(
ins
->
get_target_id
()
>=
ctx
.
size
())
MIGRAPHX_THROW
(
"No context available for "
+
op
.
name
());
return
op
.
compute
(
ctx
[
ins
->
get_target_id
()],
ins
->
get_shape
(),
values
,
mod_args
,
module_eval
);
}));
}
assert
(
results
.
find
(
ins
)
!=
results
.
end
());
if
(
not
ins
->
get_shape
().
any_of_dynamic
())
...
...
@@ -514,44 +516,25 @@ std::vector<argument> generic_eval(const module* mod,
template
<
class
F
>
std
::
vector
<
argument
>
generic_eval
(
const
program
&
p
,
context
&
ctx
,
std
::
vector
<
context
>
&
ctx
,
std
::
unordered_map
<
std
::
string
,
argument
>
params
,
F
make_
trace
)
F
trace
)
{
const
module
*
mm
=
p
.
get_main_module
();
return
generic_eval
(
mm
,
ctx
,
params
,
{},
make_
trace
);
return
generic_eval
(
mm
,
ctx
,
params
,
{},
trace
);
}
std
::
vector
<
argument
>
program
::
eval
(
parameter_map
params
,
execution_environment
exec_env
)
const
{
auto
&
ctx
=
this
->
impl
->
ctx
;
#ifndef NDEBUG
auto
with_check_context
=
[
&
](
auto
f
)
{
return
[
=
,
&
ctx
](
auto
&&
)
{
auto
sctx
=
std
::
make_shared
<
context
>
(
ctx
);
auto
check_context
=
[
=
,
&
ctx
](
auto
g
)
{
assert
(
is_shared
(
ctx
,
*
sctx
));
auto
x
=
g
();
*
sctx
=
ctx
;
return
x
;
};
return
[
=
](
auto
&&
...
xs
)
{
return
f
(
xs
...,
check_context
);
};
};
};
#else
auto
with_check_context
=
[](
auto
f
)
{
return
[
=
](
auto
&&
)
{
return
[
=
](
auto
&&
...
xs
)
{
return
f
(
xs
...,
[](
auto
g
)
{
return
g
();
});
};
};
};
#endif
auto
&
contexts
=
this
->
impl
->
contexts
;
auto
trace_level
=
value_of
(
MIGRAPHX_TRACE_EVAL
{});
std
::
vector
<
argument
>
ret
;
if
(
exec_env
.
async
)
{
ctx
.
wait_for
(
exec_env
.
queue
);
assert
(
contexts
.
size
()
==
1
);
contexts
.
front
().
wait_for
(
exec_env
.
queue
);
}
if
(
trace_level
>
0
)
...
...
@@ -563,85 +546,93 @@ std::vector<argument> program::eval(parameter_map params, execution_environment
instruction
::
print
(
ss
,
x
,
ins_names
);
ins_out
[
x
]
=
ss
.
str
();
});
ret
=
generic_eval
(
*
this
,
ctx
,
std
::
move
(
params
),
with_check_context
([
&
](
auto
&
ins
,
auto
f
,
auto
&&
check_context
)
{
ctx
.
finish
();
std
::
cout
<<
"Run instruction: "
<<
ins_out
.
at
(
ins
)
<<
std
::
endl
;
timer
t
{};
auto
result
=
check_context
(
f
);
double
t1
=
t
.
record
<
milliseconds
>
();
ctx
.
finish
();
double
t2
=
t
.
record
<
milliseconds
>
();
std
::
cout
<<
"Time: "
<<
t1
<<
"ms, "
<<
t2
<<
"ms"
<<
std
::
endl
;
if
(
trace_level
>
1
and
ins
->
name
().
front
()
!=
'@'
and
ins
->
name
()
!=
"load"
and
not
result
.
empty
())
ret
=
generic_eval
(
*
this
,
contexts
,
std
::
move
(
params
),
[
&
](
instruction_ref
ins
,
auto
f
)
{
auto
&
ctx
=
contexts
[
ins
->
get_target_id
()];
ctx
.
finish
();
std
::
cout
<<
"Run instruction: "
<<
ins_out
.
at
(
ins
)
<<
std
::
endl
;
timer
t
{};
auto
result
=
f
();
double
t1
=
t
.
record
<
milliseconds
>
();
ctx
.
finish
();
double
t2
=
t
.
record
<
milliseconds
>
();
std
::
cout
<<
"Time: "
<<
t1
<<
"ms, "
<<
t2
<<
"ms"
<<
std
::
endl
;
if
(
trace_level
>
1
and
ins
->
name
().
front
()
!=
'@'
and
ins
->
name
()
!=
"load"
and
not
result
.
empty
())
{
migraphx
::
argument
buffer
;
try
{
migraphx
::
argument
buffer
;
try
{
target
tgt
=
make_target
(
this
->
impl
->
target_name
);
buffer
=
tgt
.
copy_from
(
result
);
}
catch
(
const
migraphx
::
exception
&
)
{
// instruction was run on host then no need to copy buffer from target
buffer
=
result
;
}
catch
(...)
{
MIGRAPHX_THROW
(
"MIGraphX program execution with MIGRAPHX_TRACE_EVAL failed.
\n
"
);
}
if
(
trace_level
==
2
)
{
std
::
cout
<<
"Output has "
<<
to_string_range
(
classify_argument
(
buffer
))
<<
std
::
endl
;
std
::
cout
<<
"Output: "
;
preview_argument
(
std
::
cout
,
buffer
);
std
::
cout
<<
std
::
endl
;
print_statistics
(
std
::
cout
,
buffer
);
}
else
{
std
::
cout
<<
"Output: "
<<
buffer
<<
std
::
endl
;
}
const
target
&
tgt
=
this
->
impl
->
targets
.
at
(
ins
->
get_target_id
());
buffer
=
tgt
.
copy_from
(
result
);
}
return
result
;
}));
catch
(
const
migraphx
::
exception
&
)
{
// instruction was run on host then no need to copy buffer from target
buffer
=
result
;
}
catch
(...)
{
MIGRAPHX_THROW
(
"MIGraphX program execution with MIGRAPHX_TRACE_EVAL failed.
\n
"
);
}
if
(
trace_level
==
2
)
{
std
::
cout
<<
"Output has "
<<
to_string_range
(
classify_argument
(
buffer
))
<<
std
::
endl
;
std
::
cout
<<
"Output: "
;
preview_argument
(
std
::
cout
,
buffer
);
std
::
cout
<<
std
::
endl
;
print_statistics
(
std
::
cout
,
buffer
);
}
else
{
std
::
cout
<<
"Output: "
<<
buffer
<<
std
::
endl
;
}
}
return
result
;
});
}
else
{
ret
=
generic_eval
(
*
this
,
ctx
,
std
::
move
(
params
),
with_check_context
([
&
](
auto
&
,
auto
f
,
auto
&&
check_context
)
{
return
check_context
(
f
);
}));
ret
=
generic_eval
(
*
this
,
contexts
,
std
::
move
(
params
),
[
&
](
auto
&&
,
auto
f
)
{
return
f
();
});
}
if
(
exec_env
.
async
)
{
ctx
.
finish_on
(
exec_env
.
queue
);
assert
(
contexts
.
size
()
==
1
);
contexts
.
front
().
finish_on
(
exec_env
.
queue
);
}
return
ret
;
}
const
int
program_file_version
=
5
;
void
program
::
finish
()
const
{
for
(
const
auto
&
ctx
:
this
->
impl
->
contexts
)
ctx
.
finish
();
}
std
::
string
get_migraphx_version
()
{
std
::
stringstream
ss
;
ss
<<
std
::
to_string
(
MIGRAPHX_VERSION_MAJOR
)
<<
"."
<<
std
::
to_string
(
MIGRAPHX_VERSION_MINOR
)
<<
"."
<<
std
::
to_string
(
MIGRAPHX_VERSION_PATCH
);
return
ss
.
str
();
}
/*
program file version is for the data structure or format of the MXR file. Version should be bumped
if any changes occur to the format of the MXR file.
*/
const
int
program_file_version
=
6
;
value
program
::
to_value
()
const
{
value
result
;
result
[
"version"
]
=
program_file_version
;
result
[
"target"
]
=
this
->
impl
->
target_name
;
if
(
not
this
->
impl
->
target_name
.
empty
())
result
[
"context"
]
=
this
->
impl
->
ctx
.
to_value
();
value
module_vals
=
value
::
object
{};
result
[
"version"
]
=
program_file_version
;
result
[
"migraphx_version"
]
=
get_migraphx_version
();
result
[
"targets"
]
=
migraphx
::
to_value
(
this
->
impl
->
targets
);
result
[
"contexts"
]
=
migraphx
::
to_value
(
this
->
impl
->
contexts
);
value
module_vals
=
value
::
object
{};
std
::
unordered_map
<
instruction_ref
,
std
::
string
>
names
;
for
(
auto
&
mod
:
this
->
get_modules
())
{
...
...
@@ -765,15 +756,27 @@ void program::from_value(const value& v)
auto
version
=
v
.
at
(
"version"
).
to
<
int
>
();
if
(
version
!=
program_file_version
)
{
MIGRAPHX_THROW
(
"Warning: Program version mismatch"
);
MIGRAPHX_THROW
(
"Error: Program version mismatch. MXR file was created using program file version: "
+
std
::
to_string
(
version
)
+
", while installed MIGraphX is using program file version: "
+
std
::
to_string
(
program_file_version
)
+
", Try regenerating MXR file using installed MIGraphX and running again."
);
}
this
->
impl
->
target_name
=
v
.
at
(
"target"
).
to
<
std
::
string
>
();
if
(
not
this
->
impl
->
target_name
.
empty
())
auto
migx_version
=
v
.
at
(
"migraphx_version"
).
to
<
std
::
string
>
();
if
(
migx_version
!=
get_migraphx_version
())
{
std
::
cout
<<
"WARNING: MXR File was created using MIGraphX version: "
<<
migx_version
<<
", while installed MIGraphX is at version: "
<<
get_migraphx_version
()
<<
", operators implementation could be mismatched."
;
}
migraphx
::
from_value
(
v
.
at
(
"targets"
),
this
->
impl
->
targets
);
for
(
auto
i
:
range
(
this
->
impl
->
targets
.
size
()))
{
target
t
=
make_target
(
this
->
impl
->
target_name
);
this
->
impl
->
ctx
=
t
.
get_context
();
this
->
impl
->
ctx
.
from_value
(
v
.
at
(
"context"
));
this
->
impl
->
contexts
.
push_back
(
this
->
impl
->
targets
[
i
].
get_context
());
this
->
impl
->
contexts
.
back
().
from_value
(
v
.
at
(
"contexts"
)[
i
]);
}
auto
module_vals
=
v
.
at
(
"modules"
);
...
...
@@ -794,7 +797,9 @@ void program::from_value(const value& v)
auto
*
mm
=
get_main_module
();
mod_from_val
(
mm
,
module_vals
,
map_insts
,
map_mods
);
this
->
finalize
();
// Finalize a compiled model
if
(
not
this
->
impl
->
contexts
.
empty
())
this
->
finalize
();
}
double
common_average
(
const
std
::
vector
<
double
>&
v
)
...
...
@@ -814,19 +819,19 @@ std::string perf_group(const operation& op)
void
program
::
mark
(
const
parameter_map
&
params
,
marker
&&
m
)
{
auto
&
ctx
=
this
->
impl
->
c
tx
;
auto
&
ctx
=
this
->
impl
->
c
ontexts
;
// Run once by itself
eval
(
params
);
ctx
.
finish
();
this
->
finish
();
// Start marking
m
.
mark_start
(
*
this
);
generic_eval
(
*
this
,
ctx
,
params
,
always
(
[
&
](
auto
ins
,
auto
f
)
{
generic_eval
(
*
this
,
ctx
,
params
,
[
&
](
auto
ins
,
auto
f
)
{
argument
result
;
m
.
mark_start
(
ins
);
result
=
f
();
m
.
mark_stop
(
ins
);
return
result
;
})
)
;
});
m
.
mark_stop
(
*
this
);
}
...
...
@@ -835,10 +840,10 @@ void program::perf_report(std::ostream& os,
parameter_map
params
,
std
::
size_t
batch
)
const
{
auto
&
ctx
=
this
->
impl
->
c
tx
;
auto
&
ctx
=
this
->
impl
->
c
ontexts
;
// Run once by itself
eval
(
params
);
ctx
.
finish
();
this
->
finish
();
// Run and time entire program
std
::
vector
<
double
>
total_vec
;
total_vec
.
reserve
(
n
);
...
...
@@ -846,28 +851,28 @@ void program::perf_report(std::ostream& os,
{
total_vec
.
push_back
(
time
<
milliseconds
>
([
&
]
{
eval
(
params
);
ctx
.
finish
();
this
->
finish
();
}));
}
std
::
sort
(
total_vec
.
begin
(),
total_vec
.
end
());
std
::
unordered_map
<
instruction_ref
,
std
::
vector
<
double
>>
ins_vec
;
// Fill the map
generic_eval
(
*
this
,
ctx
,
params
,
always
(
[
&
](
auto
ins
,
auto
)
{
generic_eval
(
*
this
,
ctx
,
params
,
[
&
](
auto
ins
,
auto
)
{
ins_vec
[
ins
].
reserve
(
n
);
return
argument
{
ins
->
get_shape
(),
nullptr
};
})
)
;
});
// Run and time each instruction
for
(
std
::
size_t
i
=
0
;
i
<
n
;
i
++
)
{
generic_eval
(
*
this
,
ctx
,
params
,
always
(
[
&
](
auto
ins
,
auto
f
)
{
generic_eval
(
*
this
,
ctx
,
params
,
[
&
](
auto
ins
,
auto
f
)
{
argument
result
;
ins_vec
[
ins
].
push_back
(
time
<
milliseconds
>
([
&
]
{
result
=
f
();
ctx
.
finish
();
this
->
impl
->
contexts
[
ins
->
get_target_id
()]
.
finish
();
}));
return
result
;
})
)
;
});
}
for
(
auto
&&
p
:
ins_vec
)
std
::
sort
(
p
.
second
.
begin
(),
p
.
second
.
end
());
...
...
@@ -1035,10 +1040,10 @@ void program::print_cpp(std::ostream& os) const
void
program
::
dry_run
(
std
::
unordered_map
<
std
::
string
,
argument
>
params
)
const
{
auto
&
ctx
=
this
->
impl
->
c
tx
;
generic_eval
(
*
this
,
ctx
,
std
::
move
(
params
),
always
(
[](
auto
ins
,
auto
&&
...)
{
auto
&
ctx
=
this
->
impl
->
c
ontexts
;
generic_eval
(
*
this
,
ctx
,
std
::
move
(
params
),
[](
auto
ins
,
auto
&&
...)
{
return
argument
{
ins
->
get_shape
(),
nullptr
};
})
)
;
});
}
void
program
::
annotate
(
std
::
ostream
&
os
,
const
std
::
function
<
void
(
instruction_ref
)
>&
a
)
const
...
...
src/py/migraphx_py.cpp
View file @
264a7647
...
...
@@ -547,6 +547,13 @@ MIGRAPHX_PYBIND11_MODULE(migraphx, m)
py
::
arg
(
"format"
)
=
"msgpack"
);
m
.
def
(
"get_target"
,
&
migraphx
::
make_target
);
m
.
def
(
"create_argument"
,
[](
const
migraphx
::
shape
&
s
,
const
std
::
vector
<
double
>&
values
)
{
if
(
values
.
size
()
!=
s
.
elements
())
MIGRAPHX_THROW
(
"Values and shape elements do not match"
);
migraphx
::
argument
a
{
s
};
a
.
fill
(
values
.
begin
(),
values
.
end
());
return
a
;
});
m
.
def
(
"generate_argument"
,
&
migraphx
::
generate_argument
,
py
::
arg
(
"s"
),
py
::
arg
(
"seed"
)
=
0
);
m
.
def
(
"fill_argument"
,
&
migraphx
::
fill_argument
,
py
::
arg
(
"s"
),
py
::
arg
(
"value"
));
m
.
def
(
"quantize_fp16"
,
...
...
src/quantization.cpp
View file @
264a7647
...
...
@@ -29,6 +29,7 @@
#include <migraphx/simplify_reshapes.hpp>
#include <migraphx/simplify_qdq.hpp>
#include <migraphx/eliminate_common_subexpression.hpp>
#include <migraphx/optimize_module.hpp>
#include <migraphx/dead_code_elimination.hpp>
#include <migraphx/program.hpp>
#include <migraphx/instruction.hpp>
...
...
@@ -48,19 +49,12 @@ MIGRAPHX_DECLARE_ENV_VAR(MIGRAPHX_INT8_QUANTIZATION_PARAMS)
// This function is to convert any instructions specified in the input
// from double or float to float16 by inserting a convert operator.
// For the conversion, there could be cases of overflowing, but it
// is
very rare in the area of deeping learning, so we just do a
//
truncate of the input to get the fp16
.
// For the conversion, there could be cases of overflowing
or underflowing
, but it
// is
uncommon. Run optimize_module() before converting to fp16 to const eval and fold in FP32 to
//
avoid loss of precision
.
void
quantize_fp16
(
program
&
prog
,
const
std
::
vector
<
std
::
string
>&
ins_names
)
{
run_passes
(
prog
,
{
quantize_fp16_pass
{
ins_names
},
eliminate_common_subexpression
{},
dead_code_elimination
{},
simplify_reshapes
{},
dead_code_elimination
{},
simplify_qdq
{},
dead_code_elimination
{}});
run_passes
(
prog
,
{
optimize_module
{},
quantize_fp16_pass
{
ins_names
},
optimize_module
{}});
}
void
quantize_int8
(
program
&
prog
,
...
...
src/shape.cpp
View file @
264a7647
/*
* The MIT License (MIT)
*
* Copyright (c) 2015-202
2
Advanced Micro Devices, Inc. All rights reserved.
* Copyright (c) 2015-202
3
Advanced Micro Devices, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
...
...
@@ -273,9 +273,23 @@ shape shape::from_permutation(type_t t,
shape
::
type_t
shape
::
type
()
const
{
return
impl
->
m_type
;
}
const
std
::
vector
<
std
::
size_t
>&
shape
::
lens
()
const
{
return
impl
->
m_lens
;
}
const
std
::
vector
<
std
::
size_t
>&
shape
::
lens
()
const
{
if
(
this
->
dynamic
())
{
MIGRAPHX_THROW
(
"SHAPE: lens() called on a dynamic shape"
);
}
return
impl
->
m_lens
;
}
const
std
::
vector
<
std
::
size_t
>&
shape
::
strides
()
const
{
return
impl
->
m_strides
;
}
const
std
::
vector
<
std
::
size_t
>&
shape
::
strides
()
const
{
if
(
this
->
dynamic
())
{
MIGRAPHX_THROW
(
"SHAPE: strides() called on a dynamic shape"
);
}
return
impl
->
m_strides
;
}
std
::
size_t
shape
::
ndim
()
const
{
...
...
@@ -535,7 +549,14 @@ bool shape::any_of_dynamic() const
});
}
const
std
::
vector
<
shape
::
dynamic_dimension
>&
shape
::
dyn_dims
()
const
{
return
impl
->
m_dyn_dims
;
}
const
std
::
vector
<
shape
::
dynamic_dimension
>&
shape
::
dyn_dims
()
const
{
if
(
not
this
->
dynamic
())
{
MIGRAPHX_THROW
(
"SHAPE: dyn_dims() called on a static shape"
);
}
return
impl
->
m_dyn_dims
;
}
std
::
vector
<
std
::
size_t
>
shape
::
min_lens
()
const
{
...
...
@@ -679,12 +700,22 @@ const std::vector<shape>& shape::sub_shapes() const { return impl->m_shapes; }
void
migraphx_to_value
(
value
&
v
,
const
shape
&
s
)
{
value
result
;
result
[
"type"
]
=
migraphx
::
to_value
(
s
.
type_string
());
result
[
"lens"
]
=
migraphx
::
to_value
(
s
.
lens
());
result
[
"strides"
]
=
migraphx
::
to_value
(
s
.
strides
());
result
[
"sub_shapes"
]
=
migraphx
::
to_value
(
s
.
sub_shapes
());
result
[
"dynamic_dimensions"
]
=
migraphx
::
to_value
(
s
.
dyn_dims
());
v
=
result
;
result
[
"type"
]
=
migraphx
::
to_value
(
s
.
type_string
());
result
[
"sub_shapes"
]
=
migraphx
::
to_value
(
s
.
sub_shapes
());
// avoid calling functions that will throw
if
(
s
.
dynamic
())
{
result
[
"lens"
]
=
{};
result
[
"strides"
]
=
{};
result
[
"dynamic_dimensions"
]
=
migraphx
::
to_value
(
s
.
dyn_dims
());
}
else
{
result
[
"lens"
]
=
migraphx
::
to_value
(
s
.
lens
());
result
[
"strides"
]
=
migraphx
::
to_value
(
s
.
strides
());
result
[
"dynamic_dimensions"
]
=
{};
}
v
=
result
;
}
void
migraphx_from_value
(
const
value
&
v
,
shape
&
s
)
...
...
Prev
1
2
3
4
5
6
7
8
9
10
…
14
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