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
2fc6b715
Commit
2fc6b715
authored
Apr 14, 2023
by
Paul
Browse files
Merge
parents
5967d68d
118e05c7
Changes
177
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
644 additions
and
94 deletions
+644
-94
src/register_op.cpp
src/register_op.cpp
+10
-0
src/register_target.cpp
src/register_target.cpp
+23
-1
src/replace_allocate.cpp
src/replace_allocate.cpp
+1
-2
src/schedule.cpp
src/schedule.cpp
+3
-3
src/shape.cpp
src/shape.cpp
+83
-34
src/simplify_algebra.cpp
src/simplify_algebra.cpp
+36
-3
src/simplify_reshapes.cpp
src/simplify_reshapes.cpp
+1
-1
src/split_single_dyn_dim.cpp
src/split_single_dyn_dim.cpp
+126
-0
src/targets/cpu/include/migraphx/cpu/parallel.hpp
src/targets/cpu/include/migraphx/cpu/parallel.hpp
+1
-1
src/targets/cpu/include/migraphx/cpu/target.hpp
src/targets/cpu/include/migraphx/cpu/target.hpp
+0
-3
src/targets/cpu/target.cpp
src/targets/cpu/target.cpp
+0
-2
src/targets/fpga/include/migraphx/fpga/target.hpp
src/targets/fpga/include/migraphx/fpga/target.hpp
+0
-3
src/targets/gpu/CMakeLists.txt
src/targets/gpu/CMakeLists.txt
+2
-1
src/targets/gpu/compile_gen.cpp
src/targets/gpu/compile_gen.cpp
+137
-4
src/targets/gpu/compile_hip.cpp
src/targets/gpu/compile_hip.cpp
+52
-12
src/targets/gpu/fuse_mlir.cpp
src/targets/gpu/fuse_mlir.cpp
+37
-22
src/targets/gpu/hip.cpp
src/targets/gpu/hip.cpp
+14
-2
src/targets/gpu/hiprtc/CMakeLists.txt
src/targets/gpu/hiprtc/CMakeLists.txt
+33
-0
src/targets/gpu/hiprtc/main.cpp
src/targets/gpu/hiprtc/main.cpp
+68
-0
src/targets/gpu/include/migraphx/gpu/compile_gen.hpp
src/targets/gpu/include/migraphx/gpu/compile_gen.hpp
+17
-0
No files found.
src/register_op.cpp
View file @
2fc6b715
...
...
@@ -33,7 +33,17 @@ std::unordered_map<std::string, operation>& op_map()
static
std
::
unordered_map
<
std
::
string
,
operation
>
m
;
// NOLINT
return
m
;
}
void
register_op_init
()
{
(
void
)
op_map
();
}
void
register_op
(
const
operation
&
op
)
{
op_map
()[
op
.
name
()]
=
op
;
}
void
unregister_op
(
const
std
::
string
&
op_name
)
{
assert
(
op_map
().
count
(
op_name
));
op_map
().
erase
(
op_name
);
}
operation
load_op
(
const
std
::
string
&
name
)
{
return
at
(
op_map
(),
name
,
"Operator not found: "
+
name
);
...
...
src/register_target.cpp
View file @
2fc6b715
...
...
@@ -21,26 +21,48 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string>
#include <unordered_map>
#include <migraphx/register_target.hpp>
#include <migraphx/ranges.hpp>
#include <migraphx/dynamic_loader.hpp>
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
void
store_target_lib
(
const
dynamic_loader
&
lib
)
{
static
std
::
vector
<
dynamic_loader
>
target_loader
;
target_loader
.
emplace_back
(
lib
);
}
std
::
unordered_map
<
std
::
string
,
target
>&
target_map
()
{
static
std
::
unordered_map
<
std
::
string
,
target
>
m
;
// NOLINT
return
m
;
}
void
register_target_init
()
{
(
void
)
target_map
();
}
void
unregister_target
(
const
std
::
string
&
name
)
{
assert
(
target_map
().
count
(
name
));
target_map
().
erase
(
name
);
}
void
register_target
(
const
target
&
t
)
{
target_map
()[
t
.
name
()]
=
t
;
}
target
make_target
(
const
std
::
string
&
name
)
{
if
(
not
contains
(
target_map
(),
name
))
{
std
::
string
target_name
=
"libmigraphx_"
+
name
+
".so"
;
store_target_lib
(
dynamic_loader
(
target_name
));
}
const
auto
it
=
target_map
().
find
(
name
);
if
(
it
==
target_map
().
end
())
{
MIGRAPHX_THROW
(
"Requested target '"
+
name
+
"' is not
enabl
ed or not supported"
);
MIGRAPHX_THROW
(
"Requested target '"
+
name
+
"' is not
load
ed or not supported"
);
}
return
it
->
second
;
}
...
...
src/replace_allocate.cpp
View file @
2fc6b715
...
...
@@ -104,8 +104,7 @@ void replace_allocate::apply(module& m) const
continue
;
auto
s
=
ins
->
get_shape
();
if
(
not
(
main_offload_copy
or
m
.
use_local_alloc
)
and
model
.
needs_out_params
()
and
contains
(
mod_output_names
,
ins
))
if
(
not
main_offload_copy
and
model
.
needs_out_params
()
and
contains
(
mod_output_names
,
ins
))
{
auto
out_param
=
m
.
add_parameter
(
mod_output_names
[
ins
],
s
);
m
.
replace_instruction
(
ins
,
out_param
);
...
...
src/schedule.cpp
View file @
2fc6b715
...
...
@@ -327,10 +327,10 @@ struct stream_info
return
[
=
](
auto
f
)
{
return
fix
<
bool
>
([
&
](
auto
self
,
auto
ins
)
{
return
all_of
(
select
(
ins
),
[
&
](
auto
i
)
{
if
(
iweights
.
at
(
i
)
==
0
)
return
self
(
i
);
else
if
(
has_stream
(
i
))
return
f
(
this
->
get_stream
(
i
));
else
return
self
(
i
);
});
})(
start
);
};
...
...
src/shape.cpp
View file @
2fc6b715
...
...
@@ -74,13 +74,23 @@ struct shape_impl
shape_impl
(
shape
::
type_t
t
,
std
::
vector
<
std
::
size_t
>
mins
,
std
::
vector
<
std
::
size_t
>
maxes
,
std
::
vector
<
std
::
size_t
>
opt
s
)
std
::
vector
<
std
::
set
<
std
::
size_t
>
>
opt
imals_list
)
:
m_type
(
t
)
{
assert
(
mins
.
size
()
==
maxes
.
size
()
and
maxes
.
size
()
==
opts
.
size
());
for
(
size_t
i
=
0
;
i
<
mins
.
size
();
++
i
)
if
(
optimals_list
.
empty
())
{
m_dyn_dims
.
push_back
(
shape
::
dynamic_dimension
{
mins
[
i
],
maxes
[
i
],
opts
[
i
]});
for
(
size_t
i
=
0
;
i
<
mins
.
size
();
++
i
)
{
m_dyn_dims
.
push_back
(
shape
::
dynamic_dimension
{
mins
[
i
],
maxes
[
i
]});
}
}
else
{
assert
(
mins
.
size
()
==
maxes
.
size
()
and
maxes
.
size
()
==
optimals_list
.
size
());
for
(
size_t
i
=
0
;
i
<
mins
.
size
();
++
i
)
{
m_dyn_dims
.
push_back
(
shape
::
dynamic_dimension
{
mins
[
i
],
maxes
[
i
],
optimals_list
[
i
]});
}
}
}
...
...
@@ -147,7 +157,7 @@ struct shape_impl
std
::
transform
(
m_dyn_dims
.
cbegin
(),
m_dyn_dims
.
cend
(),
ret
.
begin
(),
[](
shape
::
dynamic_dimension
x
)
{
return
x
.
min
;
});
[](
const
shape
::
dynamic_dimension
&
x
)
{
return
x
.
min
;
});
return
ret
;
}
...
...
@@ -157,19 +167,20 @@ struct shape_impl
std
::
transform
(
m_dyn_dims
.
cbegin
(),
m_dyn_dims
.
cend
(),
ret
.
begin
(),
[](
shape
::
dynamic_dimension
x
)
{
return
x
.
max
;
});
[](
const
shape
::
dynamic_dimension
&
x
)
{
return
x
.
max
;
});
return
ret
;
}
std
::
vector
<
std
::
size_t
>
opt_lens
()
const
std
::
vector
<
std
::
set
<
std
::
size_t
>
>
opt_lens
()
const
{
std
::
vector
<
std
::
size_t
>
ret
(
m_dyn_dims
.
size
());
std
::
vector
<
std
::
set
<
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
;
});
[](
const
shape
::
dynamic_dimension
&
x
)
{
return
x
.
opt
imals
;
});
return
ret
;
}
// Does the shape skip over elements?
bool
skips
()
const
{
...
...
@@ -240,8 +251,9 @@ shape::shape(type_t t, std::vector<shape::dynamic_dimension> dims)
shape
::
shape
(
type_t
t
,
std
::
vector
<
std
::
size_t
>
mins
,
std
::
vector
<
std
::
size_t
>
maxes
,
std
::
vector
<
std
::
size_t
>
opts
)
:
impl
(
std
::
make_shared
<
shape_impl
>
(
t
,
std
::
move
(
mins
),
std
::
move
(
maxes
),
std
::
move
(
opts
)))
std
::
vector
<
std
::
set
<
std
::
size_t
>>
optimals_list
)
:
impl
(
std
::
make_shared
<
shape_impl
>
(
t
,
std
::
move
(
mins
),
std
::
move
(
maxes
),
std
::
move
(
optimals_list
)))
{
}
...
...
@@ -469,12 +481,44 @@ shape shape::with_type(type_t t) const
shape
shape
::
to_dynamic
()
const
{
if
(
not
sub_shapes
().
empty
())
{
std
::
vector
<
shape
>
subs
;
std
::
transform
(
sub_shapes
().
cbegin
(),
sub_shapes
().
cend
(),
std
::
back_inserter
(
subs
),
[](
auto
s
)
{
return
s
.
to_dynamic
();
});
return
{
subs
};
}
if
(
this
->
dynamic
())
{
return
*
this
;
}
std
::
vector
<
std
::
size_t
>
zeroes
(
this
->
ndim
(),
0
);
return
{
type
(),
lens
(),
lens
(),
zeroes
};
return
{
type
(),
lens
(),
lens
(),
{}};
}
shape
shape
::
to_static
(
std
::
size_t
x
)
const
{
if
(
not
sub_shapes
().
empty
())
{
std
::
vector
<
shape
>
subs
;
std
::
transform
(
sub_shapes
().
cbegin
(),
sub_shapes
().
cend
(),
std
::
back_inserter
(
subs
),
[
&
](
auto
s
)
{
return
s
.
to_static
(
x
);
});
return
{
subs
};
}
if
(
not
this
->
dynamic
())
{
return
*
this
;
}
auto
static_lens
=
this
->
max_lens
();
std
::
transform
(
static_lens
.
begin
(),
static_lens
.
end
(),
this
->
dyn_dims
().
cbegin
(),
static_lens
.
begin
(),
[
&
](
auto
sl
,
auto
dd
)
{
return
dd
.
is_fixed
()
?
sl
:
x
;
});
return
{
type
(),
static_lens
};
}
std
::
size_t
shape
::
element_space
()
const
{
return
impl
->
element_space
();
}
...
...
@@ -506,23 +550,22 @@ 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
();
}
std
::
vector
<
std
::
set
<
std
::
size_t
>>
shape
::
opt_lens
()
const
{
return
impl
->
opt_lens
();
}
bool
shape
::
dynamic_dimension
::
is_fixed
()
const
{
return
this
->
min
==
this
->
max
;
}
bool
shape
::
dynamic_dimension
::
has_optimal
()
const
{
return
opt
!=
0
;
}
bool
shape
::
dynamic_dimension
::
has_optimal
()
const
{
return
not
optimals
.
empty
()
;
}
shape
::
dynamic_dimension
&
shape
::
dynamic_dimension
::
operator
+=
(
const
std
::
size_t
&
x
)
{
this
->
min
+=
x
;
this
->
max
+=
x
;
if
(
this
->
opt
!=
0
)
{
this
->
opt
+=
x
;
};
std
::
set
<
std
::
size_t
>
new_optimals
;
std
::
transform
(
this
->
optimals
.
begin
(),
this
->
optimals
.
end
(),
std
::
inserter
(
new_optimals
,
new_optimals
.
begin
()),
[
&
x
](
const
auto
&
opt
)
{
return
(
opt
+
x
);
});
this
->
optimals
=
new_optimals
;
return
*
this
;
}
...
...
@@ -532,19 +575,23 @@ shape::dynamic_dimension& shape::dynamic_dimension::operator-=(const std::size_t
assert
(
this
->
max
>=
x
);
this
->
min
-=
x
;
this
->
max
-=
x
;
if
(
this
->
opt
!=
0
)
{
assert
(
this
->
opt
>=
x
);
this
->
opt
-=
x
;
}
std
::
set
<
std
::
size_t
>
new_optimals
;
std
::
transform
(
this
->
optimals
.
begin
(),
this
->
optimals
.
end
(),
std
::
inserter
(
new_optimals
,
new_optimals
.
begin
()),
[
&
x
](
const
auto
&
opt
)
{
assert
(
opt
>=
x
);
return
(
opt
-
x
);
});
this
->
optimals
=
new_optimals
;
return
*
this
;
}
bool
operator
==
(
const
shape
::
dynamic_dimension
&
x
,
const
shape
::
dynamic_dimension
&
y
)
{
// don't check opt if both are fixed
// don't check opt
imals
if both are fixed
return
(
x
.
min
==
y
.
min
and
x
.
max
==
y
.
max
and
((
x
.
is_fixed
()
and
y
.
is_fixed
())
or
(
x
.
opt
==
y
.
opt
)));
((
x
.
is_fixed
()
and
y
.
is_fixed
())
or
(
x
.
opt
imals
==
y
.
opt
imals
)));
}
bool
operator
!=
(
const
shape
::
dynamic_dimension
&
x
,
const
shape
::
dynamic_dimension
&
y
)
...
...
@@ -553,7 +600,7 @@ bool operator!=(const shape::dynamic_dimension& x, const shape::dynamic_dimensio
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
shape
::
dynamic_dimension
&
x
)
{
os
<<
"["
<<
x
.
min
<<
", "
<<
x
.
max
<<
", "
<<
x
.
opt
<<
"]"
;
os
<<
"[
"
<<
x
.
min
<<
", "
<<
x
.
max
<<
",
{
"
<<
migraphx
::
to_string_range
(
x
.
optimals
)
<<
"
}
]"
;
return
os
;
}
...
...
@@ -663,10 +710,12 @@ void migraphx_from_value(const value& v, shape& s)
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
};
auto
x_min
=
x
.
at
(
"min"
).
template
to
<
size_t
>();
auto
x_max
=
x
.
at
(
"max"
).
template
to
<
size_t
>();
auto
v_optimals
=
x
.
at
(
"optimals"
);
std
::
set
<
size_t
>
set_x_optimals
=
from_value
<
std
::
set
<
std
::
size_t
>>
(
x
.
at
(
"optimals"
));
return
shape
::
dynamic_dimension
{
x_min
,
x_max
,
set_x_optimals
};
});
s
=
shape
{
shape
::
parse_type
(
t
),
dyn_dims
};
...
...
src/simplify_algebra.cpp
View file @
2fc6b715
...
...
@@ -52,8 +52,9 @@ auto op_lit_broadcast(std::string op, std::string x, std::string y)
auto
conv_const_weights
()
{
return
match
::
name
(
"convolution"
)(
match
::
used_once
(),
match
::
args
(
match
::
any
(),
match
::
is_constant
().
bind
(
"w"
)));
return
match
::
name
(
"convolution"
)(
match
::
used_once
(),
match
::
args
(
match
::
none_of
(
match
::
is_constant
()),
match
::
is_constant
().
bind
(
"w"
)));
}
auto
reduction
()
{
return
match
::
name_contains
(
"reduce"
);
}
...
...
@@ -203,7 +204,12 @@ struct find_mul_slice_conv
}
};
// a * (x + b) => a * x + a * b
// ******************************
// a * (x + b) => a * x + a * b
// ******************************
// When a * (x + b) is followed by another add of constant, then the
// additional add can be const folded. Also, better fusions can be applied
// when the add comes after.
struct
find_mul_add
{
auto
matcher
()
const
...
...
@@ -268,6 +274,32 @@ struct find_dot_add
}
};
struct
find_conv_add
{
auto
matcher
()
const
{
auto
add
=
match
::
name
(
"add"
)(
match
::
either_arg
(
0
,
1
)(
match
::
any
().
bind
(
"x"
),
match
::
any_of
(
match
::
is_constant
()).
bind
(
"a"
)),
match
::
used_once
());
return
match
::
name
(
"convolution"
)(
match
::
used_once
(),
match
::
args
(
add
,
match
::
is_constant
().
bind
(
"w"
)));
}
void
apply
(
module
&
m
,
const
match
::
matcher_result
&
r
)
const
{
auto
ins
=
r
.
result
;
auto
a_ins
=
r
.
instructions
[
"a"
];
auto
x_ins
=
r
.
instructions
[
"x"
];
auto
w_ins
=
r
.
instructions
[
"w"
];
auto
conv1
=
m
.
insert_instruction
(
ins
,
ins
->
get_operator
(),
a_ins
,
w_ins
);
auto
conv2
=
m
.
insert_instruction
(
ins
,
ins
->
get_operator
(),
x_ins
,
w_ins
);
m
.
replace_instruction
(
ins
,
make_op
(
"add"
),
conv1
,
conv2
);
}
};
struct
find_add_lit_broadcast
{
auto
matcher
()
const
...
...
@@ -1239,6 +1271,7 @@ void simplify_algebra::apply(module& m) const
find_neg_unit_ops
{},
find_zero_ops
{},
find_dot_add
{},
find_conv_add
{},
find_div_const
{},
find_sub_const
{},
find_rsqrt
{},
...
...
src/simplify_reshapes.cpp
View file @
2fc6b715
...
...
@@ -786,7 +786,7 @@ struct find_transpose_slice
return
;
// Compute axis before transpose to use for unsqueeze
auto
perm
=
ins
->
get_operator
().
to_value
()[
"permutation"
].
to_vector
<
int64_t
>
();
auto
preaxis
=
std
::
find
(
perm
.
begin
(),
perm
.
end
(),
axis
)
-
perm
.
begin
()
;
auto
preaxis
=
perm
[
axis
]
;
// Make unsqueeze
std
::
vector
<
int64_t
>
steps
(
sdistance
.
size
());
std
::
transform
(
...
...
src/split_single_dyn_dim.cpp
0 → 100644
View file @
2fc6b715
/*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 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/split_single_dyn_dim.hpp>
#include <migraphx/module.hpp>
#include <migraphx/pass_manager.hpp>
#include <migraphx/functional.hpp>
#include <migraphx/make_op.hpp>
#include <migraphx/ranges.hpp>
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
struct
dynamic_dimensions_check
{
std
::
string
dyn_param_str
;
size_t
dyn_index
;
size_t
min_dim
;
size_t
max_dim
;
};
optional
<
dynamic_dimensions_check
>
has_one_dyn_dim
(
const
std
::
unordered_map
<
std
::
string
,
shape
>&
param_shapes
)
{
// True if parameters contain exactly one dynamic shape with exactly one non-fixed
// dynamic_dimension.
auto
is_dynamic
=
[](
const
auto
&
p
)
{
return
p
.
second
.
dynamic
();
};
auto
ps_it
=
std
::
find_if
(
param_shapes
.
begin
(),
param_shapes
.
end
(),
is_dynamic
);
if
(
ps_it
==
param_shapes
.
end
())
return
std
::
nullopt
;
// Check if there is a second dynamic parameter
if
(
std
::
any_of
(
std
::
next
(
ps_it
),
param_shapes
.
end
(),
is_dynamic
))
return
std
::
nullopt
;
const
auto
&
dds
=
ps_it
->
second
.
dyn_dims
();
auto
is_non_fixed
=
[](
const
auto
&
dd
)
{
return
not
dd
.
is_fixed
();
};
auto
dds_it
=
std
::
find_if
(
dds
.
begin
(),
dds
.
end
(),
is_non_fixed
);
if
(
dds_it
==
dds
.
end
())
return
std
::
nullopt
;
// Check if there is a second non-fixed dynamic_dimension
if
(
std
::
any_of
(
std
::
next
(
dds_it
),
dds
.
end
(),
is_non_fixed
))
return
std
::
nullopt
;
return
dynamic_dimensions_check
{
ps_it
->
first
,
static_cast
<
std
::
size_t
>
(
std
::
distance
(
dds
.
begin
(),
dds_it
)),
dds_it
->
min
,
dds_it
->
max
};
}
/**
* Makes all the shapes in the dynamic_dimension range.
* Probably won't work for `if` and `loop` instructions, depending on how the submodules for those
* work. Inserts select_module instruction to the top. Replaces return, bypassing other
* instructions.
*/
void
split_single_dyn_dim
::
apply
(
module_pass_manager
&
mpm
)
const
{
module_ref
mm
=
&
mpm
.
get_module
();
auto
param_names
=
mm
->
get_parameter_names
();
auto
param_shapes
=
mm
->
get_parameter_shapes
();
optional
<
dynamic_dimensions_check
>
dd_check
=
has_one_dyn_dim
(
param_shapes
);
if
(
dd_check
.
has_value
())
{
const
auto
&
dyn_param
=
mm
->
get_parameter
(
dd_check
->
dyn_param_str
);
auto
dyn_param_shape
=
mm
->
get_parameter_shape
(
dd_check
->
dyn_param_str
);
std
::
vector
<
module_ref
>
submodules
;
// create submodules for each dimension size
for
(
size_t
dim_size
:
migraphx
::
range
(
dd_check
->
min_dim
,
dd_check
->
max_dim
+
1
))
{
auto
*
submod
=
mpm
.
create_module
(
"dim_"
+
std
::
to_string
(
dim_size
));
// instruction map for new static shaped submodule parameters
std
::
unordered_map
<
instruction_ref
,
instruction_ref
>
map_ins
;
// create static shape using dim_size
auto
static_lens
=
dyn_param_shape
.
max_lens
();
static_lens
.
at
(
dd_check
->
dyn_index
)
=
dim_size
;
map_ins
[
dyn_param
]
=
submod
->
add_parameter
(
dd_check
->
dyn_param_str
,
migraphx
::
shape
{
dyn_param_shape
.
type
(),
static_lens
});
auto
outputs
=
submod
->
add_instructions
(
mm
,
map_ins
);
submod
->
add_return
({
outputs
});
submodules
.
push_back
(
submod
);
}
// redirect to select_module operator and return
std
::
vector
<
instruction_ref
>
sm_inputs
;
std
::
transform
(
param_names
.
cbegin
(),
param_names
.
cend
(),
std
::
back_inserter
(
sm_inputs
),
[
&
](
auto
pn
)
{
return
mm
->
get_parameter
(
pn
);
});
auto
output_shapes
=
mm
->
get_output_shapes
();
migraphx
::
shape
out_attr
=
migraphx
::
shape
{
output_shapes
};
auto
sm_ins
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"select_module"
,
{{
"output_dyn_shapes"
,
migraphx
::
to_value
(
out_attr
)}}),
sm_inputs
,
submodules
);
std
::
vector
<
instruction_ref
>
outputs
(
output_shapes
.
size
());
for
(
size_t
i
=
0
;
i
<
output_shapes
.
size
();
++
i
)
{
outputs
.
at
(
i
)
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"get_tuple_elem"
,
{{
"index"
,
i
}}),
sm_ins
);
}
mm
->
replace_return
(
outputs
);
}
}
}
// namespace MIGRAPHX_INLINE_NS
}
// namespace migraphx
src/targets/cpu/include/migraphx/cpu/parallel.hpp
View file @
2fc6b715
...
...
@@ -25,7 +25,7 @@
#define MIGRAPHX_GUARD_AMDMIGRAPHX_CPU_PARALLEL_HPP
// #define MIGRAPHX_DISABLE_OMP
#include <cmath>
#include <migraphx/config.hpp>
#ifdef MIGRAPHX_DISABLE_OMP
#include <migraphx/par_for.hpp>
...
...
src/targets/cpu/include/migraphx/cpu/target.hpp
View file @
2fc6b715
...
...
@@ -40,14 +40,11 @@ struct target
std
::
string
name
()
const
;
std
::
vector
<
pass
>
get_passes
(
migraphx
::
context
&
gctx
,
const
compile_options
&
)
const
;
migraphx
::
context
get_context
()
const
{
return
context
{};
}
argument
copy_to
(
const
argument
&
arg
)
const
{
return
arg
;
}
argument
copy_from
(
const
argument
&
arg
)
const
{
return
arg
;
}
argument
allocate
(
const
shape
&
s
)
const
;
};
MIGRAPHX_REGISTER_TARGET
(
target
);
}
// namespace cpu
}
// namespace MIGRAPHX_INLINE_NS
}
// namespace migraphx
...
...
src/targets/cpu/target.cpp
View file @
2fc6b715
...
...
@@ -23,7 +23,6 @@
*/
#include <migraphx/auto_contiguous.hpp>
#include <migraphx/check_context.hpp>
#include <migraphx/adjust_allocation.hpp>
#include <migraphx/dead_code_elimination.hpp>
#include <migraphx/eliminate_allocation.hpp>
...
...
@@ -83,7 +82,6 @@ std::vector<pass> target::get_passes(migraphx::context& gctx, const compile_opti
dead_code_elimination
{},
simplify_algebra
{},
simplify_reshapes
{},
layout_nhwc
{},
dead_code_elimination
{},
simplify_reshapes
{},
simplify_algebra
{},
...
...
src/targets/fpga/include/migraphx/fpga/target.hpp
View file @
2fc6b715
...
...
@@ -43,14 +43,11 @@ struct target
std
::
vector
<
pass
>
get_passes
(
migraphx
::
context
&
ctx
,
const
compile_options
&
)
const
;
migraphx
::
context
get_context
()
const
{
return
context
{};
}
supported_segments
find_supported
(
const_module_ref
mod
,
support_metric
m
)
const
;
argument
copy_to
(
const
argument
&
arg
)
const
{
return
arg
;
}
argument
copy_from
(
const
argument
&
arg
)
const
{
return
arg
;
}
argument
allocate
(
const
shape
&
s
)
const
;
};
MIGRAPHX_REGISTER_TARGET
(
target
);
}
// namespace fpga
}
// namespace MIGRAPHX_INLINE_NS
}
// namespace migraphx
...
...
src/targets/gpu/CMakeLists.txt
View file @
2fc6b715
...
...
@@ -22,7 +22,7 @@
# THE SOFTWARE.
# ####################################################################################
list
(
APPEND CMAKE_PREFIX_PATH /opt/rocm
/opt/rocm/hip
)
list
(
APPEND CMAKE_PREFIX_PATH /opt/rocm
)
find_package
(
miopen
)
# rocblas
...
...
@@ -240,6 +240,7 @@ target_link_libraries(migraphx_gpu PUBLIC migraphx MIOpen roc::rocblas)
target_link_libraries
(
migraphx_gpu PRIVATE migraphx_device migraphx_kernels
)
add_subdirectory
(
driver
)
add_subdirectory
(
hiprtc
)
rocm_install_targets
(
TARGETS migraphx_gpu migraphx_device compile_for_gpu
...
...
src/targets/gpu/compile_gen.cpp
View file @
2fc6b715
...
...
@@ -168,7 +168,7 @@ std::string make_transformer_args(std::vector<std::string> transformers)
return
join_strings
(
std
::
move
(
transformers
),
", "
);
}
std
::
string
generate_pointwise
(
const
module
&
pm
,
const
std
::
string
&
name
)
void
generate_pointwise
(
cpp_generator
&
gg
,
const
module
&
pm
,
const
std
::
string
&
name
)
{
module
m
=
pm
;
run_passes
(
m
,
{
eliminate_common_subexpression
{},
dead_code_elimination
{}});
...
...
@@ -184,8 +184,131 @@ std::string generate_pointwise(const module& pm, const std::string& name)
// Add explict conversions
g
.
fresult
(
[](
const
shape
&
s
)
{
return
"migraphx::convert<"
+
shape
::
cpp_type
(
s
.
type
())
+
">"
;
});
g
.
create_function
(
g
.
generate_module
(
m
).
set_attributes
({
"__device__"
}).
set_generic_types
(
m
).
set_name
(
name
));
gg
.
create_function
(
g
.
generate_module
(
m
)
.
set_attributes
({
"__device__"
,
"__attribute__((const))"
})
.
set_generic_types
(
m
)
.
set_name
(
name
));
}
std
::
string
generate_pointwise
(
const
module
&
pm
,
const
std
::
string
&
name
)
{
cpp_generator
g
;
generate_pointwise
(
g
,
pm
,
name
);
return
g
.
str
();
}
std
::
string
reduce_op
::
str
()
const
{
return
write
+
"(r.reduce("
+
reduction
+
", "
+
init
+
", "
+
read
+
")("
+
input
+
"))"
;
}
void
reduce_op
::
set
(
instruction_ref
ins
,
const
operation
&
op
)
{
if
(
op
.
name
()
==
"reduce_sum"
)
{
reduction
=
"op::sum{}"
;
}
else
if
(
op
.
name
()
==
"reduce_mean"
)
{
auto
s
=
ins
->
inputs
().
front
()
->
get_shape
();
auto
reduce_elements
=
s
.
elements
()
/
ins
->
get_shape
().
elements
();
auto
reduce_type
=
s
.
type
();
reduction
=
"op::sum{}"
;
std
::
string
mean
=
"op::mean<"
+
std
::
to_string
(
reduce_elements
)
+
">{}"
;
// Use float accumulator when reduction size is too large for half
if
(
reduce_type
==
shape
::
half_type
and
reduce_elements
>
16384
)
read
=
"compose("
+
mean
+
", op::convert_to<float>{})"
;
else
if
(
contains
({
shape
::
float_type
,
shape
::
half_type
,
shape
::
double_type
},
reduce_type
))
read
=
mean
;
else
write
=
mean
;
}
else
if
(
op
.
name
()
==
"reduce_max"
)
{
reduction
=
"op::max{}"
;
init
=
"lowest{}"
;
}
else
if
(
op
.
name
()
==
"reduce_min"
)
{
reduction
=
"op::min{}"
;
init
=
"highest{}"
;
}
else
if
(
op
.
name
()
==
"reduce_prod"
)
{
reduction
=
"op::product{}"
;
init
=
"1"
;
}
else
{
MIGRAPHX_THROW
(
"Unsupported reduce"
);
}
}
std
::
string
reduce_op
::
generate
(
instruction_ref
ins
,
const
std
::
string
&
x
)
{
reduce_op
r
{
x
};
r
.
set
(
ins
,
ins
->
get_operator
());
return
r
.
str
();
}
static
bool
use_lazy_inner
(
instruction_ref
ins
)
{
if
(
ins
->
outputs
().
size
()
!=
1
)
return
false
;
auto
output
=
ins
->
outputs
().
front
();
return
contains
(
output
->
name
(),
"reduce"
)
or
output
->
name
()
==
"@return"
;
}
std
::
string
generate_reduce
(
const
module
&
m
,
const
std
::
string
&
name
)
{
cpp_generator
g
;
auto
ilens
=
m
.
get_parameter_shapes
().
begin
()
->
second
.
lens
();
std
::
size_t
i
=
0
;
auto
f
=
g
.
generate_module
(
m
,
[
&
](
instruction_ref
ins
,
const
auto
&
names
)
{
if
(
contains
(
ins
->
name
(),
"reduce"
))
{
return
reduce_op
::
generate
(
ins
,
names
.
at
(
ins
->
inputs
().
front
()));
}
else
if
(
ins
->
name
()
==
"pointwise"
)
{
auto
pointwise_name
=
"pointwise"
+
std
::
to_string
(
i
);
i
++
;
generate_pointwise
(
g
,
*
ins
->
module_inputs
().
front
(),
pointwise_name
);
std
::
vector
<
instruction_ref
>
tensors
;
std
::
copy_if
(
ins
->
inputs
().
begin
(),
ins
->
inputs
().
end
(),
std
::
back_inserter
(
tensors
),
[
&
](
auto
input
)
{
return
input
->
get_shape
().
lens
()
==
ilens
and
not
input
->
get_shape
().
broadcasted
();
});
auto
inner_names
=
names
;
for
(
auto
input
:
tensors
)
inner_names
[
input
]
+=
"_lambda_param"
;
auto
call_function
=
pointwise_name
+
"("
+
join_strings
(
cpp_generator
::
to_args
(
ins
->
inputs
(),
inner_names
),
", "
)
+
")"
;
if
(
tensors
.
empty
())
return
call_function
;
const
std
::
string
inner_template
=
"r.${inner}([=](${params}) { return ${call}; })(${args})"
;
std
::
string
inner_name
=
use_lazy_inner
(
ins
)
?
"lazy_inner"
:
"inner"
;
auto
args
=
cpp_generator
::
to_args
(
tensors
,
names
);
auto
params
=
cpp_generator
::
to_args
(
tensors
,
inner_names
);
std
::
transform
(
params
.
begin
(),
params
.
end
(),
params
.
begin
(),
[](
auto
s
)
{
return
"auto "
+
s
;
});
return
interpolate_string
(
inner_template
,
{{
"inner"
,
inner_name
},
{
"params"
,
join_strings
(
params
,
", "
)},
{
"args"
,
join_strings
(
args
,
", "
)},
{
"call"
,
call_function
}});
}
else
if
(
ins
->
name
()
==
"multibroadcast"
)
{
return
names
.
at
(
ins
->
inputs
().
front
());
}
MIGRAPHX_THROW
(
"Unknown operator: "
+
ins
->
name
());
});
f
.
set_attributes
({
"__device__"
,
"__attribute__((const))"
}).
set_generic_types
(
m
).
set_name
(
name
);
f
.
add_generic_param
(
"r"
);
g
.
create_function
(
f
);
return
g
.
str
();
}
...
...
@@ -196,7 +319,17 @@ static std::vector<std::string> get_op_names(const module& m)
{
if
(
starts_with
(
ins
.
name
(),
"@"
))
continue
;
result
.
push_back
(
ins
.
name
());
if
(
ins
.
name
()
==
"multibroadcast"
)
continue
;
if
(
ins
.
name
()
==
"pointwise"
)
{
auto
names
=
get_op_names
(
*
ins
.
module_inputs
().
front
());
result
.
insert
(
result
.
end
(),
names
.
begin
(),
names
.
end
());
}
else
{
result
.
push_back
(
ins
.
name
());
}
}
return
result
;
}
...
...
src/targets/gpu/compile_hip.cpp
View file @
2fc6b715
...
...
@@ -32,6 +32,13 @@
#ifdef MIGRAPHX_USE_HIPRTC
#include <hip/hiprtc.h>
#include <migraphx/manage_ptr.hpp>
#include <migraphx/value.hpp>
#include <migraphx/tmp_dir.hpp>
#include <migraphx/dynamic_loader.hpp>
#include <migraphx/process.hpp>
#include <migraphx/msgpack.hpp>
#include <migraphx/serialize.hpp>
#include <migraphx/file_buffer.hpp>
#else
#include <migraphx/compile_src.hpp>
#include <migraphx/process.hpp>
...
...
@@ -63,6 +70,7 @@ void hiprtc_check_error(hiprtcResult err, const std::string& msg, const std::str
throw
make_exception
(
ctx
,
hiprtc_error
(
err
,
msg
));
}
// NOLINTNEXTLINE
#define MIGRAPHX_HIPRTC(...) \
hiprtc_check_error(__VA_ARGS__, #__VA_ARGS__, MIGRAPHX_MAKE_SOURCE_CTX())
...
...
@@ -110,21 +118,19 @@ struct hiprtc_program
std
::
string
cpp_src
=
""
;
std
::
string
cpp_name
=
""
;
hiprtc_program
(
const
std
::
vector
<
src_file
>
&
srcs
)
hiprtc_program
(
std
::
vector
<
hiprtc_
src_file
>
srcs
)
{
for
(
auto
&&
src
:
srcs
)
{
std
::
string
content
{
src
.
content
.
first
,
src
.
content
.
second
};
std
::
string
path
=
src
.
path
.
string
();
if
(
src
.
path
.
extension
().
string
()
==
".cpp"
)
if
(
ends_with
(
src
.
path
,
".cpp"
))
{
cpp_src
=
std
::
move
(
content
);
cpp_name
=
std
::
move
(
path
);
cpp_src
=
std
::
move
(
src
.
content
);
cpp_name
=
std
::
move
(
src
.
path
);
}
else
{
headers
.
push_back
(
std
::
move
(
content
));
include_names
.
push_back
(
std
::
move
(
path
));
headers
.
push_back
(
std
::
move
(
src
.
content
));
include_names
.
push_back
(
std
::
move
(
src
.
path
));
}
}
prog
=
hiprtc_program_create
(
cpp_src
.
c_str
(),
...
...
@@ -134,7 +140,7 @@ struct hiprtc_program
include_names
.
data
());
}
void
compile
(
const
std
::
vector
<
std
::
string
>&
options
)
void
compile
(
const
std
::
vector
<
std
::
string
>&
options
)
const
{
if
(
enabled
(
MIGRAPHX_TRACE_HIPRTC
{}))
std
::
cout
<<
"hiprtc "
<<
join_strings
(
options
,
" "
)
<<
" "
<<
cpp_name
<<
std
::
endl
;
...
...
@@ -175,10 +181,11 @@ struct hiprtc_program
}
};
std
::
vector
<
std
::
vector
<
char
>>
compile_hip_src
(
const
std
::
vector
<
src_file
>&
srcs
,
std
::
string
params
,
const
std
::
string
&
arch
)
std
::
vector
<
std
::
vector
<
char
>>
compile_hip_src_with_hiprtc
(
std
::
vector
<
hiprtc_src_file
>
srcs
,
std
::
string
params
,
const
std
::
string
&
arch
)
{
hiprtc_program
prog
(
srcs
);
hiprtc_program
prog
(
std
::
move
(
srcs
)
)
;
auto
options
=
split_string
(
params
,
' '
);
options
.
push_back
(
"-DMIGRAPHX_USE_HIPRTC=1"
);
// remove following three compilation flags for HIPRTC once fixes from hipRTC are available in
...
...
@@ -205,8 +212,41 @@ compile_hip_src(const std::vector<src_file>& srcs, std::string params, const std
return
{
prog
.
get_code_obj
()};
}
std
::
vector
<
std
::
vector
<
char
>>
compile_hip_src
(
const
std
::
vector
<
src_file
>&
srcs
,
std
::
string
params
,
const
std
::
string
&
arch
)
{
std
::
vector
<
hiprtc_src_file
>
hsrcs
{
srcs
.
begin
(),
srcs
.
end
()};
auto
p
=
dynamic_loader
::
path
(
&
compile_hip_src_with_hiprtc
);
auto
driver
=
p
.
parent_path
().
parent_path
()
/
"bin"
/
"migraphx-hiprtc-driver"
;
if
(
fs
::
exists
(
driver
))
{
value
v
;
v
[
"srcs"
]
=
to_value
(
hsrcs
);
v
[
"params"
]
=
to_value
(
params
);
v
[
"arch"
]
=
to_value
(
arch
);
tmp_dir
td
{};
auto
out
=
td
.
path
/
"output"
;
process
(
driver
.
string
()
+
" "
+
out
.
string
()).
write
([
&
](
auto
writer
)
{
to_msgpack
(
v
,
writer
);
});
if
(
fs
::
exists
(
out
))
return
{
read_buffer
(
out
.
string
())};
}
return
compile_hip_src_with_hiprtc
(
std
::
move
(
hsrcs
),
std
::
move
(
params
),
arch
);
}
#else // MIGRAPHX_USE_HIPRTC
std
::
vector
<
std
::
vector
<
char
>>
compile_hip_src_with_hiprtc
(
std
::
vector
<
hiprtc_src_file
>
,
// NOLINT
std
::
string
,
// NOLINT
const
std
::
string
&
)
{
MIGRAPHX_THROW
(
"Not using hiprtc"
);
}
bool
is_hip_clang_compiler
()
{
static
const
auto
result
=
ends_with
(
MIGRAPHX_STRINGIZE
(
MIGRAPHX_HIP_COMPILER
),
"clang++"
);
...
...
src/targets/gpu/fuse_mlir.cpp
View file @
2fc6b715
...
...
@@ -27,6 +27,7 @@
#include <migraphx/pass_manager.hpp>
#include <migraphx/make_op.hpp>
#include <migraphx/register_op.hpp>
#include <migraphx/env.hpp>
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
...
...
@@ -35,9 +36,13 @@ struct module;
namespace
gpu
{
MIGRAPHX_DECLARE_ENV_VAR
(
MIGRAPHX_ENABLE_MLIR
);
#ifdef MIGRAPHX_MLIR
struct
mlir_conv
struct
mlir_op
{
std
::
string
name
()
const
{
return
"gpu::mlir_op"
;
}
operation
op
=
make_op
(
"convolution"
);
template
<
class
Self
,
class
F
>
...
...
@@ -46,7 +51,6 @@ struct mlir_conv
return
pack
(
f
(
self
.
op
,
"op"
));
}
std
::
string
name
()
const
{
return
"gpu::mlir_conv"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
,
const
std
::
vector
<
module_ref
>&
mods
)
const
{
check_shapes
{
inputs
,
*
this
}.
packed_or_broadcasted
();
...
...
@@ -58,7 +62,7 @@ struct mlir_conv
return
op
.
compute_shape
({
inputs
[
n
-
2
],
inputs
[
n
-
1
]});
}
};
MIGRAPHX_REGISTER_OP
(
mlir_
conv
);
MIGRAPHX_REGISTER_OP
(
mlir_
op
);
namespace
{
...
...
@@ -76,27 +80,27 @@ MIGRAPHX_PRED_MATCHER(is_mlir_conv, instruction_ref ins)
return
true
;
}
struct
find_
conv_pointwise
struct
find_
mlir_op
{
// Find a convolution followed by a pointwise operation.
auto
matcher
()
const
{
auto
convolution
=
match
::
skip
(
match
::
name
(
"
contiguous"
))(
is_mlir_conv
().
bind
(
"
convolution
"
));
return
match
::
name
(
"pointwise"
)(
match
::
any_of
[
match
::
inputs
()](
convoluti
on
.
bind
(
"x"
)));
auto
dot_or_conv
=
match
::
skip
(
match
::
name
(
"contiguous"
))(
match
::
any_of
(
match
::
name
(
"
dot"
),
is_mlir_conv
()
)
.
bind
(
"
gemm_based_op
"
));
return
match
::
name
(
"pointwise"
)(
match
::
any_of
[
match
::
inputs
()](
dot_or_c
on
v
.
bind
(
"x"
)));
}
void
apply
(
module_pass_manager
&
mpm
,
const
match
::
matcher_result
&
r
)
const
{
auto
ins
=
r
.
result
;
auto
conv_ins
=
r
.
instructions
[
"
convolution
"
];
auto
x_ins
=
r
.
instructions
[
"x"
];
// input after contiguous
auto
*
pm
=
ins
->
module_inputs
().
front
();
auto
names
=
pm
->
get_parameter_names
();
auto
ins
=
r
.
result
;
auto
gemm_based_op
=
r
.
instructions
[
"
gemm_based_op
"
];
auto
x_ins
=
r
.
instructions
[
"x"
];
// input after contiguous
auto
*
pm
=
ins
->
module_inputs
().
front
();
auto
names
=
pm
->
get_parameter_names
();
// Whitelist pointwise operators
if
(
std
::
any_of
(
pm
->
begin
(),
pm
->
end
(),
[](
const
auto
&
i
)
{
return
not
contains
({
"@literal"
,
"@param"
,
"@return"
,
"convolution"
,
"add"
,
"relu"
},
i
.
name
());
return
not
contains
(
{
"@literal"
,
"@param"
,
"@return"
,
"convolution"
,
"dot"
,
"add"
,
"relu"
},
i
.
name
());
}))
return
;
// Only fuse with fp32/fp16
...
...
@@ -110,10 +114,10 @@ struct find_conv_pointwise
mm
->
set_bypass
();
std
::
unordered_map
<
instruction_ref
,
instruction_ref
>
param_map
;
auto
x
=
mm
->
add_parameter
(
"x"
+
std
::
to_string
(
names
.
size
()),
conv_ins
->
inputs
().
at
(
0
)
->
get_shape
());
gemm_based_op
->
inputs
().
at
(
0
)
->
get_shape
());
auto
w
=
mm
->
add_parameter
(
"x"
+
std
::
to_string
(
names
.
size
()
+
1
),
conv_ins
->
inputs
().
at
(
1
)
->
get_shape
());
auto
conv
=
mm
->
add_instruction
(
conv_ins
->
get_operator
(),
{
x
,
w
});
gemm_based_op
->
inputs
().
at
(
1
)
->
get_shape
());
auto
conv
=
mm
->
add_instruction
(
gemm_based_op
->
get_operator
(),
{
x
,
w
});
std
::
transform
(
names
.
begin
(),
names
.
end
(),
ins
->
inputs
().
begin
(),
...
...
@@ -130,12 +134,13 @@ struct find_conv_pointwise
std
::
copy_if
(
ins
->
inputs
().
begin
(),
ins
->
inputs
().
end
(),
std
::
back_inserter
(
inputs
),
[
&
](
auto
input
)
{
return
input
!=
conv_ins
;
});
inputs
.
insert
(
inputs
.
end
(),
conv_ins
->
inputs
().
begin
(),
conv_ins
->
inputs
().
end
());
[
&
](
auto
input
)
{
return
input
!=
gemm_based_op
;
});
inputs
.
insert
(
inputs
.
end
(),
gemm_based_op
->
inputs
().
begin
(),
gemm_based_op
->
inputs
().
end
());
mpm
.
get_module
().
replace_instruction
(
ins
,
mlir_
conv
{
conv_ins
->
get_operator
()},
inputs
,
{
mm
});
ins
,
mlir_
op
{
gemm_based_op
->
get_operator
()},
inputs
,
{
mm
});
}
};
}
// namespace
#endif
...
...
@@ -143,7 +148,17 @@ struct find_conv_pointwise
void
fuse_mlir
::
apply
(
module_pass_manager
&
mpm
)
const
{
#ifdef MIGRAPHX_MLIR
match
::
find_matches
(
mpm
,
find_conv_pointwise
{});
const
bool
mlir_enabled
=
enabled
(
MIGRAPHX_ENABLE_MLIR
{});
if
(
mlir_enabled
)
{
match
::
find_matches
(
mpm
,
find_mlir_op
{});
}
else
{
std
::
cerr
<<
"WARNING: MIGraphX built with MLIR but it is not enabled. Please set the env "
"var MIGRAPHX_ENABLE_MLIR to use MLIR kernel generator."
<<
std
::
endl
;
}
#else
(
void
)
mpm
;
#endif
...
...
src/targets/gpu/hip.cpp
View file @
2fc6b715
...
...
@@ -189,8 +189,20 @@ argument register_on_gpu(const argument& arg)
argument
to_gpu
(
const
argument
&
arg
,
bool
host
)
{
auto
p
=
write_to_gpu
(
arg
.
data
(),
arg
.
get_shape
().
bytes
(),
host
);
return
{
arg
.
get_shape
(),
p
};
argument
result
;
arg
.
visit
(
[
&
](
auto
x
)
{
auto
p
=
write_to_gpu
(
arg
.
data
(),
arg
.
get_shape
().
bytes
(),
host
);
result
=
{
x
.
get_shape
(),
p
};
},
[
&
](
const
auto
&
xs
)
{
std
::
vector
<
argument
>
args
;
std
::
transform
(
xs
.
begin
(),
xs
.
end
(),
std
::
back_inserter
(
args
),
[
&
](
auto
x
)
{
return
to_gpu
(
x
,
host
);
});
result
=
argument
{
args
};
});
return
result
;
}
argument
from_gpu
(
const
argument
&
arg
)
...
...
src/targets/gpu/hiprtc/CMakeLists.txt
0 → 100644
View file @
2fc6b715
#####################################################################################
# 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_executable
(
migraphx-hiprtc-driver
main.cpp
)
rocm_clang_tidy_check
(
migraphx-hiprtc-driver
)
target_link_libraries
(
migraphx-hiprtc-driver PRIVATE migraphx_gpu
)
add_dependencies
(
migraphx_all_targets migraphx-hiprtc-driver
)
rocm_install_targets
(
TARGETS migraphx-hiprtc-driver
)
src/targets/gpu/hiprtc/main.cpp
0 → 100644
View file @
2fc6b715
/*
* 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/gpu/compile_hip.hpp>
#include <migraphx/serialize.hpp>
#include <migraphx/value.hpp>
#include <migraphx/msgpack.hpp>
#include <migraphx/file_buffer.hpp>
#include <migraphx/ranges.hpp>
#include <iostream>
#include <cstring>
std
::
vector
<
char
>
read_stdin
()
{
std
::
vector
<
char
>
result
;
std
::
array
<
char
,
1024
>
buffer
;
std
::
size_t
len
=
0
;
while
((
len
=
std
::
fread
(
buffer
.
data
(),
1
,
buffer
.
size
(),
stdin
))
>
0
)
{
if
(
std
::
ferror
(
stdin
)
!=
0
and
std
::
feof
(
stdin
)
==
0
)
MIGRAPHX_THROW
(
std
::
strerror
(
errno
));
result
.
insert
(
result
.
end
(),
buffer
.
data
(),
buffer
.
data
()
+
len
);
}
return
result
;
}
int
main
(
int
argc
,
char
const
*
argv
[])
{
if
(
argc
<
2
or
migraphx
::
contains
({
"-h"
,
"--help"
,
"-v"
,
"--version"
},
std
::
string
(
argv
[
1
])))
{
std
::
cout
<<
"USAGE:"
<<
std
::
endl
;
std
::
cout
<<
" "
;
std
::
cout
<<
"Used internally by migraphx to compile hip programs out-of-process."
<<
std
::
endl
;
std
::
exit
(
0
);
}
std
::
string
output_name
=
argv
[
1
];
auto
v
=
migraphx
::
from_msgpack
(
read_stdin
());
std
::
vector
<
migraphx
::
gpu
::
hiprtc_src_file
>
srcs
;
migraphx
::
from_value
(
v
.
at
(
"srcs"
),
srcs
);
auto
out
=
migraphx
::
gpu
::
compile_hip_src_with_hiprtc
(
std
::
move
(
srcs
),
v
.
at
(
"params"
).
to
<
std
::
string
>
(),
v
.
at
(
"arch"
).
to
<
std
::
string
>
());
if
(
not
out
.
empty
())
migraphx
::
write_buffer
(
output_name
,
out
.
front
());
}
src/targets/gpu/include/migraphx/gpu/compile_gen.hpp
View file @
2fc6b715
...
...
@@ -26,6 +26,7 @@
#include <migraphx/config.hpp>
#include <migraphx/module_ref.hpp>
#include <migraphx/instruction_ref.hpp>
#include <string>
#include <unordered_map>
#include <vector>
...
...
@@ -34,6 +35,7 @@ namespace migraphx {
inline
namespace
MIGRAPHX_INLINE_NS
{
struct
shape
;
struct
operation
;
namespace
gpu
{
...
...
@@ -72,8 +74,23 @@ std::string make_transformer_args(Ts... xs)
std
::
string
generate_pointwise
(
const
module
&
pm
,
const
std
::
string
&
name
);
std
::
string
generate_reduce
(
const
module
&
m
,
const
std
::
string
&
name
);
std
::
string
generate_name_from_ops
(
const
module
&
m
);
struct
reduce_op
{
std
::
string
input
=
""
;
std
::
string
reduction
=
""
;
std
::
string
init
=
"0"
;
std
::
string
read
=
"op::id{}"
;
std
::
string
write
=
"op::id{}"
;
void
set
(
instruction_ref
ins
,
const
operation
&
op
);
std
::
string
str
()
const
;
static
std
::
string
generate
(
instruction_ref
ins
,
const
std
::
string
&
x
);
};
}
// namespace gen
}
// namespace gpu
}
// namespace MIGRAPHX_INLINE_NS
...
...
Prev
1
2
3
4
5
6
7
8
9
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