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
2ba401f0
Unverified
Commit
2ba401f0
authored
Jul 28, 2022
by
Ted Themistokleous
Committed by
GitHub
Jul 28, 2022
Browse files
Merge branch 'simplify_1_mul_div_ops' into divide_by_zero_check
parents
a330d428
8398fb19
Changes
183
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
780 additions
and
59 deletions
+780
-59
src/include/migraphx/permutation.hpp
src/include/migraphx/permutation.hpp
+6
-0
src/include/migraphx/program.hpp
src/include/migraphx/program.hpp
+5
-0
src/include/migraphx/ranges.hpp
src/include/migraphx/ranges.hpp
+6
-0
src/include/migraphx/shape.hpp
src/include/migraphx/shape.hpp
+75
-1
src/include/migraphx/support_metric.hpp
src/include/migraphx/support_metric.hpp
+38
-0
src/include/migraphx/target.hpp
src/include/migraphx/target.hpp
+49
-0
src/include/migraphx/target_assignments.hpp
src/include/migraphx/target_assignments.hpp
+47
-0
src/module.cpp
src/module.cpp
+22
-12
src/onnx/include/migraphx/onnx/onnx_parser.hpp
src/onnx/include/migraphx/onnx/onnx_parser.hpp
+3
-2
src/onnx/onnx.cpp
src/onnx/onnx.cpp
+19
-2
src/onnx/onnx_parser.cpp
src/onnx/onnx_parser.cpp
+39
-12
src/program.cpp
src/program.cpp
+38
-14
src/serialize.cpp
src/serialize.cpp
+2
-2
src/shape.cpp
src/shape.cpp
+194
-13
src/simplify_reshapes.cpp
src/simplify_reshapes.cpp
+65
-1
src/target_assignments.cpp
src/target_assignments.cpp
+36
-0
src/targets/cpu/write_literals.cpp
src/targets/cpu/write_literals.cpp
+2
-0
src/targets/fpga/CMakeLists.txt
src/targets/fpga/CMakeLists.txt
+42
-0
src/targets/fpga/include/migraphx/fpga/context.hpp
src/targets/fpga/include/migraphx/fpga/context.hpp
+45
-0
src/targets/fpga/include/migraphx/fpga/lowering.hpp
src/targets/fpga/include/migraphx/fpga/lowering.hpp
+47
-0
No files found.
src/include/migraphx/permutation.hpp
View file @
2ba401f0
...
...
@@ -55,8 +55,14 @@ inline std::vector<int64_t> sort_permutation(const Vector& data, Op op)
return
result
;
}
/*!
* Returns the permutation needed to apply to the shape to undo the current permutation
*/
std
::
vector
<
int64_t
>
invert_permutation
(
const
std
::
vector
<
int64_t
>&
permutation
);
/*!
* Finds the permutation most likely from a transpose operator that has been applied to the shape.
*/
std
::
vector
<
int64_t
>
find_permutation
(
const
shape
&
s
);
std
::
vector
<
int64_t
>
find_permutation
(
const
std
::
vector
<
shape
>&
shapes
);
...
...
src/include/migraphx/program.hpp
View file @
2ba401f0
...
...
@@ -33,6 +33,8 @@
#include <migraphx/instruction_ref.hpp>
#include <migraphx/target.hpp>
#include <migraphx/compile_options.hpp>
#include <migraphx/target_assignments.hpp>
#include <migraphx/assignment_options.hpp>
#include <migraphx/env.hpp>
#include <migraphx/config.hpp>
#include <algorithm>
...
...
@@ -84,6 +86,9 @@ struct program
instruction_ref
validate
()
const
;
target_assignments
get_target_assignments
(
const
std
::
vector
<
target
>&
targets
,
assignment_options
options
=
assignment_options
{});
void
compile
(
const
target
&
t
,
compile_options
options
=
compile_options
{});
bool
is_compiled
()
const
;
...
...
src/include/migraphx/ranges.hpp
View file @
2ba401f0
...
...
@@ -198,6 +198,12 @@ void transform(Range&& r, Iterator it, F f)
std
::
transform
(
r
.
begin
(),
r
.
end
(),
it
,
f
);
}
template
<
class
Range1
,
class
Range2
,
class
Iterator
,
class
F
>
void
transform
(
Range1
&&
r1
,
Range2
&&
r2
,
Iterator
it
,
F
f
)
{
std
::
transform
(
r1
.
begin
(),
r1
.
end
(),
r2
.
begin
(),
it
,
f
);
}
template
<
class
Range
>
auto
reverse
(
Range
&
r
)
{
...
...
src/include/migraphx/shape.hpp
View file @
2ba401f0
...
...
@@ -82,6 +82,23 @@ struct shape
{
};
struct
dynamic_dimension
{
std
::
size_t
min
=
0
;
std
::
size_t
max
=
0
;
std
::
size_t
opt
=
0
;
template
<
class
Self
,
class
F
>
static
auto
reflect
(
Self
&
self
,
F
f
);
bool
is_fixed
()
const
;
bool
has_optimal
()
const
;
friend
bool
operator
==
(
const
dynamic_dimension
&
x
,
const
dynamic_dimension
&
y
);
friend
bool
operator
!=
(
const
dynamic_dimension
&
x
,
const
dynamic_dimension
&
y
);
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
dynamic_dimension
&
x
);
};
static
const
std
::
vector
<
type_t
>&
types
();
static
std
::
string
name
(
type_t
t
);
...
...
@@ -92,6 +109,12 @@ struct shape
shape
(
type_t
t
,
std
::
vector
<
std
::
size_t
>
l
);
shape
(
type_t
t
,
std
::
vector
<
std
::
size_t
>
l
,
std
::
vector
<
std
::
size_t
>
s
);
// Force all calls of the format `shape( type_t, { size_t compatibles } )` to map to
// shape(type_t, std::vector<std::size_t> l)
shape
(
type_t
t
,
std
::
initializer_list
<
std
::
size_t
>
d
);
shape
(
type_t
t
,
std
::
vector
<
dynamic_dimension
>
dims
);
template
<
class
Range
>
shape
(
type_t
t
,
const
Range
&
l
)
:
shape
(
t
,
std
::
vector
<
std
::
size_t
>
(
l
.
begin
(),
l
.
end
()))
{
...
...
@@ -112,10 +135,44 @@ struct shape
type_t
type
()
const
;
const
std
::
vector
<
std
::
size_t
>&
lens
()
const
;
const
std
::
vector
<
std
::
size_t
>&
strides
()
const
;
/*!
* Return the number of elements in the tensor.
*/
std
::
size_t
elements
()
const
;
/*!
* Return the number of total bytes used for storage of the tensor data; includes subshapes.
* For dynamic shape, returns the maximum number of bytes presuming a packed shape.
*/
std
::
size_t
bytes
()
const
;
/*!
* Return the size of the type of the main shape.
* Returns 0 if there are subshapes.
*/
std
::
size_t
type_size
()
const
;
const
std
::
vector
<
dynamic_dimension
>&
dyn_dims
()
const
;
/*!
* Minimum lengths for dynamic shape.
* lens() for fixed shape.
*/
std
::
vector
<
std
::
size_t
>
min_lens
()
const
;
/*!
* Maximum lengths for dynamic shape.
* lens() for fixed shape.
*/
std
::
vector
<
std
::
size_t
>
max_lens
()
const
;
/*!
* Optimum lengths for dynamic shape.
* lens() for fixed shape.
*/
std
::
vector
<
std
::
size_t
>
opt_lens
()
const
;
/// Map multiple indices to space index
std
::
size_t
index
(
std
::
initializer_list
<
std
::
size_t
>
l
)
const
;
/// Map multiple indices to space index
...
...
@@ -136,19 +193,27 @@ struct shape
std
::
vector
<
std
::
size_t
>
multi
(
std
::
size_t
i
)
const
;
void
multi_copy
(
std
::
size_t
i
,
std
::
size_t
*
start
,
const
std
::
size_t
*
end
)
const
;
/// Returns true if the shape is packed with no padding
/// Returns true if the shape is packed (number of elements and buffer size the same) with no
/// padding
bool
packed
()
const
;
/// Returns true is the shape has been transposed. That is the strides are not in descending
/// order
bool
transposed
()
const
;
/// Returns true if the shape is broadcasting a dimension. That is, one of the strides are zero
bool
broadcasted
()
const
;
/// Returns true if the shape is in its standard format. That is, the shape is both packed and
/// not transposed.
bool
standard
()
const
;
/// Returns true if all strides are equal to 0 (scalar tensor)
bool
scalar
()
const
;
/// Return true if the shape is dynamic
bool
dynamic
()
const
;
shape
normalize_standard
()
const
;
shape
with_lens
(
type_t
t
,
const
std
::
vector
<
std
::
size_t
>&
l
)
const
;
...
...
@@ -191,6 +256,10 @@ struct shape
std
::
size_t
size
(
std
::
size_t
n
=
1
)
const
{
return
sizeof
(
type
)
*
n
;
}
auto
is_integral
()
const
{
return
std
::
is_integral
<
type
>
{};
}
auto
is_signed
()
const
{
return
std
::
is_signed
<
type
>
{};
}
auto
is_unsigned
()
const
{
return
std
::
is_unsigned
<
type
>
{};
}
template
<
class
U
>
type
*
from
(
U
*
buffer
,
std
::
size_t
n
=
0
)
const
{
...
...
@@ -248,6 +317,11 @@ struct shape
const
std
::
vector
<
shape
>&
sub_shapes
()
const
;
/*!
* Returns the number of elements in the data buffer.
* For a dynamic shape, returns the maximum number of elements of the data buffer and assumes it
* is packed.
*/
std
::
size_t
element_space
()
const
;
private:
...
...
src/include/migraphx/support_metric.hpp
0 → 100644
View file @
2ba401f0
/*
* The MIT License (MIT)
*
* Copyright (c) 2015-2022 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
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MIGRAPHX_GUARD_MIGRAPHX_SUPPORT_METRIC_HPP
#define MIGRAPHX_GUARD_MIGRAPHX_SUPPORT_METRIC_HPP
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
enum
class
support_metric
{
latency
,
throughput
};
}
// namespace MIGRAPHX_INLINE_NS
}
// namespace migraphx
#endif // MIGRAPHX_GUARD_MIGRAPHX_SUPPORT_METRIC_HPP
src/include/migraphx/target.hpp
View file @
2ba401f0
...
...
@@ -37,6 +37,8 @@
#include <migraphx/compile_options.hpp>
#include <migraphx/argument.hpp>
#include <migraphx/rank.hpp>
#include <migraphx/support_metric.hpp>
#include <migraphx/instruction_ref.hpp>
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
...
...
@@ -61,6 +63,13 @@ struct target
* @return The context to be used during compilation and execution.
*/
context
get_context
()
const
;
/**
* @brief Check how well an instruction is supported on a target with the given metric
* @param ins Instruction to check if it's supported
* @param metric Used to define how the return value should be interpreted
* @return The value based on the chosen metric. Negative numbers mean unsupported
*/
float
is_supported
(
T
&
,
instruction_ref
ins
,
support_metric
m
)
const
;
/**
* @brief copy an argument to the current target.
*
...
...
@@ -105,6 +114,12 @@ argument copy_from_target(T&, const argument& arg)
return
arg
;
}
template
<
class
T
>
float
target_is_supported
(
T
&
,
instruction_ref
,
support_metric
)
{
return
0
;
}
#ifdef TYPE_ERASED_DECLARATION
// Type-erased interface for:
...
...
@@ -117,6 +132,8 @@ struct target
//
context
get_context
()
const
;
// (optional)
float
is_supported
(
instruction_ref
ins
,
support_metric
m
)
const
;
// (optional)
argument
copy_to
(
const
argument
&
input
)
const
;
// (optional)
argument
copy_from
(
const
argument
&
input
)
const
;
...
...
@@ -207,6 +224,12 @@ struct target
return
(
*
this
).
private_detail_te_get_handle
().
get_context
();
}
float
is_supported
(
instruction_ref
ins
,
support_metric
m
)
const
{
assert
((
*
this
).
private_detail_te_handle_mem_var
);
return
(
*
this
).
private_detail_te_get_handle
().
is_supported
(
ins
,
m
);
}
argument
copy_to
(
const
argument
&
input
)
const
{
assert
((
*
this
).
private_detail_te_handle_mem_var
);
...
...
@@ -242,11 +265,31 @@ struct target
virtual
std
::
vector
<
pass
>
get_passes
(
context
&
ctx
,
const
compile_options
&
options
)
const
=
0
;
virtual
context
get_context
()
const
=
0
;
virtual
float
is_supported
(
instruction_ref
ins
,
support_metric
m
)
const
=
0
;
virtual
argument
copy_to
(
const
argument
&
input
)
const
=
0
;
virtual
argument
copy_from
(
const
argument
&
input
)
const
=
0
;
virtual
argument
allocate
(
const
shape
&
s
)
const
=
0
;
};
template
<
class
T
>
static
auto
private_detail_te_default_is_supported
(
char
,
T
&&
private_detail_te_self
,
instruction_ref
ins
,
support_metric
m
)
->
decltype
(
private_detail_te_self
.
is_supported
(
ins
,
m
))
{
return
private_detail_te_self
.
is_supported
(
ins
,
m
);
}
template
<
class
T
>
static
float
private_detail_te_default_is_supported
(
float
,
T
&&
private_detail_te_self
,
instruction_ref
ins
,
support_metric
m
)
{
return
target_is_supported
(
private_detail_te_self
,
ins
,
m
);
}
template
<
class
T
>
static
auto
private_detail_te_default_copy_to
(
char
,
T
&&
private_detail_te_self
,
const
argument
&
input
)
...
...
@@ -329,6 +372,12 @@ struct target
context
get_context
()
const
override
{
return
private_detail_te_value
.
get_context
();
}
float
is_supported
(
instruction_ref
ins
,
support_metric
m
)
const
override
{
return
private_detail_te_default_is_supported
(
char
(
0
),
private_detail_te_value
,
ins
,
m
);
}
argument
copy_to
(
const
argument
&
input
)
const
override
{
...
...
src/include/migraphx/target_assignments.hpp
0 → 100644
View file @
2ba401f0
/*
* The MIT License (MIT)
*
* Copyright (c) 2015-2022 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
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MIGRAPHX_GUARD_MIGRAPHX_ASSIGNMENT_HPP
#define MIGRAPHX_GUARD_MIGRAPHX_ASSIGNMENT_HPP
#include <unordered_map>
#include <migraphx/instruction_ref.hpp>
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
struct
target_assignments
{
void
add_assignment
(
instruction_ref
ins
,
const
std
::
string
&
target
);
auto
begin
()
const
{
return
assignments
.
cbegin
();
}
auto
end
()
const
{
return
assignments
.
cend
();
}
private:
std
::
unordered_map
<
instruction_ref
,
std
::
string
>
assignments
;
};
}
// namespace MIGRAPHX_INLINE_NS
}
// namespace migraphx
#endif // MIGRAPHX_GUARD_MIGRAPHX_ASSIGNMENT_HPP
src/module.cpp
View file @
2ba401f0
...
...
@@ -410,7 +410,8 @@ module::add_instructions(const std::vector<instruction_ref>& instructions,
}
std
::
vector
<
instruction_ref
>
module
::
add_instructions
(
module_ref
m
,
std
::
unordered_map
<
instruction_ref
,
instruction_ref
>
map_ins
)
module
::
add_instructions
(
const_module_ref
m
,
std
::
unordered_map
<
instruction_ref
,
instruction_ref
>
map_ins
)
{
return
this
->
insert_instructions
(
this
->
end
(),
m
,
std
::
move
(
map_ins
));
}
...
...
@@ -431,8 +432,10 @@ module::insert_instructions(instruction_ref ins,
return
insert_generic_instructions
(
*
this
,
ins
,
instructions
,
std
::
move
(
map_ins
));
}
std
::
vector
<
instruction_ref
>
module
::
insert_instructions
(
instruction_ref
ins
,
module_ref
m
,
std
::
unordered_map
<
instruction_ref
,
instruction_ref
>
map_ins
)
std
::
vector
<
instruction_ref
>
module
::
insert_instructions
(
instruction_ref
ins
,
const_module_ref
m
,
std
::
unordered_map
<
instruction_ref
,
instruction_ref
>
map_ins
)
{
return
insert_generic_instructions
(
*
this
,
ins
,
iterator_for
(
*
m
),
std
::
move
(
map_ins
));
}
...
...
@@ -447,11 +450,7 @@ module::insert_instructions(instruction_ref ins,
return
insert_generic_instructions
(
*
this
,
ins
,
iterator_for
(
r
),
std
::
move
(
map_ins
));
}
instruction_ref
module
::
add_literal
(
literal
l
)
{
impl
->
emplace_front
(
std
::
move
(
l
));
return
impl
->
instructions
.
begin
();
}
instruction_ref
module
::
add_literal
(
literal
l
)
{
return
insert_literal
(
begin
(),
std
::
move
(
l
));
}
instruction_ref
module
::
add_outline
(
const
shape
&
s
)
{
...
...
@@ -461,10 +460,7 @@ instruction_ref module::add_outline(const shape& s)
instruction_ref
module
::
add_parameter
(
std
::
string
name
,
shape
s
)
{
assert
(
get_parameter_shape
(
name
)
==
shape
{});
impl
->
push_front
({
builtin
::
param
{
std
::
move
(
name
),
impl
->
nparams
},
std
::
move
(
s
),
{}});
impl
->
nparams
++
;
return
impl
->
instructions
.
begin
();
return
insert_parameter
(
begin
(),
std
::
move
(
name
),
std
::
move
(
s
));
}
instruction_ref
module
::
add_return
(
std
::
vector
<
instruction_ref
>
args
)
...
...
@@ -477,6 +473,20 @@ instruction_ref module::add_return(std::vector<instruction_ref> args)
return
result
;
}
instruction_ref
module
::
insert_literal
(
instruction_ref
ins
,
literal
l
)
{
impl
->
emplace
(
ins
,
std
::
move
(
l
));
return
std
::
prev
(
ins
);
}
instruction_ref
module
::
insert_parameter
(
instruction_ref
ins
,
std
::
string
name
,
shape
s
)
{
assert
(
get_parameter_shape
(
name
)
==
shape
{});
impl
->
insert
(
ins
,
{
builtin
::
param
{
std
::
move
(
name
),
impl
->
nparams
},
std
::
move
(
s
),
{}});
impl
->
nparams
++
;
return
std
::
prev
(
ins
);
}
instruction_ref
module
::
replace_return
(
std
::
vector
<
instruction_ref
>
args
)
{
auto
last
=
std
::
prev
(
this
->
end
());
...
...
src/onnx/include/migraphx/onnx/onnx_parser.hpp
View file @
2ba401f0
...
...
@@ -93,9 +93,10 @@ struct onnx_parser
onnx_parser
&
,
const
node_info
&
,
std
::
vector
<
instruction_ref
>
)
>
;
node_map
nodes
;
std
::
unordered_map
<
std
::
string
,
instruction_ref
>
instructions
;
program
prog
=
program
();
s
td
::
size_t
default_dim_value
=
1
;
program
prog
=
program
();
s
hape
::
dynamic_dimension
default_
dyn_
dim_value
=
{
1
,
1
,
0
}
;
std
::
unordered_map
<
std
::
string
,
std
::
vector
<
std
::
size_t
>>
map_input_dims
;
std
::
unordered_map
<
std
::
string
,
std
::
vector
<
shape
::
dynamic_dimension
>>
map_dyn_input_dims
;
bool
skip_unknown_operators
=
false
;
int64_t
max_loop_iterations
=
10
;
int64_t
opset_version
=
13
;
...
...
src/onnx/onnx.cpp
View file @
2ba401f0
...
...
@@ -41,8 +41,25 @@ template <class... Ts>
program
parse_onnx_from
(
const
onnx_options
&
options
,
Ts
&&
...
xs
)
{
onnx
::
onnx_parser
parser
;
parser
.
map_input_dims
=
options
.
map_input_dims
;
parser
.
default_dim_value
=
options
.
default_dim_value
;
parser
.
map_input_dims
=
options
.
map_input_dims
;
parser
.
map_dyn_input_dims
=
options
.
map_dyn_input_dims
;
auto
dim_val
=
options
.
default_dim_value
;
if
(
dim_val
!=
0
)
{
if
(
options
.
default_dyn_dim_value
!=
shape
::
dynamic_dimension
{
1
,
1
,
0
})
{
MIGRAPHX_THROW
(
"PARSE_ONNX_FROM: both default_dim_value and default_dyn_dim_value"
"set to non-default value"
);
}
else
{
parser
.
default_dyn_dim_value
=
{
dim_val
,
dim_val
,
0
};
}
}
else
{
parser
.
default_dyn_dim_value
=
options
.
default_dyn_dim_value
;
}
parser
.
skip_unknown_operators
=
options
.
skip_unknown_operators
;
parser
.
max_loop_iterations
=
options
.
max_loop_iterations
;
...
...
src/onnx/onnx_parser.cpp
View file @
2ba401f0
...
...
@@ -35,9 +35,11 @@
#include <migraphx/file_buffer.hpp>
#include <migraphx/filesystem.hpp>
#include <migraphx/op/unknown.hpp>
#include <migraphx/env.hpp>
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
namespace
onnx
{
static
onnx_parser
::
attribute_map
get_attributes
(
const
onnx
::
NodeProto
&
node
)
...
...
@@ -255,6 +257,11 @@ int64_t onnx_parser::get_opset_version(const onnx::ModelProto& model)
void
onnx_parser
::
parse_graph
(
module
*
mod
,
const
onnx
::
GraphProto
&
graph
)
{
if
(
not
map_input_dims
.
empty
()
and
not
map_dyn_input_dims
.
empty
())
{
MIGRAPHX_THROW
(
"PARSE_GRAPH: both map_input_dims and map_dyn_input_dims non-empty, only"
"one should be used"
);
}
std
::
unordered_map
<
std
::
string
,
instruction_ref
>
mod_insts
;
for
(
auto
&&
f
:
graph
.
initializer
())
{
...
...
@@ -268,7 +275,7 @@ void onnx_parser::parse_graph(module* mod, const onnx::GraphProto& graph)
// input not in initializer_data, so it is a real input
if
(
!
contains
(
mod_insts
,
name
))
{
// ONNX specification does not specify h
w
o to deal with the
// ONNX specification does not specify ho
w
to deal with the
// scenario that a nested subgraph contains a parameter with the
// name existed in its parent graph.
// In the current implementation, MIGraphX throws an exception for that.
...
...
@@ -278,13 +285,22 @@ void onnx_parser::parse_graph(module* mod, const onnx::GraphProto& graph)
"
\"
existing in parent graph!"
);
}
shape
s
;
std
::
vector
<
std
::
size_t
>
dims
;
if
(
map_input_dims
.
count
(
name
)
>
0
)
{
dims
=
map_input_dims
.
at
(
name
);
s
=
parse_type
(
input
.
type
(),
dims
);
}
else
if
(
map_dyn_input_dims
.
count
(
name
)
>
0
)
{
shape
::
type_t
shape_type
=
get_type
(
input
.
type
().
tensor_type
().
elem_type
());
s
=
{
shape_type
,
map_dyn_input_dims
.
at
(
name
)};
}
else
{
s
=
parse_type
(
input
.
type
(),
dims
);
}
shape
s
=
parse_type
(
input
.
type
(),
dims
);
mod_insts
[
name
]
=
mod
->
add_parameter
(
name
,
s
);
}
}
...
...
@@ -439,30 +455,41 @@ shape onnx_parser::parse_type(const onnx::TypeProto& t,
return
{
shape_type
,
input_dims
};
}
std
::
vector
<
s
td
::
size_t
>
dims
;
std
::
vector
<
s
hape
::
dynamic_dimension
>
dynamic_
dims
;
auto
&&
tensor_dims
=
t
.
tensor_type
().
shape
().
dim
();
std
::
transform
(
tensor_dims
.
begin
(),
tensor_dims
.
end
(),
std
::
back_inserter
(
dims
),
[
&
](
auto
&&
d
)
->
s
td
::
size_t
{
std
::
back_inserter
(
dynamic_
dims
),
[
&
](
auto
&&
d
)
->
s
hape
::
dynamic_dimension
{
if
(
d
.
has_dim_value
())
{
if
(
static_cast
<
int
>
(
d
.
dim_value
())
<=
0
)
{
return
default_dim_value
;
return
default_
dyn_
dim_value
;
}
return
d
.
dim_value
();
std
::
size_t
tmp
=
d
.
dim_value
();
return
{
tmp
,
tmp
,
0
};
}
else
{
return
default_dim_value
;
return
default_
dyn_
dim_value
;
}
});
if
(
dims
.
empty
())
if
(
dynamic_dims
.
empty
())
{
return
{
shape_type
};
return
{
shape_type
,
dims
};
}
if
(
std
::
all_of
(
dynamic_dims
.
begin
(),
dynamic_dims
.
end
(),
[](
auto
dd
)
{
return
dd
.
is_fixed
();
}))
{
std
::
vector
<
std
::
size_t
>
dims
;
std
::
transform
(
dynamic_dims
.
begin
(),
dynamic_dims
.
end
(),
std
::
back_inserter
(
dims
),
[](
auto
d
)
{
return
d
.
max
;
});
return
{
shape_type
,
dims
};
}
return
{
shape_type
,
dynamic_dims
};
}
shape
::
type_t
get_type
(
int
dtype
)
...
...
src/program.cpp
View file @
2ba401f0
...
...
@@ -159,6 +159,25 @@ instruction_ref program::validate() const
return
mm
->
validate
();
}
target_assignments
program
::
get_target_assignments
(
const
std
::
vector
<
target
>&
targets
,
assignment_options
options
)
{
const
auto
m
=
options
.
metric
;
target_assignments
p
;
const
auto
*
mod
=
get_main_module
();
for
(
auto
it
:
iterator_for
(
*
mod
))
{
auto
t
=
std
::
max_element
(
targets
.
begin
(),
targets
.
end
(),
[
it
,
m
](
const
target
&
lhs
,
const
target
&
rhs
)
{
return
lhs
.
is_supported
(
it
,
m
)
<
rhs
.
is_supported
(
it
,
m
);
});
p
.
add_assignment
(
it
,
t
->
name
());
}
return
p
;
}
bool
program
::
is_compiled
()
const
{
return
not
this
->
impl
->
target_name
.
empty
();
}
void
program
::
compile
(
const
target
&
t
,
compile_options
options
)
...
...
@@ -514,12 +533,14 @@ static void mod_from_val(module_ref mod,
if
(
name
==
"@param"
)
{
output
=
mod
->
add_parameter
(
fields
[
"parameter"
].
to
<
std
::
string
>
(),
migraphx
::
from_value
<
shape
>
(
node
.
at
(
"shape"
)));
output
=
mod
->
insert_parameter
(
mod
->
end
(),
fields
[
"parameter"
].
to
<
std
::
string
>
(),
migraphx
::
from_value
<
shape
>
(
node
.
at
(
"shape"
)));
}
else
if
(
name
==
"@literal"
)
{
output
=
mod
->
add_literal
(
migraphx
::
from_value
<
literal
>
(
node
.
at
(
"literal"
)));
output
=
mod
->
insert_literal
(
mod
->
end
(),
migraphx
::
from_value
<
literal
>
(
node
.
at
(
"literal"
)));
}
else
{
...
...
@@ -554,11 +575,11 @@ static void mod_from_val(module_ref mod,
}
else
if
(
module_inputs
.
empty
())
{
output
=
mod
->
add
_instruction
(
op
,
inputs
);
output
=
mod
->
insert
_instruction
(
mod
->
end
(),
op
,
inputs
);
}
else
{
output
=
mod
->
add
_instruction
(
op
,
inputs
,
module_inputs
);
output
=
mod
->
insert
_instruction
(
mod
->
end
(),
op
,
inputs
,
module_inputs
);
}
}
output
->
set_normalized
(
normalized
);
...
...
@@ -691,11 +712,13 @@ void program::perf_report(std::ostream& os,
double
overhead_percent
=
overhead_time
*
100.0
/
total_time
;
double
total_instruction_time
=
0.0
;
std
::
unordered_map
<
std
::
string
,
double
>
op_times
;
std
::
unordered_map
<
std
::
string
,
std
::
size_t
>
op_n
;
for
(
auto
&&
p
:
ins_vec
)
{
double
avg
=
common_average
(
p
.
second
);
op_times
[
perf_group
(
p
.
first
->
get_operator
())]
+=
avg
;
total_instruction_time
+=
avg
;
op_n
[
perf_group
(
p
.
first
->
get_operator
())]
++
;
}
double
calculate_overhead_time
=
total_time
-
total_instruction_time
;
double
calculate_overhead_percent
=
calculate_overhead_time
*
100.0
/
total_time
;
...
...
@@ -716,18 +739,19 @@ void program::perf_report(std::ostream& os,
os
<<
std
::
endl
;
os
<<
"Summary:"
<<
std
::
endl
;
std
::
vector
<
std
::
pair
<
double
,
std
::
string
>>
op_times_sorted
;
std
::
transform
(
op_times
.
begin
(),
op_times
.
end
(),
std
::
back_inserter
(
op_times_sorted
),
[](
auto
p
)
{
return
std
::
make_pair
(
p
.
second
,
p
.
first
);
});
std
::
vector
<
std
::
tuple
<
double
,
std
::
size_t
,
std
::
string
>>
op_times_sorted
;
std
::
transform
(
op_times
.
begin
(),
op_times
.
end
(),
std
::
back_inserter
(
op_times_sorted
),
[
&
](
auto
p
)
{
auto
&&
name
=
p
.
first
;
return
std
::
make_tuple
(
p
.
second
,
op_n
.
at
(
name
),
name
);
});
std
::
sort
(
op_times_sorted
.
begin
(),
op_times_sorted
.
end
(),
std
::
greater
<>
{});
for
(
auto
&&
p
:
op_times_sorted
)
for
(
auto
&&
[
avg
,
nn
,
name
]
:
op_times_sorted
)
{
auto
&&
name
=
p
.
second
;
double
avg
=
p
.
first
;
double
percent
=
std
::
ceil
(
100.0
*
avg
/
total_instruction_time
);
os
<<
name
<<
": "
<<
avg
<<
"ms, "
<<
percent
<<
"%"
<<
std
::
endl
;
double
per_ins
=
avg
/
nn
;
os
<<
name
<<
": "
<<
avg
<<
"ms / "
<<
nn
<<
" = "
<<
per_ins
<<
"ms, "
<<
percent
<<
"%"
<<
std
::
endl
;
}
os
<<
std
::
endl
;
...
...
src/serialize.cpp
View file @
2ba401f0
...
...
@@ -36,7 +36,7 @@ void raw_data_to_value(value& v, const RawData& rd)
result
[
"shape"
]
=
migraphx
::
to_value
(
rd
.
get_shape
());
if
(
rd
.
get_shape
().
type
()
==
shape
::
tuple_type
)
result
[
"sub"
]
=
migraphx
::
to_value
(
rd
.
get_sub_objects
());
else
else
if
(
not
rd
.
empty
())
result
[
"data"
]
=
migraphx
::
value
::
binary
(
rd
.
data
(),
rd
.
get_shape
().
bytes
());
v
=
result
;
}
...
...
@@ -56,7 +56,7 @@ void migraphx_from_value(const value& v, argument& a)
literal
l
=
migraphx
::
from_value
<
literal
>
(
v
);
a
=
l
.
get_argument
();
}
else
else
if
(
v
.
contains
(
"sub"
))
{
a
=
migraphx
::
from_value
<
std
::
vector
<
argument
>>
(
v
.
at
(
"sub"
));
}
...
...
src/shape.cpp
View file @
2ba401f0
...
...
@@ -26,6 +26,7 @@
#include <migraphx/stringutils.hpp>
#include <migraphx/serialize.hpp>
#include <migraphx/permutation.hpp>
#include <migraphx/ranges.hpp>
#include <numeric>
#include <algorithm>
#include <functional>
...
...
@@ -65,13 +66,21 @@ struct shape_impl
std
::
is_sorted
(
m_strides
.
rbegin
(),
m_strides
.
rend
());
}
shape_impl
(
shape
::
type_t
t
,
std
::
vector
<
shape
::
dynamic_dimension
>
dims
)
:
m_type
(
t
),
m_dyn_dims
(
std
::
move
(
dims
))
{
}
shape_impl
(
const
std
::
vector
<
shape
>&
subs
)
:
m_type
(
shape
::
tuple_type
),
m_shapes
(
subs
)
{}
shape
::
type_t
m_type
;
std
::
vector
<
std
::
size_t
>
m_lens
=
{};
std
::
vector
<
std
::
size_t
>
m_strides
=
{};
std
::
vector
<
shape
>
m_shapes
=
{};
bool
m_standard
=
false
;
std
::
vector
<
shape
::
dynamic_dimension
>
m_dyn_dims
=
{};
void
calculate_strides
()
{
m_strides
.
clear
();
...
...
@@ -87,6 +96,12 @@ struct shape_impl
std
::
size_t
element_space
()
const
{
if
(
not
m_dyn_dims
.
empty
())
{
auto
maxes
=
max_lens
();
return
std
::
accumulate
(
maxes
.
begin
(),
maxes
.
end
(),
std
::
size_t
{
1
},
std
::
multiplies
<>
());
}
assert
(
m_lens
.
size
()
==
m_strides
.
size
());
if
(
m_lens
.
empty
())
return
0
;
...
...
@@ -101,6 +116,11 @@ struct shape_impl
std
::
size_t
elements
()
const
{
if
(
not
m_dyn_dims
.
empty
())
{
MIGRAPHX_THROW
(
"SHAPE: elements() called on dynamic shape"
);
}
assert
(
m_lens
.
size
()
==
m_strides
.
size
());
if
(
m_lens
.
empty
())
return
0
;
...
...
@@ -108,6 +128,35 @@ struct shape_impl
m_lens
.
begin
(),
m_lens
.
end
(),
std
::
size_t
{
1
},
std
::
multiplies
<
std
::
size_t
>
());
}
std
::
vector
<
std
::
size_t
>
min_lens
()
const
{
std
::
vector
<
std
::
size_t
>
ret
(
m_dyn_dims
.
size
());
std
::
transform
(
m_dyn_dims
.
cbegin
(),
m_dyn_dims
.
cend
(),
ret
.
begin
(),
[](
shape
::
dynamic_dimension
x
)
{
return
x
.
min
;
});
return
ret
;
}
std
::
vector
<
std
::
size_t
>
max_lens
()
const
{
std
::
vector
<
std
::
size_t
>
ret
(
m_dyn_dims
.
size
());
std
::
transform
(
m_dyn_dims
.
cbegin
(),
m_dyn_dims
.
cend
(),
ret
.
begin
(),
[](
shape
::
dynamic_dimension
x
)
{
return
x
.
max
;
});
return
ret
;
}
std
::
vector
<
std
::
size_t
>
opt_lens
()
const
{
std
::
vector
<
std
::
size_t
>
ret
(
m_dyn_dims
.
size
());
std
::
transform
(
m_dyn_dims
.
cbegin
(),
m_dyn_dims
.
cend
(),
ret
.
begin
(),
[](
shape
::
dynamic_dimension
x
)
{
return
x
.
opt
;
});
return
ret
;
}
// Does the shape skip over elements?
bool
skips
()
const
{
...
...
@@ -165,6 +214,16 @@ shape::shape(type_t t, std::vector<std::size_t> l, std::vector<std::size_t> s)
{
}
shape
::
shape
(
type_t
t
,
std
::
initializer_list
<
std
::
size_t
>
d
)
:
shape
::
shape
(
t
,
std
::
vector
<
std
::
size_t
>
{
d
.
begin
(),
d
.
end
()})
{
}
shape
::
shape
(
type_t
t
,
std
::
vector
<
shape
::
dynamic_dimension
>
dims
)
:
impl
(
std
::
make_shared
<
shape_impl
>
(
t
,
std
::
move
(
dims
)))
{
}
shape
::
shape
(
const
std
::
vector
<
shape
>&
subs
)
:
impl
(
std
::
make_shared
<
shape_impl
>
(
subs
))
{}
shape
::
shape
(
std
::
shared_ptr
<
shape_impl
>
pimpl
)
:
impl
(
std
::
move
(
pimpl
))
{}
...
...
@@ -180,9 +239,13 @@ 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
::
strides
()
const
{
return
impl
->
m_strides
;
}
std
::
size_t
shape
::
elements
()
const
{
return
impl
->
elements
();
}
std
::
size_t
shape
::
bytes
()
const
{
if
(
this
->
sub_shapes
().
empty
())
...
...
@@ -199,6 +262,7 @@ std::size_t shape::bytes() const
[
&
](
auto
x
,
auto
y
)
{
return
x
+
y
.
bytes
();
});
}
}
std
::
size_t
shape
::
type_size
()
const
{
std
::
size_t
n
=
0
;
...
...
@@ -206,20 +270,35 @@ std::size_t shape::type_size() const
this
->
visit_type
([
&
](
auto
as
)
{
n
=
as
.
size
();
});
return
n
;
}
std
::
size_t
shape
::
index
(
std
::
initializer_list
<
std
::
size_t
>
l
)
const
{
if
(
this
->
dynamic
())
{
MIGRAPHX_THROW
(
"SHAPE: index() called on dynamic shape"
);
}
assert
(
l
.
size
()
<=
this
->
lens
().
size
());
assert
(
this
->
lens
().
size
()
==
this
->
strides
().
size
());
return
std
::
inner_product
(
l
.
begin
(),
l
.
end
(),
this
->
strides
().
begin
(),
std
::
size_t
{
0
});
}
std
::
size_t
shape
::
index
(
const
std
::
vector
<
std
::
size_t
>&
l
)
const
{
if
(
this
->
dynamic
())
{
MIGRAPHX_THROW
(
"SHAPE: index() called on dynamic shape"
);
}
assert
(
l
.
size
()
<=
this
->
lens
().
size
());
assert
(
this
->
lens
().
size
()
==
this
->
strides
().
size
());
return
std
::
inner_product
(
l
.
begin
(),
l
.
end
(),
this
->
strides
().
begin
(),
std
::
size_t
{
0
});
}
std
::
size_t
shape
::
index
(
std
::
size_t
i
)
const
{
if
(
this
->
dynamic
())
{
MIGRAPHX_THROW
(
"SHAPE: index() called on dynamic shape"
);
}
assert
(
this
->
lens
().
size
()
==
this
->
strides
().
size
());
if
(
this
->
standard
())
return
i
;
...
...
@@ -267,12 +346,20 @@ void shape::multi_copy(std::size_t i, std::size_t* start, const std::size_t* end
bool
shape
::
packed
()
const
{
if
(
this
->
dynamic
())
{
return
false
;
}
return
this
->
sub_shapes
().
empty
()
and
not
impl
->
skips
()
and
this
->
elements
()
==
this
->
element_space
();
}
bool
shape
::
transposed
()
const
{
if
(
this
->
dynamic
())
{
return
false
;
}
if
(
this
->
broadcasted
())
{
// TODO: Use a filter_iterator instead
...
...
@@ -292,6 +379,10 @@ bool shape::transposed() const
bool
shape
::
broadcasted
()
const
{
if
(
this
->
dynamic
())
{
return
false
;
}
assert
(
this
->
lens
().
size
()
==
this
->
strides
().
size
());
return
std
::
any_of
(
this
->
strides
().
begin
(),
this
->
strides
().
end
(),
[](
auto
x
)
{
return
x
==
0
;
});
...
...
@@ -299,6 +390,10 @@ bool shape::broadcasted() const
bool
shape
::
scalar
()
const
{
if
(
this
->
dynamic
())
{
return
false
;
}
assert
(
this
->
lens
().
size
()
==
this
->
strides
().
size
());
// if any stride > 0, then accumulate will return false
return
this
->
sub_shapes
().
empty
()
and
...
...
@@ -317,6 +412,10 @@ shape shape::normalize_standard() const
shape
shape
::
with_lens
(
type_t
t
,
const
std
::
vector
<
std
::
size_t
>&
l
)
const
{
if
(
this
->
dynamic
())
{
MIGRAPHX_THROW
(
"SHAPE: with_lens() called on dynamic shape"
);
}
assert
(
l
.
size
()
==
this
->
lens
().
size
());
auto
perm
=
find_permutation
(
*
this
);
return
shape
::
from_permutation
(
t
,
l
,
perm
);
...
...
@@ -324,6 +423,10 @@ shape shape::with_lens(type_t t, const std::vector<std::size_t>& l) const
shape
shape
::
with_lens
(
const
std
::
vector
<
std
::
size_t
>&
l
)
const
{
if
(
this
->
dynamic
())
{
MIGRAPHX_THROW
(
"SHAPE: with_lens() called on dynamic shape"
);
}
return
this
->
with_lens
(
this
->
type
(),
l
);
}
...
...
@@ -338,20 +441,80 @@ std::size_t shape::element_space() const { return impl->element_space(); }
std
::
string
shape
::
type_string
()
const
{
return
name
(
this
->
type
());
}
bool
shape
::
dynamic
()
const
{
return
not
impl
->
m_dyn_dims
.
empty
();
}
const
std
::
vector
<
shape
::
dynamic_dimension
>&
shape
::
dyn_dims
()
const
{
return
impl
->
m_dyn_dims
;
}
std
::
vector
<
std
::
size_t
>
shape
::
min_lens
()
const
{
return
this
->
dynamic
()
?
impl
->
min_lens
()
:
this
->
lens
();
}
std
::
vector
<
std
::
size_t
>
shape
::
max_lens
()
const
{
return
this
->
dynamic
()
?
impl
->
max_lens
()
:
this
->
lens
();
}
std
::
vector
<
std
::
size_t
>
shape
::
opt_lens
()
const
{
return
this
->
dynamic
()
?
impl
->
opt_lens
()
:
this
->
lens
();
}
bool
shape
::
dynamic_dimension
::
is_fixed
()
const
{
return
this
->
min
==
this
->
max
;
}
bool
shape
::
dynamic_dimension
::
has_optimal
()
const
{
return
opt
!=
0
;
}
template
<
class
Self
,
class
F
>
auto
shape
::
dynamic_dimension
::
reflect
(
Self
&
self
,
F
f
)
{
return
pack
(
f
(
self
.
min
,
"min"
),
f
(
self
.
max
,
"max"
),
f
(
self
.
opt
,
"opt"
));
}
bool
operator
==
(
const
shape
::
dynamic_dimension
&
x
,
const
shape
::
dynamic_dimension
&
y
)
{
return
(
x
.
min
==
y
.
min
and
x
.
max
==
y
.
max
and
x
.
opt
==
y
.
opt
);
}
bool
operator
!=
(
const
shape
::
dynamic_dimension
&
x
,
const
shape
::
dynamic_dimension
&
y
)
{
return
!
(
x
==
y
);
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
shape
::
dynamic_dimension
&
x
)
{
os
<<
"["
<<
x
.
min
<<
", "
<<
x
.
max
<<
", "
<<
x
.
opt
<<
"]"
;
return
os
;
}
bool
operator
==
(
const
shape
&
x
,
const
shape
&
y
)
{
return
x
.
impl
==
y
.
impl
or
(
x
.
type
()
==
y
.
type
()
and
x
.
lens
()
==
y
.
lens
()
and
x
.
strides
()
==
y
.
strides
()
and
x
.
sub_shapes
()
==
y
.
sub_shapes
());
if
(
x
.
dynamic
()
and
y
.
dynamic
())
{
return
x
.
impl
==
y
.
impl
or
(
x
.
type
()
==
y
.
type
()
and
x
.
dyn_dims
()
==
y
.
dyn_dims
()
and
x
.
sub_shapes
()
==
y
.
sub_shapes
());
}
return
x
.
impl
==
y
.
impl
or
(
x
.
dynamic
()
==
y
.
dynamic
()
and
x
.
type
()
==
y
.
type
()
and
x
.
lens
()
==
y
.
lens
()
and
x
.
strides
()
==
y
.
strides
()
and
x
.
sub_shapes
()
==
y
.
sub_shapes
());
}
bool
operator
!=
(
const
shape
&
x
,
const
shape
&
y
)
{
return
!
(
x
==
y
);
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
shape
&
x
)
{
if
(
x
.
sub_shapes
().
empty
())
{
os
<<
x
.
type_string
()
<<
", "
;
os
<<
"{"
<<
to_string_range
(
x
.
lens
())
<<
"}, "
;
os
<<
"{"
<<
to_string_range
(
x
.
strides
())
<<
"}"
;
if
(
x
.
dynamic
())
{
os
<<
"dynamic, "
;
os
<<
x
.
type_string
()
<<
", "
;
os
<<
"{"
<<
to_string_range
(
x
.
dyn_dims
())
<<
"}"
;
}
else
{
os
<<
x
.
type_string
()
<<
", "
;
os
<<
"{"
<<
to_string_range
(
x
.
lens
())
<<
"}, "
;
os
<<
"{"
<<
to_string_range
(
x
.
strides
())
<<
"}"
;
}
}
else
{
...
...
@@ -375,12 +538,14 @@ 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
());
v
=
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
;
}
void
migraphx_from_value
(
const
value
&
v
,
shape
&
s
)
{
auto
t
=
v
.
at
(
"type"
).
get_string
();
...
...
@@ -390,9 +555,25 @@ void migraphx_from_value(const value& v, shape& s)
}
else
{
s
=
shape
{
shape
::
parse_type
(
t
),
v
.
at
(
"lens"
).
to_vector
<
std
::
size_t
>
(),
v
.
at
(
"strides"
).
to_vector
<
std
::
size_t
>
()};
if
(
v
.
at
(
"dynamic_dimensions"
).
empty
())
{
s
=
shape
{
shape
::
parse_type
(
t
),
v
.
at
(
"lens"
).
to_vector
<
std
::
size_t
>
(),
v
.
at
(
"strides"
).
to_vector
<
std
::
size_t
>
()};
}
else
{
auto
v_dd
=
v
.
at
(
"dynamic_dimensions"
);
std
::
vector
<
shape
::
dynamic_dimension
>
dyn_dims
(
v
.
at
(
"dynamic_dimensions"
).
size
());
std
::
transform
(
v_dd
.
begin
(),
v_dd
.
end
(),
dyn_dims
.
begin
(),
[](
migraphx
::
value
x
)
{
auto
x_min
=
x
.
at
(
"min"
).
template
to
<
size_t
>();
auto
x_max
=
x
.
at
(
"max"
).
template
to
<
size_t
>();
auto
x_opt
=
x
.
at
(
"opt"
).
template
to
<
size_t
>();
return
shape
::
dynamic_dimension
{
x_min
,
x_max
,
x_opt
};
});
s
=
shape
{
shape
::
parse_type
(
t
),
dyn_dims
};
}
}
}
...
...
src/simplify_reshapes.cpp
View file @
2ba401f0
...
...
@@ -272,7 +272,7 @@ struct find_concat_transpose
{
auto
matcher
()
const
{
return
match
::
name
(
"concat"
)(
match
::
all_of
[
match
::
inputs
()](
match
::
transpose
_shape
(
)));
return
match
::
name
(
"concat"
)(
match
::
all_of
[
match
::
inputs
()](
match
::
name
(
"
transpose
"
)));
}
void
apply
(
module
&
m
,
const
match
::
matcher_result
&
mr
)
const
...
...
@@ -601,6 +601,69 @@ struct find_transpose_contiguous_reshaper_unary
}
};
struct
find_slice_transpose
{
auto
matcher
()
const
{
return
match
::
any
(
match
::
any_of
[
match
::
outputs
()](
match
::
name
(
"slice"
)(
match
::
output
(
match
::
name
(
"transpose"
)))));
}
static
std
::
vector
<
int64_t
>
find_common_perm
(
const
std
::
vector
<
instruction_ref
>&
transposes
)
{
std
::
map
<
std
::
vector
<
int64_t
>
,
int64_t
>
count
;
for
(
auto
t
:
transposes
)
{
auto
perm
=
t
->
get_operator
().
to_value
()[
"permutation"
].
to_vector
<
int64_t
>
();
count
[
perm
]
++
;
}
return
std
::
max_element
(
count
.
begin
(),
count
.
end
(),
by
(
std
::
less
<>
{},
[](
auto
&&
p
)
{
return
p
.
second
;
}))
->
first
;
}
void
apply
(
module
&
m
,
const
match
::
matcher_result
&
r
)
const
{
auto
ins
=
r
.
result
;
std
::
vector
<
instruction_ref
>
splits
;
std
::
copy_if
(
ins
->
outputs
().
begin
(),
ins
->
outputs
().
end
(),
std
::
back_inserter
(
splits
),
[
&
](
instruction_ref
out
)
{
return
out
->
name
()
==
"slice"
and
out
->
outputs
().
size
()
==
1
and
out
->
outputs
().
front
()
->
name
()
==
"transpose"
;
});
if
(
splits
.
size
()
<
2
)
return
;
std
::
vector
<
instruction_ref
>
transposes
;
std
::
transform
(
splits
.
begin
(),
splits
.
end
(),
std
::
back_inserter
(
transposes
),
[](
auto
split
)
{
return
split
->
outputs
().
front
();
});
auto
perm
=
find_common_perm
(
transposes
);
auto
iperm
=
invert_permutation
(
perm
);
auto
pre
=
m
.
insert_instruction
(
std
::
next
(
ins
),
make_op
(
"transpose"
,
{{
"permutation"
,
perm
}}),
ins
);
for
(
auto
i
:
range
(
transposes
.
size
()))
{
auto
split
=
splits
[
i
];
auto
t
=
transposes
[
i
];
auto
op
=
any_cast
<
op
::
slice
>
(
split
->
get_operator
());
std
::
transform
(
op
.
axes
.
begin
(),
op
.
axes
.
end
(),
op
.
axes
.
begin
(),
[
&
](
auto
axis
)
{
return
iperm
[
axis
];
});
auto
new_ins
=
m
.
insert_instruction
(
t
,
op
,
pre
);
if
(
t
->
get_operator
()
!=
pre
->
get_operator
())
{
auto
curr
=
t
->
get_operator
().
to_value
()[
"permutation"
].
to_vector
<
int64_t
>
();
new_ins
=
m
.
insert_instruction
(
t
,
make_op
(
"transpose"
,
{{
"permutation"
,
reorder_dims
(
iperm
,
curr
)}}),
new_ins
);
}
m
.
replace_instruction
(
t
,
new_ins
);
}
}
};
void
simplify_reshapes
::
apply
(
module
&
m
)
const
{
for
(
int
i
=
0
;
i
<
2
;
i
++
)
...
...
@@ -616,6 +679,7 @@ void simplify_reshapes::apply(module& m) const
find_nested_convert
{},
find_nested_slice
{},
find_nested_concat
{},
find_slice_transpose
{},
find_transpose_contiguous_reshaper_unary
{});
dead_code_elimination
{}.
apply
(
m
);
}
...
...
src/target_assignments.cpp
0 → 100644
View file @
2ba401f0
/*
* The MIT License (MIT)
*
* Copyright (c) 2015-2022 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
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <migraphx/target_assignments.hpp>
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
void
target_assignments
::
add_assignment
(
instruction_ref
ins
,
const
std
::
string
&
target
)
{
assignments
.
emplace
(
ins
,
target
);
}
}
// namespace MIGRAPHX_INLINE_NS
}
// namespace migraphx
src/targets/cpu/write_literals.cpp
View file @
2ba401f0
...
...
@@ -25,6 +25,7 @@
#include <migraphx/module.hpp>
#include <migraphx/instruction.hpp>
#include <migraphx/iterator_for.hpp>
#include <migraphx/register_op.hpp>
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
...
...
@@ -52,6 +53,7 @@ struct cpu_literal
return
os
;
}
};
MIGRAPHX_REGISTER_OP
(
cpu_literal
);
void
write_literals
::
apply
(
module
&
m
)
const
{
...
...
src/targets/fpga/CMakeLists.txt
0 → 100644
View file @
2ba401f0
#####################################################################################
# The MIT License (MIT)
#
# Copyright (c) 2015-2022 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
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#####################################################################################
add_library
(
migraphx_fpga
target.cpp
lowering.cpp
subgraph.cpp
vitis_ai_adapter.cpp
)
set_target_properties
(
migraphx_fpga PROPERTIES EXPORT_NAME fpga
)
rocm_set_soversion
(
migraphx_fpga
${
MIGRAPHX_SO_VERSION
}
)
rocm_clang_tidy_check
(
migraphx_fpga
)
target_link_libraries
(
migraphx_fpga migraphx
)
rocm_install_targets
(
TARGETS migraphx_fpga
INCLUDE
${
CMAKE_CURRENT_SOURCE_DIR
}
/include
)
src/targets/fpga/include/migraphx/fpga/context.hpp
0 → 100644
View file @
2ba401f0
/*
* The MIT License (MIT)
*
* Copyright (c) 2015-2022 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
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MIGRAPHX_GUARD_FPGA_CONTEXT_HPP
#define MIGRAPHX_GUARD_FPGA_CONTEXT_HPP
#include <migraphx/config.hpp>
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
namespace
fpga
{
struct
context
{
int
id
=
0
;
void
finish
()
const
{}
};
}
// namespace fpga
}
// namespace MIGRAPHX_INLINE_NS
}
// namespace migraphx
#endif // MIGRAPHX_GUARD_FPGA_CONTEXT_HPP
src/targets/fpga/include/migraphx/fpga/lowering.hpp
0 → 100644
View file @
2ba401f0
/*
* The MIT License (MIT)
*
* Copyright (c) 2015-2022 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
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MIGRAPHX_GUARD_FPGA_LOWERING_HPP
#define MIGRAPHX_GUARD_FPGA_LOWERING_HPP
#include <migraphx/program.hpp>
#include <migraphx/config.hpp>
#include <migraphx/fpga/context.hpp>
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
namespace
fpga
{
struct
lowering
{
context
*
ctx
=
nullptr
;
std
::
string
name
()
const
{
return
"fpga::lowering"
;
}
void
apply
(
module
&
m
)
const
;
};
}
// namespace fpga
}
// namespace MIGRAPHX_INLINE_NS
}
// namespace migraphx
#endif // MIGRAPHX_GUARD_FPGA_LOWERING_HPP
Prev
1
2
3
4
5
6
7
8
9
10
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