Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
gaoqiong
MIGraphX
Commits
99ee76c0
Commit
99ee76c0
authored
Sep 24, 2018
by
Paul
Browse files
Merge branch 'master' into mem_color_separate_literal-master
parents
85c2c29d
f9f4f713
Changes
40
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
821 additions
and
156 deletions
+821
-156
src/include/migraph/verify.hpp
src/include/migraph/verify.hpp
+1
-1
src/include/migraph/verify_args.hpp
src/include/migraph/verify_args.hpp
+36
-2
src/instruction.cpp
src/instruction.cpp
+166
-0
src/onnx/onnx.cpp
src/onnx/onnx.cpp
+21
-15
src/onnx/verify_onnx.cpp
src/onnx/verify_onnx.cpp
+43
-11
src/program.cpp
src/program.cpp
+59
-47
src/simplify_reshapes.cpp
src/simplify_reshapes.cpp
+8
-8
src/targets/cpu/cpu_lowering.cpp
src/targets/cpu/cpu_lowering.cpp
+70
-12
src/targets/gpu/eliminate_workspace.cpp
src/targets/gpu/eliminate_workspace.cpp
+3
-3
src/targets/gpu/fuse_ops.cpp
src/targets/gpu/fuse_ops.cpp
+5
-5
src/targets/gpu/lowering.cpp
src/targets/gpu/lowering.cpp
+80
-33
src/targets/gpu/target.cpp
src/targets/gpu/target.cpp
+2
-2
src/targets/gpu/write_literals.cpp
src/targets/gpu/write_literals.cpp
+2
-2
test/cpu_ops_test.cpp
test/cpu_ops_test.cpp
+160
-0
test/eval_test.cpp
test/eval_test.cpp
+4
-4
test/gpu/miopen.cpp
test/gpu/miopen.cpp
+79
-7
test/include/rob.hpp
test/include/rob.hpp
+48
-0
test/operation.cpp
test/operation.cpp
+2
-0
test/validate.cpp
test/validate.cpp
+7
-1
tools/include/operation.hpp
tools/include/operation.hpp
+25
-3
No files found.
src/include/migraph/verify.hpp
View file @
99ee76c0
...
...
@@ -140,7 +140,7 @@ std::size_t mismatch_diff(R1&& r1, R2&& r2, T diff)
{
return
mismatch_idx
(
r1
,
r2
,
[
&
](
auto
x
,
auto
y
)
{
auto
d
=
abs_diff
(
x
,
y
);
return
!
(
d
>
diff
&&
d
<
diff
);
return
float_equal
(
d
,
diff
);
});
}
...
...
src/include/migraph/verify_args.hpp
View file @
99ee76c0
...
...
@@ -6,14 +6,16 @@
namespace
migraph
{
inline
void
verify_args
(
const
std
::
string
&
name
,
inline
bool
verify_args
(
const
std
::
string
&
name
,
const
argument
&
cpu_arg
,
const
argument
&
gpu_arg
,
double
tolerance
=
80
)
{
bool
passed
=
true
;
visit_all
(
cpu_arg
,
gpu_arg
)([
&
](
auto
cpu
,
auto
gpu
)
{
double
error
;
if
(
not
verify_range
(
cpu
,
gpu
,
tolerance
,
&
error
))
passed
=
verify_range
(
cpu
,
gpu
,
tolerance
,
&
error
);
if
(
not
passed
)
{
// TODO: Check for nans
std
::
cout
<<
"FAILED: "
<<
name
<<
std
::
endl
;
...
...
@@ -27,6 +29,9 @@ inline void verify_args(const std::string& name,
if
(
range_zero
(
gpu
))
std
::
cout
<<
"Gpu data is all zeros"
<<
std
::
endl
;
auto
mxdiff
=
max_diff
(
cpu
,
gpu
);
std
::
cout
<<
"Max diff: "
<<
mxdiff
<<
std
::
endl
;
auto
idx
=
mismatch_idx
(
cpu
,
gpu
,
float_equal
);
if
(
idx
<
range_distance
(
cpu
))
{
...
...
@@ -45,7 +50,36 @@ inline void verify_args(const std::string& name,
<<
gpu
[
gpu_nan_idx
]
<<
std
::
endl
;
std
::
cout
<<
std
::
endl
;
}
else
{
if
(
range_zero
(
cpu
))
std
::
cout
<<
"Cpu data is all zeros"
<<
std
::
endl
;
if
(
range_zero
(
gpu
))
std
::
cout
<<
"Gpu data is all zeros"
<<
std
::
endl
;
// auto mxdiff = max_diff(cpu, gpu);
// std::cout << "Max diff: " << mxdiff << std::endl;
// auto idx = mismatch_idx(cpu, gpu, float_equal);
// if(idx < range_distance(cpu))
// {
// std::cout << "Mismatch at " << idx << ": " << cpu[idx] << " != " << gpu[idx]
// << std::endl;
// }
auto
cpu_nan_idx
=
find_idx
(
cpu
,
not_finite
);
if
(
cpu_nan_idx
>=
0
)
std
::
cout
<<
"Non finite number found in cpu at "
<<
cpu_nan_idx
<<
": "
<<
cpu
[
cpu_nan_idx
]
<<
std
::
endl
;
auto
gpu_nan_idx
=
find_idx
(
gpu
,
not_finite
);
if
(
gpu_nan_idx
>=
0
)
std
::
cout
<<
"Non finite number found in gpu at "
<<
gpu_nan_idx
<<
": "
<<
gpu
[
gpu_nan_idx
]
<<
std
::
endl
;
// std::cout << std::endl;
}
});
return
passed
;
}
}
// namespace migraph
...
...
src/instruction.cpp
0 → 100644
View file @
99ee76c0
#include <migraph/instruction.hpp>
#include <migraph/builtin.hpp>
#include <migraph/erase.hpp>
namespace
migraph
{
instruction
::
instruction
(
operation
o
,
shape
r
,
std
::
vector
<
instruction_ref
>
args
)
:
op
(
std
::
move
(
o
)),
result
(
std
::
move
(
r
)),
arguments
(
std
::
move
(
args
))
{
}
instruction
::
instruction
(
literal
l
)
:
op
(
builtin
::
literal
{}),
result
(
l
.
get_shape
()),
lit
(
std
::
move
(
l
))
{
}
void
instruction
::
replace
(
const
shape
&
r
)
{
if
(
r
!=
result
)
{
result
=
r
;
for
(
auto
&&
ins
:
output
)
{
assert
(
ins
->
name
().
front
()
!=
'@'
);
ins
->
recompute_shape
();
}
}
}
void
instruction
::
recompute_shape
()
{
replace
(
compute_shape
(
op
,
arguments
));
}
void
instruction
::
clear_arguments
()
{
for
(
auto
&&
arg
:
arguments
)
{
arg
->
remove_output
(
*
this
);
}
arguments
.
clear
();
}
bool
operator
==
(
const
instruction
&
i
,
instruction_ref
ref
)
{
return
std
::
addressof
(
i
)
==
std
::
addressof
(
*
ref
);
}
bool
instruction
::
valid
(
instruction_ref
start
)
const
{
return
valid
()
&&
std
::
all_of
(
arguments
.
begin
(),
arguments
.
end
(),
[
&
](
instruction_ref
i
)
{
auto
self
=
std
::
find
(
i
->
outputs
().
begin
(),
i
->
outputs
().
end
(),
*
this
);
return
self
!=
i
->
outputs
().
end
()
&&
std
::
distance
(
start
,
i
)
<
std
::
distance
(
start
,
*
self
);
});
}
bool
instruction
::
valid
()
const
{
shape
computed
;
if
(
op
.
name
()
==
"@literal"
)
{
computed
=
lit
.
get_shape
();
}
else
if
(
op
.
name
()
==
"@param"
)
{
computed
=
result
;
}
else
{
try
{
computed
=
compute_shape
(
op
,
arguments
);
}
catch
(
migraph
::
exception
&
)
{
return
false
;
}
}
return
result
==
computed
&&
std
::
all_of
(
output
.
begin
(),
output
.
end
(),
[
&
](
instruction_ref
i
)
{
return
std
::
find
(
i
->
inputs
().
begin
(),
i
->
inputs
().
end
(),
*
this
)
!=
i
->
inputs
().
end
();
});
}
shape
instruction
::
get_shape
()
const
{
return
result
;
}
const
literal
&
instruction
::
get_literal
()
const
{
assert
(
op
.
name
()
==
"@literal"
);
return
lit
;
}
const
operation
&
instruction
::
get_operator
()
const
{
return
op
;
}
std
::
string
instruction
::
name
()
const
{
return
op
.
name
();
}
const
std
::
vector
<
instruction_ref
>&
instruction
::
inputs
()
const
{
return
arguments
;
}
const
std
::
vector
<
instruction_ref
>&
instruction
::
outputs
()
const
{
return
output
;
}
bool
operator
==
(
instruction_ref
ref
,
const
instruction
&
i
)
{
return
i
==
ref
;
}
bool
operator
!=
(
const
instruction
&
i
,
instruction_ref
ref
)
{
return
!
(
i
==
ref
);
}
bool
operator
!=
(
instruction_ref
ref
,
const
instruction
&
i
)
{
return
!
(
i
==
ref
);
}
void
instruction
::
add_output
(
instruction_ref
ins
)
{
if
(
std
::
find
(
output
.
begin
(),
output
.
end
(),
ins
)
==
output
.
end
())
output
.
push_back
(
ins
);
}
template
<
class
T
>
void
instruction
::
remove_output
(
const
T
&
ins
)
{
migraph
::
erase
(
output
,
ins
);
}
void
instruction
::
backreference
(
instruction_ref
ref
)
{
for
(
auto
&&
arg
:
ref
->
inputs
())
arg
->
add_output
(
ref
);
}
void
instruction
::
replace_argument
(
instruction_ref
ins
,
instruction_ref
old
,
instruction_ref
new_ins
)
{
ins
->
replace_argument
(
old
,
new_ins
);
backreference
(
ins
);
ins
->
recompute_shape
();
}
void
instruction
::
replace
(
instruction_ref
ins
,
operation
o
,
const
shape
&
r
,
std
::
vector
<
instruction_ref
>
args
)
{
ins
->
replace
(
std
::
move
(
o
),
r
,
std
::
move
(
args
));
backreference
(
ins
);
}
void
instruction
::
replace
(
operation
o
,
const
shape
&
r
,
std
::
vector
<
instruction_ref
>
args
)
{
op
=
std
::
move
(
o
);
replace
(
r
);
replace
(
std
::
move
(
args
));
}
void
instruction
::
replace
(
std
::
vector
<
instruction_ref
>
args
)
{
clear_arguments
();
arguments
=
std
::
move
(
args
);
}
void
instruction
::
replace_argument
(
instruction_ref
old
,
instruction_ref
new_ins
)
{
std
::
replace
(
arguments
.
begin
(),
arguments
.
end
(),
old
,
new_ins
);
old
->
remove_output
(
*
this
);
}
shape
compute_shape
(
const
operation
&
op
,
const
std
::
vector
<
instruction_ref
>&
args
)
{
std
::
vector
<
shape
>
shapes
(
args
.
size
());
std
::
transform
(
args
.
begin
(),
args
.
end
(),
shapes
.
begin
(),
[](
instruction_ref
i
)
{
return
i
->
get_shape
();
});
return
op
.
compute_shape
(
shapes
);
}
}
// namespace migraph
src/onnx/onnx.cpp
View file @
99ee76c0
...
...
@@ -28,10 +28,6 @@ struct unknown
else
return
input
.
front
();
}
argument
compute
(
context
&
,
const
shape
&
,
const
std
::
vector
<
argument
>&
)
const
{
MIGRAPH_THROW
(
"not computable"
);
}
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
unknown
&
x
)
{
os
<<
x
.
name
();
...
...
@@ -58,6 +54,7 @@ struct onnx_parser
add_generic_op
(
"Mul"
,
mul
{});
add_generic_op
(
"Relu"
,
activation
{
"relu"
});
add_generic_op
(
"Sub"
,
sub
{});
add_generic_op
(
"Sum"
,
add
{});
add_mem_op
(
"Constant"
,
&
onnx_parser
::
parse_constant
);
add_mem_op
(
"Conv"
,
&
onnx_parser
::
parse_conv
);
...
...
@@ -67,6 +64,7 @@ struct onnx_parser
add_mem_op
(
"Flatten"
,
&
onnx_parser
::
parse_flatten
);
add_mem_op
(
"Gemm"
,
&
onnx_parser
::
parse_gemm
);
add_mem_op
(
"BatchNormalization"
,
&
onnx_parser
::
parse_batchnorm
);
add_mem_op
(
"Softmax"
,
&
onnx_parser
::
parse_softmax
);
}
template
<
class
F
>
...
...
@@ -103,6 +101,15 @@ struct onnx_parser
});
}
instruction_ref
parse_softmax
(
const
std
::
string
&
,
const
attribute_map
&
,
std
::
vector
<
instruction_ref
>
args
)
{
auto
dims
=
args
.
front
()
->
get_shape
().
lens
();
auto
r
=
prog
.
add_instruction
(
reshape
{{
long
(
dims
[
0
]),
long
(
dims
[
1
]),
1
,
1
}},
args
.
front
());
auto
s
=
prog
.
add_instruction
(
softmax
{},
r
);
return
prog
.
add_instruction
(
reshape
{{
long
(
dims
[
0
]),
long
(
dims
[
1
])}},
s
);
}
instruction_ref
parse_conv
(
const
std
::
string
&
,
attribute_map
attributes
,
std
::
vector
<
instruction_ref
>
args
)
{
...
...
@@ -160,7 +167,7 @@ struct onnx_parser
}
if
(
args
.
size
()
==
2
)
{
literal
s
=
args
[
1
]
->
lit
;
literal
s
=
args
[
1
]
->
get_literal
()
;
s
.
visit
([
&
](
auto
v
)
{
copy
(
v
,
std
::
back_inserter
(
op
.
dims
));
});
}
return
prog
.
add_instruction
(
op
,
args
[
0
]);
...
...
@@ -344,11 +351,10 @@ struct onnx_parser
if
(
node
.
name
().
empty
())
{
std
::
string
generated
=
"migraph_unnamed_node"
;
for
(
auto
&&
output
:
node
.
output
())
{
generated
+=
"_"
+
output
;
}
return
generated
;
return
std
::
accumulate
(
node
.
output
().
begin
(),
node
.
output
().
end
(),
generated
,
[](
auto
x
,
auto
y
)
{
return
x
+
"_"
+
y
;
});
}
return
node
.
name
();
}
...
...
@@ -481,11 +487,11 @@ struct onnx_parser
break
;
// throw std::runtime_error("Unsupported type COMPLEX128");
}
std
::
vector
<
std
::
size_t
>
dims
;
// TODO: USe std::tra
ns
f
or
m
for
(
auto
&&
d
:
t
.
te
nsor
_type
().
shape
().
dim
()
)
{
dims
.
push_back
(
d
.
dim_value
());
}
auto
&&
tensor_dims
=
t
.
te
nsor
_type
().
shape
().
dim
();
std
::
tra
ns
f
or
m
(
tensor_dims
.
begin
()
,
tensor_dims
.
end
(),
std
::
back_inserter
(
dims
),
[](
auto
&&
d
)
{
return
d
.
dim_value
();
});
return
{
shape_type
,
dims
};
}
};
...
...
src/onnx/verify_onnx.cpp
View file @
99ee76c0
...
...
@@ -51,48 +51,76 @@ void verify_program(const std::string& name, F f, double tolerance = 100)
auto
x
=
run_cpu
(
f
);
auto
y
=
run_gpu
(
f
);
migraph
::
verify_args
(
name
,
x
,
y
,
tolerance
);
// std::cout << "cpu: " << x << std::endl;
// std::cout << "gpu: " << y << std::endl;
}
void
verify_instructions
(
const
migraph
::
program
&
prog
,
double
tolerance
=
80
)
{
for
(
auto
&&
ins
:
prog
)
{
if
(
ins
.
op
.
name
().
front
()
==
'@'
)
if
(
ins
.
name
().
front
()
==
'@'
)
continue
;
if
(
ins
.
op
.
name
()
==
"broadcast"
)
if
(
ins
.
name
()
==
"broadcast"
)
continue
;
if
(
ins
.
op
.
name
()
==
"transpose"
)
if
(
ins
.
name
()
==
"transpose"
)
continue
;
if
(
ins
.
op
.
name
()
==
"reshape"
)
if
(
ins
.
name
()
==
"reshape"
)
continue
;
auto
create_program
=
[
&
]
{
migraph
::
program
p
;
std
::
vector
<
migraph
::
instruction_ref
>
inputs
;
for
(
auto
&&
arg
:
ins
.
arguments
)
for
(
auto
&&
arg
:
ins
.
inputs
()
)
{
if
(
arg
->
op
.
name
()
==
"@literal"
)
inputs
.
push_back
(
p
.
add_literal
(
arg
->
lit
));
if
(
arg
->
name
()
==
"@literal"
)
inputs
.
push_back
(
p
.
add_literal
(
arg
->
get_literal
()
));
else
inputs
.
push_back
(
p
.
add_parameter
(
std
::
to_string
(
inputs
.
size
()),
arg
->
get_shape
()));
}
p
.
add_instruction
(
ins
.
op
,
inputs
);
p
.
add_instruction
(
ins
.
get_operator
()
,
inputs
);
return
p
;
};
try
{
std
::
cout
<<
"Verify: "
<<
ins
.
op
.
name
()
<<
std
::
endl
;
std
::
cout
<<
"Verify: "
<<
ins
.
name
()
<<
std
::
endl
;
std
::
cout
<<
create_program
()
<<
std
::
endl
;
verify_program
(
ins
.
op
.
name
(),
create_program
,
tolerance
);
verify_program
(
ins
.
name
(),
create_program
,
tolerance
);
}
catch
(...)
{
std
::
cout
<<
"Instruction "
<<
ins
.
op
.
name
()
<<
" threw an exception."
<<
std
::
endl
;
std
::
cout
<<
"Instruction "
<<
ins
.
name
()
<<
" threw an exception."
<<
std
::
endl
;
throw
;
}
}
}
template
<
class
F
>
void
verify_reduced
(
F
f
,
int
n
,
double
tolerance
=
80
)
{
auto
create_program
=
[
&
]
{
migraph
::
program
p
=
f
();
auto
last
=
std
::
prev
(
p
.
end
(),
n
+
1
);
p
.
remove_instructions
(
last
,
p
.
end
());
return
p
;
};
std
::
cout
<<
"Verify: "
<<
std
::
endl
;
std
::
cout
<<
create_program
()
<<
std
::
endl
;
verify_program
(
std
::
to_string
(
n
),
create_program
,
tolerance
);
}
template
<
class
F
>
void
verify_reduced_program
(
F
f
,
double
tolerance
=
80
)
{
migraph
::
program
p
=
f
();
auto
n
=
std
::
distance
(
p
.
begin
(),
p
.
end
());
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
verify_reduced
(
f
,
i
,
tolerance
);
}
}
int
main
(
int
argc
,
char
const
*
argv
[])
{
std
::
vector
<
std
::
string
>
args
(
argv
+
1
,
argv
+
argc
);
...
...
@@ -106,6 +134,10 @@ int main(int argc, char const* argv[])
{
verify_instructions
(
p
);
}
else
if
(
std
::
any_of
(
args
.
begin
(),
args
.
end
(),
[](
const
auto
&
s
)
{
return
s
==
"-r"
;
}))
{
verify_reduced_program
([
&
]
{
return
migraph
::
parse_onnx
(
file
);
});
}
else
{
verify_program
(
file
,
[
&
]
{
return
migraph
::
parse_onnx
(
file
);
});
...
...
src/program.cpp
View file @
99ee76c0
...
...
@@ -12,6 +12,7 @@
namespace
migraph
{
MIGRAPH_DECLARE_ENV_VAR
(
MIGRAPH_TRACE_COMPILE
)
MIGRAPH_DECLARE_ENV_VAR
(
MIGRAPH_TRACE_EVAL
)
struct
program_impl
{
...
...
@@ -20,7 +21,7 @@ struct program_impl
context
ctx
;
};
const
operation
&
get_operation
(
instruction_ref
ins
)
{
return
ins
->
op
;
}
const
operation
&
get_operation
(
instruction_ref
ins
)
{
return
ins
->
get_operator
()
;
}
template
<
class
F
>
static
void
print_program
(
std
::
ostream
&
os
,
const
program
&
p
,
F
annonate
)
...
...
@@ -31,27 +32,27 @@ static void print_program(std::ostream& os, const program& p, F annonate)
for
(
auto
ins
:
iterator_for
(
p
))
{
std
::
string
var_name
=
"@"
+
std
::
to_string
(
count
);
if
(
ins
->
op
.
name
()
==
"@param"
)
if
(
ins
->
name
()
==
"@param"
)
{
var_name
=
any_cast
<
builtin
::
param
>
(
ins
->
op
).
parameter
;
var_name
=
any_cast
<
builtin
::
param
>
(
ins
->
get_operator
()
).
parameter
;
}
os
<<
var_name
<<
" = "
;
os
<<
ins
->
op
;
os
<<
ins
->
get_operator
()
;
if
(
ins
->
op
.
name
()
==
"@literal"
)
if
(
ins
->
name
()
==
"@literal"
)
{
if
(
ins
->
lit
.
get_shape
().
elements
()
>
10
)
if
(
ins
->
get_literal
()
.
get_shape
().
elements
()
>
10
)
os
<<
"{ ... }"
;
else
os
<<
"{"
<<
ins
->
lit
<<
"}"
;
os
<<
"{"
<<
ins
->
get_literal
()
<<
"}"
;
}
if
(
!
ins
->
arguments
.
empty
())
if
(
!
ins
->
inputs
()
.
empty
())
{
char
delim
=
'('
;
for
(
auto
&&
arg
:
ins
->
arguments
)
for
(
auto
&&
arg
:
ins
->
inputs
()
)
{
assert
(
p
.
has_instruction
(
arg
)
&&
"Instruction not found"
);
os
<<
delim
<<
names
.
at
(
arg
);
...
...
@@ -60,7 +61,7 @@ static void print_program(std::ostream& os, const program& p, F annonate)
os
<<
")"
;
}
os
<<
" -> "
<<
ins
->
result
;
os
<<
" -> "
<<
ins
->
get_shape
()
;
annonate
(
ins
,
names
);
...
...
@@ -92,8 +93,8 @@ instruction_ref program::insert_instruction(instruction_ref ins,
// TODO: Use move
shape
r
=
compute_shape
(
op
,
args
);
auto
result
=
impl
->
instructions
.
insert
(
ins
,
{
op
,
r
,
std
::
move
(
args
)});
backreference
(
result
);
// assert(result->
arguments
== args);
instruction
::
backreference
(
result
);
// assert(result->
inputs()
== args);
assert
(
result
->
valid
(
begin
()));
return
result
;
}
...
...
@@ -108,8 +109,7 @@ instruction_ref program::replace_instruction(instruction_ref ins,
assert
(
not
starts_with
(
op
.
name
(),
"@"
));
shape
r
=
compute_shape
(
op
,
args
);
ins
->
replace
(
op
,
r
,
std
::
move
(
args
));
backreference
(
ins
);
instruction
::
replace
(
ins
,
op
,
r
,
std
::
move
(
args
));
assert
(
ins
->
valid
(
begin
()));
return
ins
;
}
...
...
@@ -120,21 +120,21 @@ instruction_ref program::replace_instruction(instruction_ref ins, instruction_re
assert
(
has_instruction
(
rep
));
assert
(
ins
!=
rep
);
// TODO: Should it be an error if the output is empty?
if
(
ins
->
output
.
empty
())
if
(
ins
->
output
s
()
.
empty
())
{
return
rep
;
}
for
(
auto
&&
out
:
ins
->
output
)
for
(
auto
&&
out
:
ins
->
output
s
()
)
{
// TODO: Check for possible cycles
if
(
out
!=
rep
)
{
replace_argument
(
out
,
ins
,
rep
);
instruction
::
replace_argument
(
out
,
ins
,
rep
);
}
assert
(
out
->
valid
(
begin
()));
}
// Replacement should not be dead code unless its the last instruction
assert
(
!
rep
->
output
.
empty
()
or
rep
==
std
::
prev
(
end
()));
assert
(
!
rep
->
output
s
()
.
empty
()
or
rep
==
std
::
prev
(
end
()));
assert
(
ins
->
valid
(
begin
()));
assert
(
rep
->
valid
(
begin
()));
return
rep
;
...
...
@@ -143,7 +143,7 @@ instruction_ref program::replace_instruction(instruction_ref ins, instruction_re
instruction_ref
program
::
remove_instruction
(
instruction_ref
ins
)
{
assert
(
has_instruction
(
ins
));
assert
(
ins
->
output
.
empty
());
assert
(
ins
->
output
s
()
.
empty
());
ins
->
clear_arguments
();
return
impl
->
instructions
.
erase
(
ins
);
}
...
...
@@ -155,7 +155,7 @@ instruction_ref program::remove_instructions(instruction_ref first, instruction_
// TODO: Check every element
assert
(
has_instruction
(
first
));
std
::
for_each
(
first
,
last
,
[
&
](
instruction
&
ins
)
{
ins
.
clear_arguments
();
});
assert
(
std
::
all_of
(
first
,
last
,
[
&
](
instruction
&
ins
)
{
return
ins
.
output
.
empty
();
}));
assert
(
std
::
all_of
(
first
,
last
,
[
&
](
instruction
&
ins
)
{
return
ins
.
output
s
()
.
empty
();
}));
return
impl
->
instructions
.
erase
(
first
,
last
);
}
...
...
@@ -188,9 +188,9 @@ shape program::get_parameter_shape(std::string name) const
{
auto
ins
=
std
::
find_if
(
impl
->
instructions
.
begin
(),
impl
->
instructions
.
end
(),
[
&
](
const
instruction
&
x
)
{
if
(
x
.
op
.
name
()
==
"@param"
)
if
(
x
.
name
()
==
"@param"
)
{
return
any_cast
<
builtin
::
param
>
(
x
.
op
).
parameter
==
name
;
return
any_cast
<
builtin
::
param
>
(
x
.
get_operator
()
).
parameter
==
name
;
}
else
{
...
...
@@ -198,7 +198,7 @@ shape program::get_parameter_shape(std::string name) const
}
});
if
(
ins
!=
this
->
end
())
return
ins
->
result
;
return
ins
->
get_shape
()
;
else
return
{};
}
...
...
@@ -227,10 +227,10 @@ std::unordered_map<std::string, shape> program::get_parameter_shapes() const
std
::
unordered_map
<
std
::
string
,
shape
>
result
;
for
(
auto
&&
ins
:
impl
->
instructions
)
{
if
(
ins
.
op
.
name
()
==
"@param"
)
if
(
ins
.
name
()
==
"@param"
)
{
auto
&&
name
=
any_cast
<
builtin
::
param
>
(
ins
.
op
).
parameter
;
result
[
name
]
=
ins
.
result
;
auto
&&
name
=
any_cast
<
builtin
::
param
>
(
ins
.
get_operator
()
).
parameter
;
result
[
name
]
=
ins
.
get_shape
()
;
}
}
return
result
;
...
...
@@ -248,7 +248,7 @@ std::size_t program::size() const { return impl->instructions.size(); }
instruction_ref
program
::
begin
()
const
{
return
impl
->
instructions
.
begin
();
}
instruction_ref
program
::
end
()
const
{
return
impl
->
instructions
.
end
();
}
shape
program
::
get_shape
()
const
{
return
impl
->
instructions
.
back
().
result
;
}
shape
program
::
get_shape
()
const
{
return
impl
->
instructions
.
back
().
get_shape
()
;
}
instruction_ref
program
::
validate
()
const
{
...
...
@@ -277,7 +277,7 @@ void program::compile(const target& t, tracer trace)
{
auto
index
=
std
::
distance
(
impl
->
instructions
.
begin
(),
invalid
);
MIGRAPH_THROW
(
p
.
name
()
+
" pass produces invalid program at instruction "
+
std
::
to_string
(
index
)
+
": "
+
invalid
->
op
.
name
());
std
::
to_string
(
index
)
+
": "
+
invalid
->
name
());
}
trace
();
#endif
...
...
@@ -303,32 +303,32 @@ argument generic_eval(const program& p,
values
.
reserve
(
16
);
for
(
auto
ins
:
iterator_for
(
p
))
{
if
(
ins
->
op
.
name
()
==
"@literal"
)
if
(
ins
->
name
()
==
"@literal"
)
{
results
.
emplace
(
ins
,
trace
(
ins
,
[
&
]
{
return
ins
->
lit
.
get_argument
();
}));
results
.
emplace
(
ins
,
trace
(
ins
,
[
&
]
{
return
ins
->
get_literal
()
.
get_argument
();
}));
}
else
if
(
ins
->
op
.
name
()
==
"@param"
)
else
if
(
ins
->
name
()
==
"@param"
)
{
results
.
emplace
(
ins
,
trace
(
ins
,
[
&
]
{
return
params
.
at
(
any_cast
<
builtin
::
param
>
(
ins
->
op
).
parameter
);
return
params
.
at
(
any_cast
<
builtin
::
param
>
(
ins
->
get_operator
()).
parameter
);
}));
}
else
if
(
ins
->
op
.
name
()
==
"@outline"
)
else
if
(
ins
->
name
()
==
"@outline"
)
{
results
.
emplace
(
ins
,
trace
(
ins
,
[
&
]
{
return
argument
{
ins
->
result
,
nullptr
};
}));
results
.
emplace
(
ins
,
trace
(
ins
,
[
&
]
{
return
argument
{
ins
->
get_shape
()
,
nullptr
};
}));
}
else
{
values
.
resize
(
ins
->
arguments
.
size
());
std
::
transform
(
ins
->
arguments
.
begin
(),
ins
->
arguments
.
end
(),
values
.
begin
(),
[
&
](
instruction_ref
i
)
{
assert
(
results
.
find
(
i
)
!=
results
.
end
());
return
results
[
i
];
});
results
.
emplace
(
ins
,
trace
(
ins
,
[
&
]
{
return
ins
->
op
.
compute
(
ctx
,
ins
->
result
,
values
);
}));
values
.
resize
(
ins
->
inputs
().
size
());
std
::
transform
(
ins
->
inputs
().
begin
(),
ins
->
inputs
().
end
(),
values
.
begin
(),
[
&
](
instruction_ref
i
)
{
assert
(
results
.
find
(
i
)
!=
results
.
end
());
return
results
[
i
];
});
results
.
emplace
(
ins
,
trace
(
ins
,
[
&
]
{
return
ins
->
get_operator
().
compute
(
ctx
,
ins
->
get_shape
(),
values
);
}));
}
assert
(
results
.
find
(
ins
)
!=
results
.
end
());
}
...
...
@@ -337,8 +337,20 @@ argument generic_eval(const program& p,
argument
program
::
eval
(
std
::
unordered_map
<
std
::
string
,
argument
>
params
)
const
{
return
generic_eval
(
*
this
,
this
->
impl
->
ctx
,
std
::
move
(
params
),
[](
auto
&
,
auto
f
)
{
return
f
();
});
if
(
enabled
(
MIGRAPH_TRACE_EVAL
{}))
{
auto
&
ctx
=
this
->
impl
->
ctx
;
return
generic_eval
(
*
this
,
this
->
impl
->
ctx
,
std
::
move
(
params
),
[
&
](
auto
&
ins
,
auto
f
)
{
ctx
.
finish
();
std
::
cout
<<
"Run instruction: "
<<
ins
->
name
()
<<
std
::
endl
;
return
f
();
});
}
else
{
return
generic_eval
(
*
this
,
this
->
impl
->
ctx
,
std
::
move
(
params
),
[](
auto
&
,
auto
f
)
{
return
f
();
});
}
}
double
common_average
(
const
std
::
vector
<
double
>&
v
)
...
...
@@ -404,7 +416,7 @@ void program::perf_report(std::ostream& os, std::size_t n, parameter_map params)
for
(
auto
&&
p
:
ins_vec
)
{
double
avg
=
common_average
(
p
.
second
);
op_times
[
p
.
first
->
op
.
name
()]
+=
avg
;
op_times
[
p
.
first
->
name
()]
+=
avg
;
total_instruction_time
+=
avg
;
}
double
calculate_overhead_time
=
total_time
-
total_instruction_time
;
...
...
src/simplify_reshapes.cpp
View file @
99ee76c0
...
...
@@ -25,26 +25,26 @@ void simplify_reshapes::apply(program& p) const
{
for
(
auto
ins
:
iterator_for
(
p
))
{
if
(
not
is_reshaper
(
ins
->
op
.
name
()))
if
(
not
is_reshaper
(
ins
->
name
()))
continue
;
if
(
ins
->
output
.
size
()
!=
1
)
if
(
ins
->
output
s
()
.
size
()
!=
1
)
continue
;
if
(
is_reshaper
(
ins
->
output
.
front
()
->
op
.
name
()))
if
(
is_reshaper
(
ins
->
output
s
()
.
front
()
->
name
()))
continue
;
// Gather reshapes
std
::
vector
<
instruction_ref
>
reshapes
{
ins
};
while
(
is_reshaper
(
reshapes
.
back
()
->
op
.
name
()))
while
(
is_reshaper
(
reshapes
.
back
()
->
name
()))
{
assert
(
!
reshapes
.
back
()
->
arguments
.
empty
());
assert
(
p
.
has_instruction
(
reshapes
.
back
()
->
arguments
.
front
()));
reshapes
.
push_back
(
reshapes
.
back
()
->
arguments
.
front
());
assert
(
!
reshapes
.
back
()
->
inputs
()
.
empty
());
assert
(
p
.
has_instruction
(
reshapes
.
back
()
->
inputs
()
.
front
()));
reshapes
.
push_back
(
reshapes
.
back
()
->
inputs
()
.
front
());
}
std
::
pair
<
instruction_ref
,
instruction_ref
>
r
{
p
.
end
(),
p
.
end
()};
for
(
auto
start
:
iterator_for
(
reshapes
))
{
auto
last
=
std
::
find_if
(
reshapes
.
rbegin
(),
reshapes
.
rend
(),
[
&
](
auto
&&
i
)
{
return
i
->
result
==
(
*
start
)
->
result
and
i
!=
(
*
start
);
return
i
->
get_shape
()
==
(
*
start
)
->
get_shape
()
and
i
!=
(
*
start
);
});
if
(
last
!=
reshapes
.
rend
())
{
...
...
src/targets/cpu/cpu_lowering.cpp
View file @
99ee76c0
...
...
@@ -134,6 +134,63 @@ struct cpu_convolution
}
};
struct
cpu_im2col
{
im2col
op
;
static
std
::
string
name
()
{
return
"cpu::im2col"
;
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
argument
compute
(
context
&
,
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
argument
result
{
output_shape
};
auto
input_shape
=
args
[
0
].
get_shape
();
auto
weights_shape
=
args
[
1
].
get_shape
();
visit_all
(
result
,
args
[
0
])([
&
](
auto
col
,
auto
input
)
{
const
std
::
size_t
&
height
=
input_shape
.
lens
()[
2
];
const
std
::
size_t
&
width
=
input_shape
.
lens
()[
3
];
const
std
::
size_t
&
channels
=
weights_shape
.
lens
()[
1
];
const
std
::
size_t
&
kernel_h
=
weights_shape
.
lens
()[
2
];
const
std
::
size_t
&
kernel_w
=
weights_shape
.
lens
()[
3
];
const
std
::
size_t
&
pad_h
=
op
.
padding
[
0
];
const
std
::
size_t
&
pad_w
=
op
.
padding
[
1
];
const
std
::
size_t
&
stride_h
=
op
.
stride
[
0
];
const
std
::
size_t
&
stride_w
=
op
.
stride
[
1
];
int
kdiv2_h
,
kdiv2_w
;
kdiv2_h
=
kernel_h
/
2
;
kdiv2_w
=
kernel_w
/
2
;
// calculate output sizes
const
std
::
size_t
col_height
=
(
height
-
kernel_h
+
2
*
pad_h
)
/
stride_h
+
1
;
const
std
::
size_t
col_width
=
(
width
-
kernel_w
+
2
*
pad_w
)
/
stride_w
+
1
;
// account for padding for the starting position of the input pixels
std
::
size_t
iinput
=
kdiv2_h
-
pad_h
;
// loop over output pixels (ioutput, joutput)
for
(
std
::
size_t
ioutput
=
0
;
ioutput
<
col_height
;
ioutput
++
,
iinput
+=
stride_h
)
{
std
::
size_t
jinput
=
kdiv2_w
-
pad_w
;
for
(
std
::
size_t
joutput
=
0
;
joutput
<
col_width
;
joutput
++
,
jinput
+=
stride_w
)
{
// compute linear index for output
std
::
size_t
ldx
=
ioutput
*
col_width
+
joutput
;
std
::
size_t
p
=
0
;
dfor
(
channels
,
kernel_h
,
kernel_w
)([
&
](
std
::
size_t
c
,
std
::
size_t
koffset
,
std
::
size_t
loffset
)
{
int
idx
=
iinput
+
koffset
-
kdiv2_h
;
int
jdx
=
jinput
+
loffset
-
kdiv2_w
;
col
(
ldx
,
p
)
=
((
idx
>=
0
)
&&
(
idx
<
height
)
&&
(
jdx
>=
0
)
&&
(
jdx
<
width
))
?
input
(
0
,
c
,
idx
,
jdx
)
:
0
;
p
++
;
});
}
}
});
return
result
;
}
};
struct
max_pool
{
static
std
::
string
name
()
{
return
"max"
;
}
...
...
@@ -494,6 +551,7 @@ struct cpu_apply
void
init
()
{
apply_map
[
"im2col"
]
=
extend_op
<
cpu_im2col
,
im2col
>
();
apply_map
[
"convolution"
]
=
extend_op
<
cpu_convolution
,
convolution
>
();
apply_map
[
"gemm"
]
=
extend_op
<
cpu_gemm
,
gemm
>
();
apply_map
[
"batch_norm_inference"
]
=
...
...
@@ -521,17 +579,17 @@ struct cpu_apply
init
();
for
(
auto
it
:
iterator_for
(
*
prog
))
{
if
(
it
->
op
.
name
()
==
"activation"
)
if
(
it
->
name
()
==
"activation"
)
{
apply_activation
(
it
);
}
else
if
(
it
->
op
.
name
()
==
"pooling"
)
else
if
(
it
->
name
()
==
"pooling"
)
{
apply_pooling
(
it
);
}
else
if
(
apply_map
.
count
(
it
->
op
.
name
())
>
0
)
else
if
(
apply_map
.
count
(
it
->
name
())
>
0
)
{
apply_map
.
at
(
it
->
op
.
name
())(
it
);
apply_map
.
at
(
it
->
name
())(
it
);
}
}
}
...
...
@@ -539,30 +597,30 @@ struct cpu_apply
template
<
class
T
>
void
apply_simple_op
(
instruction_ref
ins
)
{
prog
->
replace_instruction
(
ins
,
T
{},
ins
->
arguments
);
prog
->
replace_instruction
(
ins
,
T
{},
ins
->
inputs
()
);
}
template
<
class
T
,
class
Op
>
void
apply_extend_op
(
instruction_ref
ins
)
{
auto
&&
op
=
any_cast
<
Op
>
(
ins
->
op
);
prog
->
replace_instruction
(
ins
,
T
{
op
},
ins
->
arguments
);
auto
&&
op
=
any_cast
<
Op
>
(
ins
->
get_operator
()
);
prog
->
replace_instruction
(
ins
,
T
{
op
},
ins
->
inputs
()
);
}
void
apply_activation
(
instruction_ref
ins
)
{
auto
&&
op
=
any_cast
<
activation
>
(
ins
->
op
);
auto
&&
op
=
any_cast
<
activation
>
(
ins
->
get_operator
()
);
if
(
op
.
mode
==
"relu"
)
prog
->
replace_instruction
(
ins
,
cpu_unary
<
relu_op
>
{},
ins
->
arguments
);
prog
->
replace_instruction
(
ins
,
cpu_unary
<
relu_op
>
{},
ins
->
inputs
()
);
}
void
apply_pooling
(
instruction_ref
ins
)
{
auto
&&
op
=
any_cast
<
pooling
>
(
ins
->
op
);
auto
&&
op
=
any_cast
<
pooling
>
(
ins
->
get_operator
()
);
if
(
op
.
mode
==
"max"
)
prog
->
replace_instruction
(
ins
,
cpu_pooling
<
max_pool
>
{
op
},
ins
->
arguments
);
prog
->
replace_instruction
(
ins
,
cpu_pooling
<
max_pool
>
{
op
},
ins
->
inputs
()
);
else
if
(
op
.
mode
==
"average"
)
prog
->
replace_instruction
(
ins
,
cpu_pooling
<
avg_pool
>
{
op
},
ins
->
arguments
);
prog
->
replace_instruction
(
ins
,
cpu_pooling
<
avg_pool
>
{
op
},
ins
->
inputs
()
);
}
};
...
...
src/targets/gpu/eliminate_workspace.cpp
View file @
99ee76c0
...
...
@@ -20,11 +20,11 @@ void eliminate_workspace::apply(program& p) const
std
::
vector
<
instruction_ref
>
allocs
;
for
(
auto
ins
:
iterator_for
(
p
))
{
if
(
ins
->
output
.
size
()
!=
1
)
if
(
ins
->
output
s
()
.
size
()
!=
1
)
continue
;
if
(
ins
->
op
.
name
()
!=
"hip::allocate"
)
if
(
ins
->
name
()
!=
"hip::allocate"
)
continue
;
auto
&&
a
=
any_cast
<
hip_allocate
>
(
ins
->
op
);
auto
&&
a
=
any_cast
<
hip_allocate
>
(
ins
->
get_operator
()
);
if
(
a
.
tag
==
"workspace"
)
{
n
=
std
::
max
(
n
,
ins
->
get_shape
().
bytes
());
...
...
src/targets/gpu/fuse_ops.cpp
View file @
99ee76c0
...
...
@@ -26,14 +26,14 @@ void fuse_ops::apply(program& p) const
{
for
(
auto
ins
:
iterator_for
(
p
))
{
if
(
ins
->
op
.
name
()
!=
"gpu::relu"
)
if
(
ins
->
name
()
!=
"gpu::relu"
)
continue
;
auto
add_ins
=
ins
->
arguments
.
front
();
if
(
add_ins
->
op
.
name
()
!=
"gpu::add"
)
auto
add_ins
=
ins
->
inputs
()
.
front
();
if
(
add_ins
->
name
()
!=
"gpu::add"
)
continue
;
auto
args
=
add_ins
->
arguments
;
auto
args
=
add_ins
->
inputs
()
;
// Use the allocation from the relu operator
args
.
back
()
=
ins
->
arguments
.
back
();
args
.
back
()
=
ins
->
inputs
()
.
back
();
p
.
replace_instruction
(
ins
,
hip_add_relu
{},
args
);
}
}
...
...
src/targets/gpu/lowering.cpp
View file @
99ee76c0
...
...
@@ -132,8 +132,16 @@ struct miopen_convolution
workspace_size
,
false
);
algo
=
perf
.
fwd_algo
;
return
algo
==
miopenConvolutionFwdAlgoWinograd
?
shape
{
shape
::
int8_type
,
{
0
}}
:
workspace_shape
;
return
shape
{
shape
::
int8_type
,
{
perf
.
memory
}};
}
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
miopen_convolution
&
self
)
{
os
<<
self
.
name
()
<<
"["
;
os
<<
self
.
op
<<
", "
;
os
<<
"algo="
<<
self
.
algo
;
os
<<
"]"
;
return
os
;
}
};
...
...
@@ -308,6 +316,34 @@ struct miopen_relu
}
};
struct
miopen_softmax
{
softmax
op
;
std
::
string
name
()
const
{
return
"gpu::softmax"
;
}
shape
compute_shape
(
const
std
::
vector
<
shape
>&
inputs
)
const
{
check_shapes
{
inputs
,
*
this
}.
has
(
2
).
standard
();
return
op
.
compute_shape
({
inputs
.
at
(
0
)});
}
argument
compute
(
context
&
ctx
,
const
shape
&
output_shape
,
const
std
::
vector
<
argument
>&
args
)
const
{
float
alpha
=
1
,
beta
=
0
;
auto
x_desc
=
make_tensor
(
args
[
0
].
get_shape
());
auto
y_desc
=
make_tensor
(
output_shape
);
miopenSoftmaxForward
(
ctx
.
handle
.
get
(),
&
alpha
,
x_desc
.
get
(),
args
[
0
].
implicit
(),
&
beta
,
y_desc
.
get
(),
args
[
1
].
implicit
());
return
args
[
1
];
}
};
struct
miopen_apply
{
program
*
prog
=
nullptr
;
...
...
@@ -325,34 +361,38 @@ struct miopen_apply
for
(
auto
it
=
prog
->
begin
();
it
!=
prog
->
end
();
it
++
)
{
auto
s
=
it
->
get_shape
();
if
(
it
->
op
.
name
()
==
"convolution"
)
if
(
it
->
name
()
==
"convolution"
)
{
check_shape
(
s
,
apply_convolution
(
it
));
}
else
if
(
it
->
op
.
name
()
==
"activation"
)
else
if
(
it
->
name
()
==
"activation"
)
{
check_shape
(
s
,
apply_activation
(
it
));
}
else
if
(
it
->
op
.
name
()
==
"pooling"
)
else
if
(
it
->
name
()
==
"pooling"
)
{
check_shape
(
s
,
apply_pooling
(
it
));
}
else
if
(
it
->
op
.
name
()
==
"add"
)
else
if
(
it
->
name
()
==
"add"
)
{
check_shape
(
s
,
apply_add
(
it
));
}
else
if
(
it
->
op
.
name
()
==
"gemm"
)
else
if
(
it
->
name
()
==
"gemm"
)
{
check_shape
(
s
,
apply_gemm
(
it
));
}
else
if
(
it
->
op
.
name
()
==
"contiguous"
)
else
if
(
it
->
name
()
==
"contiguous"
)
{
check_shape
(
s
,
apply_contiguous
(
it
));
}
else
if
(
it
->
op
.
name
()
==
"batch_norm_inference"
)
else
if
(
it
->
name
()
==
"batch_norm_inference"
)
{
check_shape
(
s
,
apply_batch_norm_inference
(
it
));
}
else
if
(
it
->
name
()
==
"softmax"
)
{
check_shape
(
s
,
apply_softmax
(
it
));
}
}
}
...
...
@@ -372,78 +412,85 @@ struct miopen_apply
instruction_ref
apply_convolution
(
instruction_ref
ins
)
{
auto
&&
op
=
any_cast
<
convolution
>
(
ins
->
op
);
auto
&&
op
=
any_cast
<
convolution
>
(
ins
->
get_operator
()
);
auto
conv
=
miopen_convolution
{
op
,
make_conv
(
op
)};
auto
ws
=
conv
.
compile
(
ctx
,
ins
->
result
,
ins
->
arguments
);
auto
ws
=
conv
.
compile
(
ctx
,
ins
->
get_shape
(),
ins
->
inputs
()
);
auto
workspace
=
insert_allocation
(
ins
,
ws
,
"workspace"
);
auto
output
=
insert_allocation
(
ins
,
ins
->
result
);
auto
output
=
insert_allocation
(
ins
,
ins
->
get_shape
()
);
return
prog
->
replace_instruction
(
ins
,
conv
,
ins
->
arguments
.
at
(
0
),
ins
->
arguments
.
at
(
1
),
workspace
,
output
);
ins
,
conv
,
ins
->
inputs
()
.
at
(
0
),
ins
->
inputs
()
.
at
(
1
),
workspace
,
output
);
}
instruction_ref
apply_pooling
(
instruction_ref
ins
)
{
auto
&&
op
=
any_cast
<
pooling
>
(
ins
->
op
);
auto
&&
op
=
any_cast
<
pooling
>
(
ins
->
get_operator
()
);
auto
pd
=
make_pooling
(
op
);
auto
output
=
insert_allocation
(
ins
,
ins
->
result
);
auto
output
=
insert_allocation
(
ins
,
ins
->
get_shape
()
);
return
prog
->
replace_instruction
(
ins
,
miopen_pooling
{
op
,
std
::
move
(
pd
)},
ins
->
arguments
.
at
(
0
),
output
);
ins
,
miopen_pooling
{
op
,
std
::
move
(
pd
)},
ins
->
inputs
()
.
at
(
0
),
output
);
}
instruction_ref
apply_activation
(
instruction_ref
ins
)
{
auto
&&
op
=
any_cast
<
activation
>
(
ins
->
op
);
auto
&&
op
=
any_cast
<
activation
>
(
ins
->
get_operator
()
);
auto
ad
=
make_relu
();
if
(
op
.
mode
==
"relu"
)
{
auto
output
=
insert_allocation
(
ins
,
ins
->
result
);
auto
output
=
insert_allocation
(
ins
,
ins
->
get_shape
()
);
return
prog
->
replace_instruction
(
ins
,
miopen_relu
{
std
::
move
(
ad
)},
ins
->
arguments
.
at
(
0
),
output
);
ins
,
miopen_relu
{
std
::
move
(
ad
)},
ins
->
inputs
()
.
at
(
0
),
output
);
}
return
ins
;
}
instruction_ref
apply_softmax
(
instruction_ref
ins
)
{
auto
&&
op
=
any_cast
<
softmax
>
(
ins
->
get_operator
());
auto
output
=
insert_allocation
(
ins
,
ins
->
get_shape
());
return
prog
->
replace_instruction
(
ins
,
miopen_softmax
{
op
},
ins
->
inputs
().
at
(
0
),
output
);
}
instruction_ref
apply_add
(
instruction_ref
ins
)
{
auto
output
=
insert_allocation
(
ins
,
ins
->
result
);
auto
output
=
insert_allocation
(
ins
,
ins
->
get_shape
()
);
return
prog
->
replace_instruction
(
ins
,
hip_add
{},
ins
->
arguments
.
at
(
0
),
ins
->
arguments
.
at
(
1
),
output
);
ins
,
hip_add
{},
ins
->
inputs
()
.
at
(
0
),
ins
->
inputs
()
.
at
(
1
),
output
);
}
instruction_ref
apply_gemm
(
instruction_ref
ins
)
{
auto
&&
op
=
any_cast
<
gemm
>
(
ins
->
op
);
auto
output
=
insert_allocation
(
ins
,
ins
->
result
);
auto
&&
op
=
any_cast
<
gemm
>
(
ins
->
get_operator
()
);
auto
output
=
insert_allocation
(
ins
,
ins
->
get_shape
()
);
return
prog
->
replace_instruction
(
ins
,
miopen_gemm
{
op
},
ins
->
arguments
.
at
(
0
),
ins
->
arguments
.
at
(
1
),
output
);
ins
,
miopen_gemm
{
op
},
ins
->
inputs
()
.
at
(
0
),
ins
->
inputs
()
.
at
(
1
),
output
);
}
instruction_ref
apply_contiguous
(
instruction_ref
ins
)
{
auto
&&
op
=
any_cast
<
contiguous
>
(
ins
->
op
);
auto
output
=
insert_allocation
(
ins
,
ins
->
result
);
return
prog
->
replace_instruction
(
ins
,
miopen_contiguous
{
op
},
ins
->
arguments
.
at
(
0
),
output
);
auto
&&
op
=
any_cast
<
contiguous
>
(
ins
->
get_operator
()
);
auto
output
=
insert_allocation
(
ins
,
ins
->
get_shape
()
);
return
prog
->
replace_instruction
(
ins
,
miopen_contiguous
{
op
},
ins
->
inputs
()
.
at
(
0
),
output
);
}
instruction_ref
apply_batch_norm_inference
(
instruction_ref
ins
)
{
auto
&&
op
=
any_cast
<
batch_norm_inference
>
(
ins
->
op
);
auto
output
=
insert_allocation
(
ins
,
ins
->
result
);
shape
old_shape
=
ins
->
arguments
.
at
(
1
)
->
get_shape
();
auto
&&
op
=
any_cast
<
batch_norm_inference
>
(
ins
->
get_operator
()
);
auto
output
=
insert_allocation
(
ins
,
ins
->
get_shape
()
);
shape
old_shape
=
ins
->
inputs
()
.
at
(
1
)
->
get_shape
();
std
::
vector
<
int64_t
>
new_shape
{
1
,
static_cast
<
int64_t
>
(
old_shape
.
elements
()),
1
,
1
};
auto
reshape_op
=
reshape
{
new_shape
};
std
::
vector
<
instruction_ref
>
reshapes
;
std
::
transform
(
ins
->
arguments
.
begin
()
+
1
,
ins
->
arguments
.
end
(),
std
::
transform
(
ins
->
inputs
()
.
begin
()
+
1
,
ins
->
inputs
()
.
end
(),
std
::
back_inserter
(
reshapes
),
[
&
](
auto
i
)
{
return
prog
->
insert_instruction
(
ins
,
reshape_op
,
i
);
});
return
prog
->
replace_instruction
(
ins
,
miopen_batch_norm_inference
{
op
},
ins
->
arguments
.
at
(
0
),
ins
->
inputs
()
.
at
(
0
),
reshapes
[
0
],
reshapes
[
1
],
reshapes
[
2
],
...
...
src/targets/gpu/target.cpp
View file @
99ee76c0
...
...
@@ -32,11 +32,11 @@ std::vector<pass> target::get_passes(migraph::context& gctx) const
memory_coloring
{
"hip::allocate"
},
fuse_ops
{},
dead_code_elimination
{},
eliminate_workspace
{},
eliminate_contiguous
{},
dead_code_elimination
{},
write_literals
{
&
ctx
},
eliminate_allocation
{
""
},
eliminate_workspace
{},
eliminate_allocation
{
"hip::allocate"
},
check_context
<
context
>
{},
dead_code_elimination
{}
};
...
...
src/targets/gpu/write_literals.cpp
View file @
99ee76c0
...
...
@@ -28,9 +28,9 @@ void write_literals::apply(program& p) const
assert
(
ctx
!=
nullptr
);
for
(
auto
ins
:
iterator_for
(
p
))
{
if
(
ins
->
op
.
name
()
==
"@literal"
)
if
(
ins
->
name
()
==
"@literal"
)
{
argument
a
=
to_gpu
(
ins
->
lit
.
get_argument
());
argument
a
=
to_gpu
(
ins
->
get_literal
()
.
get_argument
());
std
::
size_t
n
=
ctx
->
literals
.
size
();
ctx
->
literals
.
push_back
(
a
);
p
.
replace_instruction
(
ins
,
hip_load_literal
{
a
.
get_shape
(),
n
});
...
...
test/cpu_ops_test.cpp
View file @
99ee76c0
...
...
@@ -6,6 +6,132 @@
#include <migraph/verify.hpp>
#include "test.hpp"
void
im2col_3x3_no_pad_identity_test
()
{
std
::
size_t
f
[
2
]
=
{
3
,
3
};
std
::
size_t
size
[
2
]
=
{
3
,
3
};
std
::
array
<
std
::
size_t
,
2
>
padding
{{
0
,
0
}};
std
::
array
<
std
::
size_t
,
2
>
stride
{{
1
,
1
}};
std
::
array
<
std
::
size_t
,
2
>
dilation
{{
1
,
1
}};
std
::
size_t
channels
=
1
;
std
::
vector
<
int32_t
>
weights
(
channels
*
f
[
0
]
*
f
[
1
]);
std
::
vector
<
int32_t
>
input
(
channels
*
size
[
0
]
*
size
[
1
]);
std
::
iota
(
input
.
begin
(),
input
.
end
(),
0
);
migraph
::
program
p
;
migraph
::
shape
s_image
{
migraph
::
shape
::
int32_type
,
{
1
,
channels
,
size
[
0
],
size
[
1
]}};
migraph
::
shape
s_weights
{
migraph
::
shape
::
int32_type
,
{
1
,
channels
,
f
[
0
],
f
[
1
]}};
auto
l_image
=
p
.
add_literal
(
migraph
::
literal
{
s_image
,
input
});
auto
l_weights
=
p
.
add_literal
(
migraph
::
literal
{
s_weights
,
weights
});
p
.
add_instruction
(
migraph
::
im2col
{
padding
,
stride
,
dilation
},
l_image
,
l_weights
);
p
.
compile
(
migraph
::
cpu
::
cpu_target
{});
auto
result
=
p
.
eval
({});
std
::
size_t
col_height
=
(
size
[
0
]
-
f
[
0
]
+
2
*
padding
[
0
])
/
stride
[
0
]
+
1
;
std
::
size_t
col_width
=
(
size
[
1
]
-
f
[
1
]
+
2
*
padding
[
1
])
/
stride
[
1
]
+
1
;
std
::
vector
<
float
>
results_vector
(
channels
*
f
[
0
]
*
f
[
1
]
*
col_height
*
col_width
);
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
EXPECT
(
migraph
::
verify_range
(
results_vector
,
input
));
}
void
im2col_3x3_no_pad_test
()
{
std
::
size_t
f
[
2
]
=
{
3
,
3
};
std
::
size_t
size
[
2
]
=
{
4
,
4
};
std
::
array
<
std
::
size_t
,
2
>
padding
{{
0
,
0
}};
std
::
array
<
std
::
size_t
,
2
>
stride
{{
1
,
1
}};
std
::
array
<
std
::
size_t
,
2
>
dilation
{{
1
,
1
}};
std
::
size_t
channels
=
1
;
std
::
vector
<
int32_t
>
weights
(
channels
*
f
[
0
]
*
f
[
1
]);
std
::
vector
<
int32_t
>
input
(
channels
*
size
[
0
]
*
size
[
1
]);
std
::
iota
(
input
.
begin
(),
input
.
end
(),
0
);
migraph
::
program
p
;
migraph
::
shape
s_image
{
migraph
::
shape
::
int32_type
,
{
1
,
channels
,
size
[
0
],
size
[
1
]}};
migraph
::
shape
s_weights
{
migraph
::
shape
::
int32_type
,
{
1
,
channels
,
f
[
0
],
f
[
1
]}};
auto
l_image
=
p
.
add_literal
(
migraph
::
literal
{
s_image
,
input
});
auto
l_weights
=
p
.
add_literal
(
migraph
::
literal
{
s_weights
,
weights
});
p
.
add_instruction
(
migraph
::
im2col
{
padding
,
stride
,
dilation
},
l_image
,
l_weights
);
p
.
compile
(
migraph
::
cpu
::
cpu_target
{});
auto
result
=
p
.
eval
({});
std
::
vector
<
int
>
correct
=
{
0
,
1
,
2
,
4
,
5
,
6
,
8
,
9
,
10
,
1
,
2
,
3
,
5
,
6
,
7
,
9
,
10
,
11
,
4
,
5
,
6
,
8
,
9
,
10
,
12
,
13
,
14
,
5
,
6
,
7
,
9
,
10
,
11
,
13
,
14
,
15
};
std
::
size_t
col_height
=
(
size
[
0
]
-
f
[
0
]
+
2
*
padding
[
0
])
/
stride
[
0
]
+
1
;
std
::
size_t
col_width
=
(
size
[
1
]
-
f
[
1
]
+
2
*
padding
[
1
])
/
stride
[
1
]
+
1
;
std
::
vector
<
float
>
results_vector
(
channels
*
f
[
0
]
*
f
[
1
]
*
col_height
*
col_width
);
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
EXPECT
(
migraph
::
verify_range
(
results_vector
,
correct
));
}
void
im2col_3x3_stride_2_no_pad_test
()
{
std
::
size_t
f
[
2
]
=
{
3
,
3
};
std
::
size_t
size
[
2
]
=
{
6
,
6
};
std
::
array
<
std
::
size_t
,
2
>
padding
{{
0
,
0
}};
std
::
array
<
std
::
size_t
,
2
>
stride
{{
2
,
2
}};
std
::
array
<
std
::
size_t
,
2
>
dilation
{{
1
,
1
}};
std
::
size_t
channels
=
1
;
std
::
vector
<
int32_t
>
weights
(
channels
*
f
[
0
]
*
f
[
1
]);
std
::
vector
<
int32_t
>
input
(
channels
*
size
[
0
]
*
size
[
1
]);
std
::
iota
(
input
.
begin
(),
input
.
end
(),
0
);
migraph
::
program
p
;
migraph
::
shape
s_image
{
migraph
::
shape
::
int32_type
,
{
1
,
channels
,
size
[
0
],
size
[
1
]}};
migraph
::
shape
s_weights
{
migraph
::
shape
::
int32_type
,
{
1
,
channels
,
f
[
0
],
f
[
1
]}};
auto
l_image
=
p
.
add_literal
(
migraph
::
literal
{
s_image
,
input
});
auto
l_weights
=
p
.
add_literal
(
migraph
::
literal
{
s_weights
,
weights
});
p
.
add_instruction
(
migraph
::
im2col
{
padding
,
stride
,
dilation
},
l_image
,
l_weights
);
p
.
compile
(
migraph
::
cpu
::
cpu_target
{});
auto
result
=
p
.
eval
({});
std
::
vector
<
int
>
correct
=
{
0
,
1
,
2
,
6
,
7
,
8
,
12
,
13
,
14
,
2
,
3
,
4
,
8
,
9
,
10
,
14
,
15
,
16
,
12
,
13
,
14
,
18
,
19
,
20
,
24
,
25
,
26
,
14
,
15
,
16
,
20
,
21
,
22
,
26
,
27
,
28
};
std
::
size_t
col_height
=
(
size
[
0
]
-
f
[
0
]
+
2
*
padding
[
0
])
/
stride
[
0
]
+
1
;
std
::
size_t
col_width
=
(
size
[
1
]
-
f
[
1
]
+
2
*
padding
[
1
])
/
stride
[
1
]
+
1
;
std
::
vector
<
float
>
results_vector
(
channels
*
f
[
0
]
*
f
[
1
]
*
col_height
*
col_width
);
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
EXPECT
(
migraph
::
verify_range
(
results_vector
,
correct
));
}
void
im2col_3x3_with_padding_test
()
{
std
::
size_t
f
[
2
]
=
{
3
,
3
};
std
::
size_t
size
[
2
]
=
{
2
,
2
};
std
::
array
<
std
::
size_t
,
2
>
padding
{{
1
,
1
}};
std
::
array
<
std
::
size_t
,
2
>
stride
{{
1
,
1
}};
std
::
array
<
std
::
size_t
,
2
>
dilation
{{
1
,
1
}};
std
::
size_t
channels
=
1
;
std
::
vector
<
int32_t
>
weights
(
channels
*
f
[
0
]
*
f
[
1
]);
std
::
vector
<
int32_t
>
input
(
channels
*
size
[
0
]
*
size
[
1
]);
std
::
iota
(
input
.
begin
(),
input
.
end
(),
0
);
migraph
::
program
p
;
migraph
::
shape
s_image
{
migraph
::
shape
::
int32_type
,
{
1
,
channels
,
size
[
0
],
size
[
1
]}};
migraph
::
shape
s_weights
{
migraph
::
shape
::
int32_type
,
{
1
,
channels
,
f
[
0
],
f
[
1
]}};
auto
l_image
=
p
.
add_literal
(
migraph
::
literal
{
s_image
,
input
});
auto
l_weights
=
p
.
add_literal
(
migraph
::
literal
{
s_weights
,
weights
});
p
.
add_instruction
(
migraph
::
im2col
{
padding
,
stride
,
dilation
},
l_image
,
l_weights
);
p
.
compile
(
migraph
::
cpu
::
cpu_target
{});
auto
result
=
p
.
eval
({});
std
::
vector
<
int
>
correct
=
{
0
,
0
,
0
,
0
,
0
,
1
,
0
,
2
,
3
,
0
,
0
,
0
,
0
,
1
,
0
,
2
,
3
,
0
,
0
,
0
,
1
,
0
,
2
,
3
,
0
,
0
,
0
,
0
,
1
,
0
,
2
,
3
,
0
,
0
,
0
,
0
};
std
::
size_t
col_height
=
(
size
[
0
]
-
f
[
0
]
+
2
*
padding
[
0
])
/
stride
[
0
]
+
1
;
std
::
size_t
col_width
=
(
size
[
1
]
-
f
[
1
]
+
2
*
padding
[
1
])
/
stride
[
1
]
+
1
;
std
::
vector
<
float
>
results_vector
(
channels
*
f
[
0
]
*
f
[
1
]
*
col_height
*
col_width
);
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
EXPECT
(
migraph
::
verify_range
(
results_vector
,
correct
));
}
void
batch_norm_inference_test
()
{
migraph
::
program
p
;
...
...
@@ -46,6 +172,35 @@ void batch_norm_inference_test()
EXPECT
(
migraph
::
verify_range
(
result_vector
,
gold
));
}
void
im2col_3x3_with_channels_identity_test
()
{
std
::
size_t
f
[
2
]
=
{
3
,
3
};
std
::
size_t
size
[
2
]
=
{
3
,
3
};
std
::
array
<
std
::
size_t
,
2
>
padding
{{
0
,
0
}};
std
::
array
<
std
::
size_t
,
2
>
stride
{{
1
,
1
}};
std
::
array
<
std
::
size_t
,
2
>
dilation
{{
1
,
1
}};
std
::
size_t
channels
=
2
;
std
::
vector
<
int32_t
>
weights
(
channels
*
f
[
0
]
*
f
[
1
]);
std
::
vector
<
int32_t
>
input
(
channels
*
size
[
0
]
*
size
[
1
]);
std
::
iota
(
input
.
begin
(),
input
.
end
(),
0
);
migraph
::
program
p
;
migraph
::
shape
s_image
{
migraph
::
shape
::
int32_type
,
{
1
,
channels
,
size
[
0
],
size
[
1
]}};
migraph
::
shape
s_weights
{
migraph
::
shape
::
int32_type
,
{
1
,
channels
,
f
[
0
],
f
[
1
]}};
auto
l_image
=
p
.
add_literal
(
migraph
::
literal
{
s_image
,
input
});
auto
l_weights
=
p
.
add_literal
(
migraph
::
literal
{
s_weights
,
weights
});
p
.
add_instruction
(
migraph
::
im2col
{
padding
,
stride
,
dilation
},
l_image
,
l_weights
);
p
.
compile
(
migraph
::
cpu
::
cpu_target
{});
auto
result
=
p
.
eval
({});
std
::
size_t
col_height
=
(
size
[
0
]
-
f
[
0
]
+
2
*
padding
[
0
])
/
stride
[
0
]
+
1
;
std
::
size_t
col_width
=
(
size
[
1
]
-
f
[
1
]
+
2
*
padding
[
1
])
/
stride
[
1
]
+
1
;
std
::
vector
<
float
>
results_vector
(
channels
*
f
[
0
]
*
f
[
1
]
*
col_height
*
col_width
);
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
EXPECT
(
migraph
::
verify_range
(
results_vector
,
input
));
}
void
exp_test
()
{
migraph
::
program
p
;
...
...
@@ -666,4 +821,9 @@ int main()
conv2d_padding_test
();
conv2d_padding_stride_test
();
batch_norm_inference_test
();
im2col_3x3_no_pad_identity_test
();
im2col_3x3_no_pad_test
();
im2col_3x3_stride_2_no_pad_test
();
im2col_3x3_with_channels_identity_test
();
im2col_3x3_with_padding_test
();
}
test/eval_test.cpp
View file @
99ee76c0
...
...
@@ -21,13 +21,13 @@ struct reverse_pass
{
for
(
auto
ins
:
migraph
::
iterator_for
(
p
))
{
if
(
ins
->
op
.
name
()
==
"sum"
)
if
(
ins
->
name
()
==
"sum"
)
{
p
.
replace_instruction
(
ins
,
minus_op
{},
ins
->
arguments
);
p
.
replace_instruction
(
ins
,
minus_op
{},
ins
->
inputs
()
);
}
else
if
(
ins
->
op
.
name
()
==
"minus"
)
else
if
(
ins
->
name
()
==
"minus"
)
{
p
.
replace_instruction
(
ins
,
sum_op
{},
ins
->
arguments
);
p
.
replace_instruction
(
ins
,
sum_op
{},
ins
->
inputs
()
);
}
}
}
...
...
test/gpu/miopen.cpp
View file @
99ee76c0
...
...
@@ -97,10 +97,10 @@ void compile_check(migraph::program& p, const migraph::target& t)
}
template
<
class
V
>
migraph
::
argument
run_cpu
()
migraph
::
argument
run_cpu
(
migraph
::
program
&
p
)
{
V
v
;
auto
p
=
v
.
create_program
();
p
=
v
.
create_program
();
auto_print
pp
{
p
,
0
};
compile_check
(
p
,
migraph
::
cpu
::
cpu_target
{});
migraph
::
program
::
parameter_map
m
;
...
...
@@ -112,10 +112,10 @@ migraph::argument run_cpu()
}
template
<
class
V
>
migraph
::
argument
run_gpu
()
migraph
::
argument
run_gpu
(
migraph
::
program
&
p
)
{
V
v
;
auto
p
=
v
.
create_program
();
p
=
v
.
create_program
();
auto_print
pp
{
p
,
1
};
compile_check
(
p
,
migraph
::
gpu
::
target
{});
migraph
::
program
::
parameter_map
m
;
...
...
@@ -131,9 +131,20 @@ template <class V>
void
verify_program
()
{
auto_print
::
set_terminate_handler
(
migraph
::
get_type_name
<
V
>
());
auto
cpu_arg_f
=
detach_async
([]
{
return
run_cpu
<
V
>
();
});
auto
gpu_arg
=
run_gpu
<
V
>
();
verify_args
(
migraph
::
get_type_name
<
V
>
(),
cpu_arg_f
.
get
(),
gpu_arg
);
migraph
::
program
cpu_prog
;
migraph
::
program
gpu_prog
;
auto
cpu_arg_f
=
detach_async
([
&
]
{
return
run_cpu
<
V
>
(
cpu_prog
);
});
auto
gpu_arg
=
run_gpu
<
V
>
(
gpu_prog
);
bool
passed
=
verify_args
(
migraph
::
get_type_name
<
V
>
(),
cpu_arg_f
.
get
(),
gpu_arg
);
if
(
not
passed
)
{
V
v
;
auto
p
=
v
.
create_program
();
std
::
cout
<<
p
<<
std
::
endl
;
std
::
cout
<<
"cpu:
\n
"
<<
cpu_prog
<<
std
::
endl
;
std
::
cout
<<
"gpu:
\n
"
<<
gpu_prog
<<
std
::
endl
;
std
::
cout
<<
std
::
endl
;
}
std
::
set_terminate
(
nullptr
);
}
...
...
@@ -235,6 +246,28 @@ struct test_add_broadcast5
}
};
struct
test_softmax
{
migraph
::
program
create_program
()
const
{
migraph
::
program
p
;
auto
x
=
p
.
add_parameter
(
"x"
,
migraph
::
shape
{
migraph
::
shape
::
float_type
,
{
5
,
3
,
4
,
2
}});
p
.
add_instruction
(
migraph
::
softmax
{},
x
);
return
p
;
}
};
struct
test_softmax2
{
migraph
::
program
create_program
()
const
{
migraph
::
program
p
;
auto
x
=
p
.
add_parameter
(
"x"
,
migraph
::
shape
{
migraph
::
shape
::
float_type
,
{
1
,
1000
,
1
,
1
}});
p
.
add_instruction
(
migraph
::
softmax
{},
x
);
return
p
;
}
};
struct
test_conv
{
migraph
::
program
create_program
()
const
...
...
@@ -248,6 +281,20 @@ struct test_conv
}
};
struct
test_conv2
{
migraph
::
program
create_program
()
const
{
migraph
::
program
p
;
auto
input
=
p
.
add_parameter
(
"x"
,
migraph
::
shape
{
migraph
::
shape
::
float_type
,
{
1
,
512
,
28
,
28
}});
auto
weights
=
p
.
add_parameter
(
"w"
,
migraph
::
shape
{
migraph
::
shape
::
float_type
,
{
256
,
512
,
1
,
1
}});
p
.
add_instruction
(
migraph
::
convolution
{{
0
,
0
},
{
1
,
1
},
{
1
,
1
}},
input
,
weights
);
return
p
;
}
};
struct
test_conv_relu
{
migraph
::
program
create_program
()
const
...
...
@@ -428,6 +475,27 @@ struct test_batchnorm_inference
}
};
struct
test_conv_bn
{
migraph
::
program
create_program
()
const
{
migraph
::
program
p
;
migraph
::
shape
xs
{
migraph
::
shape
::
float_type
,
{
1
,
3
,
224
,
224
}};
migraph
::
shape
ws
{
migraph
::
shape
::
float_type
,
{
64
,
3
,
7
,
7
}};
migraph
::
shape
vars
{
migraph
::
shape
::
float_type
,
{
64
}};
auto
x
=
p
.
add_parameter
(
"x"
,
xs
);
auto
w
=
p
.
add_parameter
(
"w"
,
ws
);
auto
conv
=
p
.
add_instruction
(
migraph
::
convolution
{{
3
,
3
},
{
2
,
2
},
{
1
,
1
}},
x
,
w
);
auto
scale
=
p
.
add_literal
(
migraph
::
abs
(
migraph
::
generate_literal
(
vars
,
1
)));
auto
bias
=
p
.
add_literal
(
migraph
::
abs
(
migraph
::
generate_literal
(
vars
,
2
)));
auto
mean
=
p
.
add_literal
(
migraph
::
abs
(
migraph
::
generate_literal
(
vars
,
3
)));
auto
variance
=
p
.
add_literal
(
migraph
::
abs
(
migraph
::
generate_literal
(
vars
,
4
)));
p
.
add_instruction
(
migraph
::
batch_norm_inference
{},
conv
,
scale
,
bias
,
mean
,
variance
);
return
p
;
}
};
struct
test_conv_bn_relu_pooling
{
migraph
::
program
create_program
()
const
...
...
@@ -495,7 +563,10 @@ int main()
verify_program
<
test_add_broadcast3
>
();
verify_program
<
test_add_broadcast4
>
();
verify_program
<
test_add_broadcast5
>
();
verify_program
<
test_softmax
>
();
verify_program
<
test_softmax2
>
();
verify_program
<
test_conv
>
();
verify_program
<
test_conv2
>
();
verify_program
<
test_conv_relu
>
();
verify_program
<
test_add_relu
>
();
verify_program
<
test_conv_pooling
>
();
...
...
@@ -508,6 +579,7 @@ int main()
verify_program
<
test_transpose
>
();
verify_program
<
test_batchnorm_inference
>
();
verify_program
<
test_batchnorm_inference_2
>
();
verify_program
<
test_conv_bn
>
();
verify_program
<
test_conv_bn_relu_pooling
>
();
verify_program
<
test_conv_bn_relu_pooling2
>
();
}
test/include/rob.hpp
0 → 100644
View file @
99ee76c0
#ifndef MIGRAPH_GUARD_ROB_HPP
#define MIGRAPH_GUARD_ROB_HPP
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wglobal-constructors"
#endif
// Used to access private member variables
template
<
class
Tag
>
struct
stowed
{
static
typename
Tag
::
type
value
;
};
template
<
class
Tag
>
typename
Tag
::
type
stowed
<
Tag
>::
value
;
template
<
class
Tag
,
typename
Tag
::
type
X
>
struct
stow_private
{
stow_private
()
noexcept
{
stowed
<
Tag
>::
value
=
X
;
}
static
stow_private
instance
;
};
template
<
class
Tag
,
typename
Tag
::
type
X
>
stow_private
<
Tag
,
X
>
stow_private
<
Tag
,
X
>::
instance
;
template
<
class
C
,
class
T
>
struct
mem_data_ptr
{
using
type
=
T
C
::*
;
};
#define MIGRAPH_ROB(name, Type, C, mem) \
struct name##_tag : mem_data_ptr<C, Type> \
{ \
}; \
template struct stow_private<name##_tag, &C::mem>; \
template <class T> \
auto& name(T&& x) \
{ \
return x.*stowed<name##_tag>::value; \
}
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#endif
test/operation.cpp
View file @
99ee76c0
...
...
@@ -43,7 +43,9 @@ void operation_copy_test()
simple_operation
s
{};
migraph
::
operation
op1
=
s
;
// NOLINT
migraph
::
operation
op2
=
op1
;
// NOLINT
// cppcheck-suppress duplicateExpression
EXPECT
(
s
.
name
()
==
op1
.
name
());
// cppcheck-suppress duplicateExpression
EXPECT
(
op2
.
name
()
==
op1
.
name
());
}
...
...
test/validate.cpp
View file @
99ee76c0
...
...
@@ -2,6 +2,7 @@
#include <migraph/instruction.hpp>
#include <basic_ops.hpp>
#include <test.hpp>
#include <rob.hpp>
void
simple_test
()
{
...
...
@@ -38,6 +39,11 @@ void incomplete_args()
EXPECT
(
bool
{
p
.
validate
()
==
ins
});
}
MIGRAPH_ROB
(
access_ins_arguments
,
std
::
vector
<
migraph
::
instruction_ref
>
,
migraph
::
instruction
,
arguments
)
void
invalid_args
()
{
migraph
::
program
p
;
...
...
@@ -45,7 +51,7 @@ void invalid_args()
auto
one
=
p
.
add_literal
(
1
);
auto
two
=
p
.
add_literal
(
2
);
auto
ins
=
p
.
add_instruction
(
sum_op
{},
one
,
two
);
ins
->
arguments
.
clear
();
access_
ins
_
arguments
(
*
ins
)
.
clear
();
EXPECT
(
bool
{
p
.
validate
()
==
p
.
begin
()});
}
...
...
tools/include/operation.hpp
View file @
99ee76c0
...
...
@@ -8,6 +8,7 @@
#include <type_traits>
#include <utility>
#include <migraph/shape.hpp>
#include <migraph/rank.hpp>
#include <migraph/argument.hpp>
#include <migraph/context.hpp>
#include <migraph/auto_any_cast.hpp>
...
...
@@ -27,13 +28,16 @@ struct operation
/// exception.
shape
compute_shape
(
const
std
::
vector
<
shape
>&
input
)
const
;
/**
* @brief This performs the operation's computation
* @brief This performs the operation's computation.
*
* This method can be optional when the operation is only used as a placeholder to be lowered
* later on.
*
* @param ctx This is the context created by the `target` during compilation. Implementations
* can use the target's `context` class rather than the `context` interface class.
* @param output This is the output shape. It is equivalent to running `compute_shape` with each
* `shape` of the `argument`.
* @param input This is the `argument` result from the previous instuction's computation.
* @param input This is the `argument` result from the previous inst
r
uction's computation.
* @return Return an `argument` of the result computation. The `shape` of `argument` should be
* the same the `output` shape.
*/
...
...
@@ -55,11 +59,29 @@ auto operator<<(std::ostream& os, const T& x) -> decltype(os << x.name())
}
// namespace operation_stream
template
<
class
T
>
auto
compute_op
(
rank
<
1
>
,
const
T
&
x
,
context
&
ctx
,
const
shape
&
output_shape
,
const
std
::
vector
<
argument
>&
input
)
->
decltype
(
x
.
compute
(
auto_any_cast
(
ctx
),
output_shape
,
input
))
{
return
x
.
compute
(
auto_any_cast
(
ctx
),
output_shape
,
input
);
}
template
<
class
T
>
argument
compute_op
(
rank
<
0
>
,
const
T
&
x
,
context
&
,
const
shape
&
,
const
std
::
vector
<
argument
>&
)
{
std
::
string
name
=
x
.
name
();
MIGRAPH_THROW
(
"Not computable: "
+
name
);
}
template
<
class
T
>
argument
compute_op
(
const
T
&
x
,
context
&
ctx
,
const
shape
&
output_shape
,
const
std
::
vector
<
argument
>&
input
)
{
return
x
.
compute
(
auto_any_cast
(
ctx
)
,
output_shape
,
input
);
return
compute
_op
(
rank
<
1
>
{},
x
,
ctx
,
output_shape
,
input
);
}
<%
...
...
Prev
1
2
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