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
038a4c52
Commit
038a4c52
authored
Aug 22, 2018
by
wsttiger
Browse files
Merged from master still debugging resnet
parents
06cc4f8f
905d4ab0
Changes
41
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
695 additions
and
281 deletions
+695
-281
src/onnx/onnx.cpp
src/onnx/onnx.cpp
+16
-32
src/onnx/perf_onnx.cpp
src/onnx/perf_onnx.cpp
+36
-0
src/onnx/resnet18.cpp
src/onnx/resnet18.cpp
+33
-36
src/onnx/verify_onnx.cpp
src/onnx/verify_onnx.cpp
+2
-2
src/program.cpp
src/program.cpp
+172
-67
src/shape.cpp
src/shape.cpp
+79
-47
src/targets/cpu/cpu_lowering.cpp
src/targets/cpu/cpu_lowering.cpp
+16
-15
src/targets/gpu/CMakeLists.txt
src/targets/gpu/CMakeLists.txt
+1
-0
src/targets/gpu/eliminate_workspace.cpp
src/targets/gpu/eliminate_workspace.cpp
+38
-0
src/targets/gpu/hip.cpp
src/targets/gpu/hip.cpp
+25
-9
src/targets/gpu/include/migraph/gpu/eliminate_workspace.hpp
src/targets/gpu/include/migraph/gpu/eliminate_workspace.hpp
+20
-0
src/targets/gpu/include/migraph/gpu/hip.hpp
src/targets/gpu/include/migraph/gpu/hip.hpp
+8
-6
src/targets/gpu/lowering.cpp
src/targets/gpu/lowering.cpp
+67
-50
src/targets/gpu/target.cpp
src/targets/gpu/target.cpp
+4
-3
test/cpu_ops_test.cpp
test/cpu_ops_test.cpp
+1
-3
test/gpu/miopen.cpp
test/gpu/miopen.cpp
+25
-0
test/include/basic_ops.hpp
test/include/basic_ops.hpp
+6
-6
test/include/test.hpp
test/include/test.hpp
+1
-1
test/op_shape_test.cpp
test/op_shape_test.cpp
+141
-0
test/operation.cpp
test/operation.cpp
+4
-4
No files found.
src/onnx/onnx.cpp
View file @
038a4c52
...
...
@@ -6,6 +6,7 @@
#include <unordered_map>
#include <functional>
#include <array>
#include <utility>
#include <vector>
#include <migraph/fallthrough.hpp>
...
...
@@ -27,7 +28,7 @@ struct unknown
else
return
input
.
front
();
}
argument
compute
(
context
&
,
shape
,
std
::
vector
<
argument
>
)
const
argument
compute
(
context
&
,
const
shape
&
,
const
std
::
vector
<
argument
>
&
)
const
{
MIGRAPH_THROW
(
"not computable"
);
}
...
...
@@ -103,7 +104,7 @@ struct onnx_parser
}
instruction_ref
parse_conv
(
std
::
string
,
attribute_map
attributes
,
std
::
vector
<
instruction_ref
>
args
)
parse_conv
(
const
std
::
string
&
,
attribute_map
attributes
,
std
::
vector
<
instruction_ref
>
args
)
{
convolution
op
;
if
(
contains
(
attributes
,
"pads"
))
...
...
@@ -128,8 +129,9 @@ struct onnx_parser
return
prog
.
add_instruction
(
op
,
args
);
}
instruction_ref
parse_pooling
(
std
::
string
name
,
attribute_map
attributes
,
std
::
vector
<
instruction_ref
>
args
)
instruction_ref
parse_pooling
(
const
std
::
string
&
name
,
attribute_map
attributes
,
std
::
vector
<
instruction_ref
>
args
)
{
pooling
op
{
name
==
"MaxPool"
?
"max"
:
"average"
};
if
(
contains
(
attributes
,
"pads"
))
...
...
@@ -144,30 +146,11 @@ struct onnx_parser
{
copy
(
attributes
[
"kernel_shape"
].
ints
(),
op
.
lengths
.
begin
());
}
return
prog
.
add_instruction
(
op
,
args
);
return
prog
.
add_instruction
(
op
,
std
::
move
(
args
)
)
;
}
instruction_ref
parse_average_pooling
(
std
::
string
,
attribute_map
attributes
,
std
::
vector
<
instruction_ref
>
args
)
{
pooling
op
{
"average"
};
if
(
contains
(
attributes
,
"pads"
))
{
copy
(
attributes
[
"pads"
].
ints
(),
op
.
padding
.
begin
());
}
if
(
contains
(
attributes
,
"strides"
))
{
copy
(
attributes
[
"strides"
].
ints
(),
op
.
stride
.
begin
());
}
if
(
contains
(
attributes
,
"kernel_shape"
))
{
copy
(
attributes
[
"kernel_shape"
].
ints
(),
op
.
lengths
.
begin
());
}
return
prog
.
add_instruction
(
op
,
args
);
}
instruction_ref
parse_reshape
(
std
::
string
,
attribute_map
attributes
,
std
::
vector
<
instruction_ref
>
args
)
parse_reshape
(
const
std
::
string
&
,
attribute_map
attributes
,
std
::
vector
<
instruction_ref
>
args
)
{
reshape
op
;
if
(
args
.
size
()
==
1
)
...
...
@@ -184,7 +167,7 @@ struct onnx_parser
}
instruction_ref
parse_flatten
(
std
::
string
,
attribute_map
attributes
,
std
::
vector
<
instruction_ref
>
args
)
parse_flatten
(
const
std
::
string
&
,
attribute_map
attributes
,
std
::
vector
<
instruction_ref
>
args
)
{
uint64_t
axis
=
0
;
if
(
contains
(
attributes
,
"axis"
))
...
...
@@ -194,15 +177,16 @@ struct onnx_parser
return
prog
.
add_instruction
(
flatten
{
axis
},
args
[
0
]);
}
instruction_ref
parse_constant
(
std
::
string
,
attribute_map
attributes
,
std
::
vector
<
instruction_ref
>
)
instruction_ref
parse_constant
(
const
std
::
string
&
,
attribute_map
attributes
,
const
std
::
vector
<
instruction_ref
>&
)
{
literal
v
=
parse_value
(
attributes
.
at
(
"value"
));
return
prog
.
add_literal
(
v
);
}
instruction_ref
parse_gemm
(
std
::
string
,
attribute_map
attributes
,
std
::
vector
<
instruction_ref
>
args
)
parse_gemm
(
const
std
::
string
&
,
attribute_map
attributes
,
std
::
vector
<
instruction_ref
>
args
)
{
float
alpha
=
1.0
f
;
float
beta
=
0.0
f
;
...
...
@@ -238,7 +222,7 @@ struct onnx_parser
}
instruction_ref
parse_batchnorm
(
std
::
string
,
attribute_map
attributes
,
std
::
vector
<
instruction_ref
>
args
)
parse_batchnorm
(
const
std
::
string
&
,
attribute_map
attributes
,
std
::
vector
<
instruction_ref
>
args
)
{
float
epsilon
=
1e-5
f
;
float
momentum
=
0.9
f
;
...
...
@@ -263,7 +247,7 @@ struct onnx_parser
:
batch_norm_inference
::
per_activation
;
}
batch_norm_inference
op
{
epsilon
,
momentum
,
bn_mode
,
is_test
};
return
prog
.
add_instruction
(
op
,
args
);
return
prog
.
add_instruction
(
op
,
std
::
move
(
args
)
)
;
}
void
parse_from
(
std
::
istream
&
is
)
...
...
@@ -312,7 +296,7 @@ struct onnx_parser
}
}
void
parse_node
(
std
::
string
name
)
void
parse_node
(
const
std
::
string
&
name
)
{
if
(
name
.
empty
())
MIGRAPH_THROW
(
"Onnx node must have a name"
);
...
...
src/onnx/perf_onnx.cpp
0 → 100644
View file @
038a4c52
#include <migraph/onnx.hpp>
#include <migraph/gpu/target.hpp>
#include <migraph/gpu/hip.hpp>
#include <migraph/generate.hpp>
#include <migraph/verify.hpp>
migraph
::
program
::
parameter_map
create_param_map
(
const
migraph
::
program
&
p
,
bool
gpu
=
true
)
{
migraph
::
program
::
parameter_map
m
;
for
(
auto
&&
x
:
p
.
get_parameter_shapes
())
{
if
(
gpu
)
m
[
x
.
first
]
=
migraph
::
gpu
::
to_gpu
(
migraph
::
generate_argument
(
x
.
second
));
else
m
[
x
.
first
]
=
migraph
::
generate_argument
(
x
.
second
);
}
return
m
;
}
int
main
(
int
argc
,
char
const
*
argv
[])
{
if
(
argc
>
1
)
{
std
::
string
file
=
argv
[
1
];
std
::
size_t
n
=
argc
>
2
?
std
::
stoul
(
argv
[
2
])
:
50
;
auto
p
=
migraph
::
parse_onnx
(
file
);
std
::
cout
<<
"Compiling ... "
<<
std
::
endl
;
p
.
compile
(
migraph
::
gpu
::
target
{});
std
::
cout
<<
"Allocating params ... "
<<
std
::
endl
;
auto
m
=
create_param_map
(
p
);
std
::
cout
<<
"Running performance report ... "
<<
std
::
endl
;
p
.
perf_report
(
std
::
cout
,
n
,
m
);
}
}
src/onnx/resnet18.cpp
View file @
038a4c52
...
...
@@ -61,52 +61,49 @@ int main(int argc, char const* argv[])
std
::
cout
<<
prog
<<
std
::
endl
;
auto
imageset
=
read_cifar10_images
(
datafile
);
// GPU target
prog
.
compile
(
migraph
::
gpu
::
target
{});
migraph
::
program
::
parameter_map
m
;
auto
s
=
migraph
::
shape
{
migraph
::
shape
::
float_type
,
{
1
,
3
,
32
,
32
}};
m
[
"output"
]
=
migraph
::
gpu
::
to_gpu
(
migraph
::
generate_argument
(
prog
.
get_parameter_shape
(
"output"
)));
auto
labels
=
imageset
.
first
;
auto
input
=
imageset
.
second
;
auto
ptr
=
input
.
data
();
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
std
::
cout
<<
"label: "
<<
(
uint32_t
)
labels
[
i
]
<<
" ----> "
;
m
[
"0"
]
=
migraph
::
gpu
::
to_gpu
(
migraph
::
argument
{
s
,
&
ptr
[
3072
*
i
]});
auto
result
=
migraph
::
gpu
::
from_gpu
(
prog
.
eval
(
m
));
std
::
vector
<
float
>
logits
;
result
.
visit
([
&
](
auto
output
)
{
logits
.
assign
(
output
.
begin
(),
output
.
end
());
});
std
::
vector
<
float
>
probs
=
softmax
(
logits
);
for
(
auto
x
:
probs
)
std
::
cout
<<
x
<<
" "
;
std
::
cout
<<
std
::
endl
;
std
::
cout
<<
std
::
endl
;
for
(
int
j
=
0
;
j
<
10
;
j
++
)
{
std
::
cout
<<
255.0
*
input
[
i
*
3072
+
j
]
<<
" "
;
}
std
::
cout
<<
std
::
endl
;
std
::
cout
<<
std
::
endl
;
std
::
cout
<<
std
::
endl
;
}
// // // CPU target
// prog.compile(migraph::cpu::cpu_target{});
// auto s = migraph::shape{migraph::shape::float_type, {1, 3, 32, 32}};
// // GPU target
// prog.compile(migraph::gpu::target{});
// migraph::program::parameter_map m;
// auto s = migraph::shape{migraph::shape::float_type, {1, 3, 32, 32}};
// for(auto&& x : prog.get_parameter_shapes())
// {
// m[x.first] = migraph::gpu::to_gpu(migraph::generate_argument(x.second));
// }
// auto labels = imageset.first;
// auto input = imageset.second;
// auto ptr = input.data();
// for(int i = 0; i < 10; i++)
// {
// std::cout << "label: " << (uint32_t)labels[i] << " ----> ";
//
auto input3 =
migraph::argument{s, &ptr[3072 * i]};
// auto result =
prog.eval({{"0", input3}}
);
//
m["0"] = migraph::gpu::to_gpu(
migraph::argument{s, &ptr[3072 * i]}
)
;
// auto result =
migraph::gpu::from_gpu(prog.eval(m)
);
// std::vector<float> logits;
// result.visit([&](auto output) { logits.assign(output.begin(), output.end()); });
// std::vector<float> probs = softmax(logits);
// for(auto x : logits)
// std::cout << x << " ";
// //std::cout << x << " ";
// //std::cout << x << std::endl;
// printf("%10.5e ", x);
// std::cout << std::endl;
// std::cout << std::endl;
// }
// // CPU target
prog
.
compile
(
migraph
::
cpu
::
cpu_target
{});
auto
s
=
migraph
::
shape
{
migraph
::
shape
::
float_type
,
{
1
,
3
,
32
,
32
}};
auto
labels
=
imageset
.
first
;
auto
input
=
imageset
.
second
;
auto
ptr
=
input
.
data
();
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
std
::
cout
<<
"label: "
<<
(
uint32_t
)
labels
[
i
]
<<
" ----> "
;
auto
input3
=
migraph
::
argument
{
s
,
&
ptr
[
3072
*
i
]};
auto
result
=
prog
.
eval
({{
"0"
,
input3
}});
std
::
vector
<
float
>
logits
;
result
.
visit
([
&
](
auto
output
)
{
logits
.
assign
(
output
.
begin
(),
output
.
end
());
});
std
::
vector
<
float
>
probs
=
softmax
(
logits
);
for
(
auto
x
:
logits
)
printf
(
"%10.5e "
,
x
);
std
::
cout
<<
std
::
endl
;
}
}
src/onnx/verify_onnx.cpp
View file @
038a4c52
...
...
@@ -7,7 +7,7 @@
#include <migraph/generate.hpp>
#include <migraph/verify.hpp>
migraph
::
argument
run_cpu
(
std
::
string
file
)
migraph
::
argument
run_cpu
(
const
std
::
string
&
file
)
{
auto
p
=
migraph
::
parse_onnx
(
file
);
p
.
compile
(
migraph
::
cpu
::
cpu_target
{});
...
...
@@ -21,7 +21,7 @@ migraph::argument run_cpu(std::string file)
return
out
;
}
migraph
::
argument
run_gpu
(
std
::
string
file
)
migraph
::
argument
run_gpu
(
const
std
::
string
&
file
)
{
auto
p
=
migraph
::
parse_onnx
(
file
);
p
.
compile
(
migraph
::
gpu
::
target
{});
...
...
src/program.cpp
View file @
038a4c52
...
...
@@ -2,9 +2,12 @@
#include <migraph/stringutils.hpp>
#include <migraph/instruction.hpp>
#include <migraph/env.hpp>
#include <migraph/time.hpp>
#include <migraph/iterator_for.hpp>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <utility>
namespace
migraph
{
...
...
@@ -19,18 +22,68 @@ struct program_impl
const
operation
&
get_operation
(
instruction_ref
ins
)
{
return
ins
->
op
;
}
template
<
class
F
>
static
void
print_program
(
std
::
ostream
&
os
,
const
program
&
p
,
F
annonate
)
{
std
::
unordered_map
<
instruction_ref
,
std
::
string
>
names
;
int
count
=
0
;
for
(
auto
ins
:
iterator_for
(
p
))
{
std
::
string
var_name
=
"@"
+
std
::
to_string
(
count
);
if
(
ins
->
op
.
name
()
==
"@param"
)
{
var_name
=
any_cast
<
builtin
::
param
>
(
ins
->
op
).
parameter
;
}
os
<<
var_name
<<
" = "
;
os
<<
ins
->
op
;
if
(
ins
->
op
.
name
()
==
"@literal"
)
{
if
(
ins
->
lit
.
get_shape
().
elements
()
>
10
)
os
<<
"{ ... }"
;
else
os
<<
"{"
<<
ins
->
lit
<<
"}"
;
}
if
(
!
ins
->
arguments
.
empty
())
{
char
delim
=
'('
;
for
(
auto
&&
arg
:
ins
->
arguments
)
{
assert
(
p
.
has_instruction
(
arg
)
&&
"Instruction not found"
);
os
<<
delim
<<
names
.
at
(
arg
);
delim
=
','
;
}
os
<<
")"
;
}
os
<<
" -> "
<<
ins
->
result
;
annonate
(
ins
,
names
);
os
<<
std
::
endl
;
names
.
emplace
(
ins
,
var_name
);
count
++
;
}
}
program
::
program
()
:
impl
(
std
::
make_unique
<
program_impl
>
())
{}
program
::
program
(
program
&&
)
noexcept
=
default
;
program
&
program
::
operator
=
(
program
&&
)
noexcept
=
default
;
program
::~
program
()
noexcept
=
default
;
instruction_ref
program
::
add_instruction
(
operation
op
,
std
::
vector
<
instruction_ref
>
args
)
instruction_ref
program
::
add_instruction
(
const
operation
&
op
,
std
::
vector
<
instruction_ref
>
args
)
{
return
insert_instruction
(
impl
->
instructions
.
end
(),
std
::
move
(
op
)
,
std
::
move
(
args
));
return
insert_instruction
(
impl
->
instructions
.
end
(),
op
,
std
::
move
(
args
));
}
instruction_ref
program
::
insert_instruction
(
instruction_ref
ins
,
operation
op
,
std
::
vector
<
instruction_ref
>
args
)
instruction_ref
program
::
insert_instruction
(
instruction_ref
ins
,
const
operation
&
op
,
std
::
vector
<
instruction_ref
>
args
)
{
assert
(
std
::
all_of
(
args
.
begin
(),
args
.
end
(),
[
&
](
instruction_ref
x
)
{
return
has_instruction
(
x
);
})
&&
...
...
@@ -45,8 +98,9 @@ program::insert_instruction(instruction_ref ins, operation op, std::vector<instr
return
result
;
}
instruction_ref
program
::
replace_instruction
(
instruction_ref
ins
,
operation
op
,
std
::
vector
<
instruction_ref
>
args
)
instruction_ref
program
::
replace_instruction
(
instruction_ref
ins
,
const
operation
&
op
,
std
::
vector
<
instruction_ref
>
args
)
{
assert
(
std
::
all_of
(
args
.
begin
(),
args
.
end
(),
[
&
](
instruction_ref
x
)
{
return
has_instruction
(
x
);
})
&&
...
...
@@ -117,7 +171,7 @@ instruction_ref program::add_literal(literal l)
return
impl
->
instructions
.
begin
();
}
instruction_ref
program
::
add_outline
(
shape
s
)
instruction_ref
program
::
add_outline
(
const
shape
&
s
)
{
impl
->
instructions
.
push_front
({
builtin
::
outline
{
s
},
s
,
{}});
return
impl
->
instructions
.
begin
();
...
...
@@ -125,7 +179,7 @@ instruction_ref program::add_outline(shape s)
instruction_ref
program
::
add_parameter
(
std
::
string
name
,
shape
s
)
{
impl
->
instructions
.
push_front
({
builtin
::
param
{
std
::
move
(
name
)},
s
,
{}});
impl
->
instructions
.
push_front
({
builtin
::
param
{
std
::
move
(
name
)},
s
td
::
move
(
s
)
,
{}});
return
impl
->
instructions
.
begin
();
}
...
...
@@ -170,6 +224,7 @@ bool program::has_instruction(instruction_ref ins) const
})
!=
impl
->
instructions
.
end
();
}
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
();
}
...
...
@@ -195,8 +250,10 @@ void program::compile(const target& t)
std
::
cout
<<
"Pass: "
<<
p
.
name
()
<<
std
::
endl
;
p
.
apply
(
*
this
);
if
(
enabled
(
MIGRAPH_TRACE_COMPILE
{}))
std
::
cout
<<
*
this
<<
std
::
endl
<<
std
::
endl
;
std
::
cout
<<
*
this
<<
std
::
endl
;
#ifndef NDEBUG
if
(
enabled
(
MIGRAPH_TRACE_COMPILE
{}))
std
::
cout
<<
"Validate ..."
<<
std
::
endl
;
auto
invalid
=
this
->
validate
();
if
(
invalid
!=
impl
->
instructions
.
end
())
{
...
...
@@ -204,6 +261,8 @@ void program::compile(const target& t)
MIGRAPH_THROW
(
p
.
name
()
+
" pass produces invalid program at instruction "
+
std
::
to_string
(
index
)
+
": "
+
invalid
->
op
.
name
());
}
if
(
enabled
(
MIGRAPH_TRACE_COMPILE
{}))
std
::
cout
<<
std
::
endl
;
#endif
}
auto
invalid
=
this
->
validate
();
...
...
@@ -214,86 +273,132 @@ void program::compile(const target& t)
}
}
argument
program
::
eval
(
std
::
unordered_map
<
std
::
string
,
argument
>
params
)
const
template
<
class
F
>
argument
generic_eval
(
const
program
&
p
,
context
&
ctx
,
std
::
unordered_map
<
std
::
string
,
argument
>
params
,
F
trace
)
{
assert
(
this
->
validate
()
==
impl
->
instructions
.
end
());
std
::
unordered_map
<
const
instruction
*
,
argument
>
results
;
argument
result
;
for
(
auto
&
ins
:
impl
->
instructions
)
assert
(
p
.
validate
()
==
p
.
end
());
std
::
unordered_map
<
instruction_ref
,
argument
>
results
;
results
.
reserve
(
p
.
size
()
*
2
);
std
::
vector
<
argument
>
values
;
values
.
reserve
(
16
);
for
(
auto
ins
:
iterator_for
(
p
))
{
if
(
ins
.
op
.
name
()
==
"@literal"
)
if
(
ins
->
op
.
name
()
==
"@literal"
)
{
result
=
ins
.
lit
.
get_argument
();
result
s
.
emplace
(
ins
,
trace
(
ins
,
[
&
]
{
return
ins
->
lit
.
get_argument
();
}));
}
else
if
(
ins
.
op
.
name
()
==
"@param"
)
else
if
(
ins
->
op
.
name
()
==
"@param"
)
{
result
=
params
.
at
(
any_cast
<
builtin
::
param
>
(
ins
.
op
).
parameter
);
std
::
cout
<<
ins
->
op
.
name
()
<<
std
::
endl
;
results
.
emplace
(
ins
,
trace
(
ins
,
[
&
]
{
return
params
.
at
(
any_cast
<
builtin
::
param
>
(
ins
->
op
).
parameter
);
}));
}
else
if
(
ins
.
op
.
name
()
==
"@outline"
)
else
if
(
ins
->
op
.
name
()
==
"@outline"
)
{
result
=
argument
{
ins
.
result
,
nullptr
};
result
s
.
emplace
(
ins
,
trace
(
ins
,
[
&
]
{
return
argument
{
ins
->
result
,
nullptr
};
}));
}
else
{
std
::
vector
<
argument
>
values
(
ins
.
arguments
.
size
());
std
::
transform
(
ins
.
arguments
.
begin
(),
ins
.
arguments
.
end
(),
values
.
resize
(
ins
->
arguments
.
size
());
std
::
transform
(
ins
->
arguments
.
begin
(),
ins
->
arguments
.
end
(),
values
.
begin
(),
[
&
](
instruction_ref
i
)
{
return
results
.
at
(
std
::
addressof
(
*
i
));
});
// std::cout << "Compute: " << ins.op.name() << std::endl;
result
=
ins
.
op
.
compute
(
this
->
impl
->
ctx
,
ins
.
result
,
values
);
[
&
](
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
);
}));
}
results
.
emplace
(
std
::
addressof
(
ins
)
,
result
);
assert
(
results
.
find
(
ins
)
!=
result
s
.
end
()
);
}
return
result
;
return
result
s
.
at
(
std
::
prev
(
p
.
end
()))
;
}
bool
operator
==
(
const
program
&
x
,
const
program
&
y
)
{
return
to_string
(
x
)
==
to_string
(
y
);
}
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
();
});
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
program
&
p
)
double
common_average
(
const
std
::
vector
<
double
>
&
v
)
{
std
::
unordered_map
<
const
instruction
*
,
std
::
string
>
names
;
int
count
=
0
;
std
::
size_t
n
=
v
.
size
()
/
4
;
double
total
=
std
::
accumulate
(
v
.
begin
()
+
n
,
v
.
end
()
-
n
,
0.0
);
return
total
/
std
::
distance
(
v
.
begin
()
+
n
,
v
.
end
()
-
n
);
}
for
(
auto
&
ins
:
p
.
impl
->
instructions
)
void
program
::
perf_report
(
std
::
ostream
&
os
,
std
::
size_t
n
,
parameter_map
params
)
const
{
using
milliseconds
=
std
::
chrono
::
duration
<
double
,
std
::
milli
>
;
// Run once by itself
eval
(
params
);
// Run and time entire program
std
::
vector
<
double
>
total_vec
;
total_vec
.
reserve
(
n
);
for
(
std
::
size_t
i
=
0
;
i
<
n
;
i
++
)
{
std
::
string
var_name
=
"@"
+
std
::
to_string
(
count
);
if
(
ins
.
op
.
name
()
==
"@param"
)
{
var_name
=
any_cast
<
builtin
::
param
>
(
ins
.
op
).
parameter
;
}
os
<<
var_name
<<
" = "
;
os
<<
ins
.
op
;
if
(
ins
.
op
.
name
()
==
"@literal"
)
{
if
(
ins
.
lit
.
get_shape
().
elements
()
>
10
)
os
<<
"{ ... }"
;
else
os
<<
"{"
<<
ins
.
lit
<<
"}"
;
}
if
(
!
ins
.
arguments
.
empty
()
)
{
char
delim
=
'('
;
for
(
auto
&&
arg
:
ins
.
arguments
)
{
assert
(
p
.
has_instruction
(
arg
)
&&
"Instruction not found"
);
os
<<
delim
<<
names
.
at
(
std
::
addressof
(
*
arg
));
delim
=
','
;
}
os
<<
")"
;
}
total_vec
.
push_back
(
time
<
milliseconds
>
([
&
]
{
eval
(
params
);
})
);
}
std
::
sort
(
total_vec
.
begin
(),
total_vec
.
end
());
std
::
unordered_map
<
instruction_ref
,
std
::
vector
<
double
>>
ins_vec
;
// Fill the map
generic_eval
(
*
this
,
this
->
impl
->
ctx
,
params
,
[
&
](
auto
ins
,
auto
)
{
ins_vec
[
ins
].
reserve
(
n
)
;
return
argument
{};
})
;
// Run and time each instruction
for
(
std
::
size_t
i
=
0
;
i
<
n
;
i
++
)
{
generic_eval
(
*
this
,
this
->
impl
->
ctx
,
params
,
[
&
](
auto
ins
,
auto
f
)
{
argument
result
;
ins_vec
[
ins
].
push_back
(
time
<
milliseconds
>
([
&
]
{
result
=
f
();
}));
return
result
;
}
);
}
for
(
auto
&&
p
:
ins_vec
)
std
::
sort
(
p
.
second
.
begin
(),
p
.
second
.
end
());
// Run and time implicit overhead
std
::
vector
<
double
>
overhead_vec
;
overhead_vec
.
reserve
(
n
);
for
(
std
::
size_t
i
=
0
;
i
<
n
;
i
++
)
{
overhead_vec
.
push_back
(
time
<
milliseconds
>
([
&
]
{
generic_eval
(
*
this
,
this
->
impl
->
ctx
,
params
,
[](
auto
...)
{
return
argument
{};
});
}))
;
}
os
<<
" -> "
<<
ins
.
result
;
double
total_time
=
common_average
(
total_vec
);
double
rate
=
std
::
ceil
(
1000.0
/
total_time
);
double
overhead_time
=
common_average
(
overhead_vec
);
double
overhead_percent
=
overhead_time
*
100.0
/
total_time
;
double
total_instruction_time
=
0.0
;
for
(
auto
&&
p
:
ins_vec
)
total_instruction_time
+=
common_average
(
p
.
second
);
double
calculate_overhead_time
=
total_time
-
total_instruction_time
;
double
calculate_overhead_percent
=
calculate_overhead_time
*
100.0
/
total_time
;
print_program
(
os
,
*
this
,
[
&
](
auto
ins
,
auto
&&
)
{
os
<<
": "
<<
common_average
(
ins_vec
[
ins
])
<<
"ms"
;
});
os
<<
"Rate: "
<<
rate
<<
"/sec"
<<
std
::
endl
;
os
<<
"Total time: "
<<
total_time
<<
"ms"
<<
std
::
endl
;
os
<<
"Total instructions time: "
<<
total_instruction_time
<<
"ms"
<<
std
::
endl
;
os
<<
"Overhead time: "
<<
overhead_time
<<
"ms"
<<
", "
<<
calculate_overhead_time
<<
"ms"
<<
std
::
endl
;
os
<<
"Overhead: "
<<
std
::
round
(
overhead_percent
)
<<
"%"
<<
", "
<<
std
::
round
(
calculate_overhead_percent
)
<<
"%"
<<
std
::
endl
;
}
os
<<
std
::
endl
;
bool
operator
==
(
const
program
&
x
,
const
program
&
y
)
{
return
to_string
(
x
)
==
to_string
(
y
);
}
names
.
emplace
(
std
::
addressof
(
ins
),
var_name
);
count
++
;
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
program
&
p
)
{
print_program
(
os
,
p
,
[](
auto
&&
...)
{});
return
os
;
}
...
...
src/shape.cpp
View file @
038a4c52
...
...
@@ -8,46 +8,90 @@
namespace
migraph
{
shape
::
shape
()
:
m_type
(
float_type
),
m_standard
(
false
)
{}
struct
shape_impl
{
static
std
::
shared_ptr
<
shape_impl
>
default_shape
()
{
static
std
::
shared_ptr
<
shape_impl
>
result
=
std
::
make_shared
<
shape_impl
>
();
return
result
;
}
shape_impl
()
:
m_type
(
shape
::
float_type
),
m_standard
(
false
)
{}
shape_impl
(
shape
::
type_t
t
)
:
m_type
(
t
),
m_lens
({
1
}),
m_strides
({
1
}),
m_standard
(
true
)
{}
shape_impl
(
shape
::
type_t
t
,
std
::
vector
<
std
::
size_t
>
l
)
:
m_type
(
t
),
m_lens
(
std
::
move
(
l
)),
m_standard
(
true
)
{
this
->
calculate_strides
();
assert
(
m_lens
.
size
()
==
m_strides
.
size
());
}
shape_impl
(
shape
::
type_t
t
,
std
::
vector
<
std
::
size_t
>
l
,
std
::
vector
<
std
::
size_t
>
s
)
:
m_type
(
t
),
m_lens
(
std
::
move
(
l
)),
m_strides
(
std
::
move
(
s
))
{
assert
(
m_lens
.
size
()
==
m_strides
.
size
());
assert
(
std
::
any_of
(
m_strides
.
begin
(),
m_strides
.
end
(),
[](
auto
x
)
{
return
x
>
0
;
})
and
"At least one stride must be non-zero"
);
m_standard
=
this
->
elements
()
==
this
->
element_space
()
and
std
::
is_sorted
(
m_strides
.
rbegin
(),
m_strides
.
rend
());
}
shape
::
type_t
m_type
;
std
::
vector
<
std
::
size_t
>
m_lens
;
std
::
vector
<
std
::
size_t
>
m_strides
;
bool
m_standard
;
void
calculate_strides
()
{
m_strides
.
clear
();
m_strides
.
resize
(
m_lens
.
size
(),
0
);
if
(
m_strides
.
empty
())
return
;
m_strides
.
back
()
=
1
;
std
::
partial_sum
(
m_lens
.
rbegin
(),
m_lens
.
rend
()
-
1
,
m_strides
.
rbegin
()
+
1
,
std
::
multiplies
<
std
::
size_t
>
());
}
std
::
size_t
element_space
()
const
{
assert
(
m_lens
.
size
()
==
m_strides
.
size
());
if
(
m_lens
.
empty
())
return
0
;
return
std
::
inner_product
(
m_lens
.
begin
(),
m_lens
.
end
(),
m_strides
.
begin
(),
std
::
size_t
{
0
},
std
::
plus
<
std
::
size_t
>
{},
[](
std
::
size_t
l
,
std
::
size_t
s
)
{
return
(
l
-
1
)
*
s
;
})
+
1
;
}
std
::
size_t
elements
()
const
{
assert
(
m_lens
.
size
()
==
m_strides
.
size
());
if
(
m_lens
.
empty
())
return
0
;
return
std
::
accumulate
(
m_lens
.
begin
(),
m_lens
.
end
(),
std
::
size_t
{
1
},
std
::
multiplies
<
std
::
size_t
>
());
}
};
shape
::
shape
()
:
impl
(
shape_impl
::
default_shape
())
{}
shape
::
shape
(
type_t
t
)
:
m_type
(
t
),
m_lens
({
1
}),
m_strides
({
1
}),
m_standard
(
true
)
{}
shape
::
shape
(
type_t
t
)
:
impl
(
std
::
make_shared
<
shape_impl
>
(
t
)
)
{}
shape
::
shape
(
type_t
t
,
std
::
vector
<
std
::
size_t
>
l
)
:
m_type
(
t
),
m_lens
(
std
::
move
(
l
)),
m_standard
(
true
)
:
impl
(
std
::
make_shared
<
shape_impl
>
(
t
,
std
::
move
(
l
))
)
{
this
->
calculate_strides
();
assert
(
m_lens
.
size
()
==
m_strides
.
size
());
}
shape
::
shape
(
type_t
t
,
std
::
vector
<
std
::
size_t
>
l
,
std
::
vector
<
std
::
size_t
>
s
)
:
m_type
(
t
),
m_lens
(
std
::
move
(
l
)
)
,
m_strides
(
std
::
move
(
s
))
:
impl
(
std
::
make_shared
<
shape_impl
>
(
t
,
std
::
move
(
l
),
std
::
move
(
s
))
)
{
assert
(
m_lens
.
size
()
==
m_strides
.
size
());
assert
(
std
::
any_of
(
m_strides
.
begin
(),
m_strides
.
end
(),
[](
auto
x
)
{
return
x
>
0
;
})
and
"At least one stride must be non-zero"
);
m_standard
=
this
->
packed
()
and
not
this
->
transposed
();
}
void
shape
::
calculate_strides
()
{
m_strides
.
clear
();
m_strides
.
resize
(
m_lens
.
size
(),
0
);
if
(
m_strides
.
empty
())
return
;
m_strides
.
back
()
=
1
;
std
::
partial_sum
(
m_lens
.
rbegin
(),
m_lens
.
rend
()
-
1
,
m_strides
.
rbegin
()
+
1
,
std
::
multiplies
<
std
::
size_t
>
());
}
shape
::
type_t
shape
::
type
()
const
{
return
this
->
m_type
;
}
const
std
::
vector
<
std
::
size_t
>&
shape
::
lens
()
const
{
return
this
->
m_lens
;
}
const
std
::
vector
<
std
::
size_t
>&
shape
::
strides
()
const
{
return
this
->
m_strides
;
}
std
::
size_t
shape
::
elements
()
const
{
assert
(
this
->
lens
().
size
()
==
this
->
strides
().
size
());
if
(
this
->
lens
().
empty
())
return
0
;
return
std
::
accumulate
(
this
->
lens
().
begin
(),
this
->
lens
().
end
(),
std
::
size_t
{
1
},
std
::
multiplies
<
std
::
size_t
>
());
}
shape
::
type_t
shape
::
type
()
const
{
return
impl
->
m_type
;
}
const
std
::
vector
<
std
::
size_t
>&
shape
::
lens
()
const
{
return
impl
->
m_lens
;
}
const
std
::
vector
<
std
::
size_t
>&
shape
::
strides
()
const
{
return
impl
->
m_strides
;
}
std
::
size_t
shape
::
elements
()
const
{
return
impl
->
elements
();
}
std
::
size_t
shape
::
bytes
()
const
{
std
::
size_t
n
=
0
;
...
...
@@ -98,25 +142,13 @@ bool shape::broadcasted() const
std
::
multiplies
<
std
::
size_t
>
())
==
0
;
}
bool
shape
::
standard
()
const
{
return
this
->
m_standard
;
}
bool
shape
::
standard
()
const
{
return
impl
->
m_standard
;
}
std
::
size_t
shape
::
element_space
()
const
{
assert
(
this
->
lens
().
size
()
==
this
->
strides
().
size
());
if
(
this
->
lens
().
empty
())
return
0
;
return
std
::
inner_product
(
this
->
lens
().
begin
(),
this
->
lens
().
end
(),
this
->
strides
().
begin
(),
std
::
size_t
{
0
},
std
::
plus
<
std
::
size_t
>
{},
[](
std
::
size_t
l
,
std
::
size_t
s
)
{
return
(
l
-
1
)
*
s
;
})
+
1
;
}
std
::
size_t
shape
::
element_space
()
const
{
return
impl
->
element_space
();
}
std
::
string
shape
::
type_string
()
const
{
switch
(
this
->
m_
type
)
switch
(
this
->
type
()
)
{
#define MIGRAPH_SHAPE_TYPE_STRING_CASE(x, t) \
case x: return #x;
...
...
src/targets/cpu/cpu_lowering.cpp
View file @
038a4c52
...
...
@@ -7,6 +7,7 @@
#include <migraph/iterator_for.hpp>
#include <migraph/cpu/gemm.hpp>
#include <unordered_map>
#include <utility>
namespace
migraph
{
namespace
cpu
{
...
...
@@ -39,9 +40,9 @@ struct cpu_batch_norm_inference
std
::
string
name
()
const
{
return
"cpu::batch_norm_inference"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
shape
compute_shape
(
const
std
::
vector
<
shape
>
&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
context
&
,
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
argument
output
{
output_shape
};
...
...
@@ -95,7 +96,7 @@ struct cpu_convolution
convolution
op
;
std
::
string
name
()
const
{
return
"cpu::convolution"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
shape
compute_shape
(
const
std
::
vector
<
shape
>
&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
argument
result
{
output_shape
};
...
...
@@ -161,8 +162,8 @@ struct cpu_pooling
pooling
op
;
std
::
string
name
()
const
{
return
"cpu::pooling_"
+
Op
::
name
();
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
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
};
visit_all
(
result
,
args
[
0
])([
&
](
auto
output
,
auto
input
)
{
...
...
@@ -208,8 +209,8 @@ struct cpu_contiguous
{
contiguous
op
;
std
::
string
name
()
const
{
return
"cpu::contiguous"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
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
};
visit_all
(
result
,
args
[
0
])([
&
](
auto
output
,
auto
input
)
{
...
...
@@ -225,9 +226,9 @@ struct cpu_gemm
{
gemm
op
;
std
::
string
name
()
const
{
return
"cpu::gemm"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
shape
compute_shape
(
const
std
::
vector
<
shape
>
&
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
context
&
,
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
argument
result
{
output_shape
};
migemm
(
result
,
args
[
0
],
args
[
1
],
op
.
alpha
,
op
.
beta
);
...
...
@@ -357,8 +358,8 @@ struct cpu_unary
{
Op
op
;
std
::
string
name
()
const
{
return
op
.
name
();
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
return
inputs
.
front
();
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
shape
compute_shape
(
const
std
::
vector
<
shape
>
&
inputs
)
const
{
return
inputs
.
front
();
}
argument
compute
(
context
&
,
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
argument
result
{
output_shape
};
result
.
visit
([
&
](
auto
output
)
{
...
...
@@ -373,8 +374,8 @@ struct cpu_unary
struct
softmax2d
{
std
::
string
name
()
const
{
return
"cpu::softmax2d"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
return
inputs
.
front
();
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
shape
compute_shape
(
const
std
::
vector
<
shape
>
&
inputs
)
const
{
return
inputs
.
front
();
}
argument
compute
(
context
&
,
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
argument
result
{
output_shape
};
visit_all
(
result
,
args
[
0
])([
&
](
auto
output
,
auto
input
)
{
...
...
@@ -449,8 +450,8 @@ struct cpu_binary
{
Op
op
;
std
::
string
name
()
const
{
return
op
.
name
();
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
return
inputs
.
front
();
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
shape
compute_shape
(
const
std
::
vector
<
shape
>
&
inputs
)
const
{
return
inputs
.
front
();
}
argument
compute
(
context
&
,
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
argument
result
{
output_shape
};
visit_all
(
result
,
args
[
0
],
args
[
1
])([
&
](
auto
output
,
auto
input1
,
auto
input2
)
{
...
...
src/targets/gpu/CMakeLists.txt
View file @
038a4c52
...
...
@@ -18,6 +18,7 @@ target_link_libraries(migraph_device migraph hip::device)
target_include_directories
(
migraph_device PUBLIC $<BUILD_INTERFACE:
${
CMAKE_CURRENT_SOURCE_DIR
}
/include>
)
add_library
(
migraph_gpu
eliminate_workspace.cpp
hip.cpp
target.cpp
lowering.cpp
...
...
src/targets/gpu/eliminate_workspace.cpp
0 → 100644
View file @
038a4c52
#include <migraph/gpu/eliminate_workspace.hpp>
#include <migraph/gpu/hip.hpp>
#include <migraph/program.hpp>
#include <migraph/instruction.hpp>
#include <migraph/operators.hpp>
#include <migraph/iterator_for.hpp>
#include <migraph/ranges.hpp>
#include <migraph/stringutils.hpp>
namespace
migraph
{
namespace
gpu
{
void
eliminate_workspace
::
apply
(
program
&
p
)
const
{
std
::
size_t
n
=
0
;
std
::
vector
<
instruction_ref
>
allocs
;
for
(
auto
ins
:
iterator_for
(
p
))
{
if
(
ins
->
output
.
size
()
!=
1
)
continue
;
if
(
ins
->
op
.
name
()
!=
"hip::allocate"
)
continue
;
auto
&&
a
=
any_cast
<
hip_allocate
>
(
ins
->
op
);
if
(
a
.
tag
==
"workspace"
)
{
n
=
std
::
max
(
n
,
ins
->
get_shape
().
bytes
());
allocs
.
push_back
(
ins
);
}
}
auto
ws
=
p
.
add_parameter
(
"workspace"
,
shape
{
shape
::
int8_type
,
{
n
}});
for
(
auto
&&
a
:
allocs
)
{
p
.
replace_instruction
(
a
,
ws
);
p
.
remove_instruction
(
a
);
}
}
}
// namespace gpu
}
// namespace migraph
src/targets/gpu/hip.cpp
View file @
038a4c52
...
...
@@ -13,12 +13,28 @@ using hip_ptr = MIGRAPH_MANAGE_PTR(void, hipFree);
std
::
string
hip_error
(
int
error
)
{
return
hipGetErrorString
(
static_cast
<
hipError_t
>
(
error
));
}
hip_ptr
allocate_gpu
(
std
::
size_t
sz
)
std
::
size_t
get_available_gpu_memory
(
)
{
size_t
free
,
total
;
auto
status
=
hipMemGetInfo
(
&
free
,
&
total
);
if
(
status
!=
hipSuccess
)
MIGRAPH_THROW
(
"Failed getting available memory: "
+
hip_error
(
status
));
return
free
;
}
hip_ptr
allocate_gpu
(
std
::
size_t
sz
,
bool
host
=
false
)
{
if
(
sz
>
get_available_gpu_memory
())
MIGRAPH_THROW
(
"Memory not available to allocate buffer: "
+
std
::
to_string
(
sz
));
void
*
result
;
auto
status
=
hipMalloc
(
&
result
,
sz
);
auto
status
=
host
?
hipHostMalloc
(
&
result
,
sz
)
:
hipMalloc
(
&
result
,
sz
);
if
(
status
!=
hipSuccess
)
MIGRAPH_THROW
(
"Gpu allocation failed: "
+
hip_error
(
status
));
{
if
(
host
)
MIGRAPH_THROW
(
"Gpu allocation failed: "
+
hip_error
(
status
));
else
allocate_gpu
(
sz
,
true
);
}
return
hip_ptr
{
result
};
}
...
...
@@ -40,24 +56,24 @@ std::vector<T> read_from_gpu(const void* x, std::size_t sz)
return
result
;
}
hip_ptr
write_to_gpu
(
const
void
*
x
,
std
::
size_t
sz
)
hip_ptr
write_to_gpu
(
const
void
*
x
,
std
::
size_t
sz
,
bool
host
=
false
)
{
auto
result
=
allocate_gpu
(
sz
);
auto
result
=
allocate_gpu
(
sz
,
host
);
auto
status
=
hipMemcpy
(
result
.
get
(),
x
,
sz
,
hipMemcpyHostToDevice
);
if
(
status
!=
hipSuccess
)
MIGRAPH_THROW
(
"Copy to gpu failed: "
+
hip_error
(
status
));
return
result
;
}
argument
allocate_gpu
(
shape
s
)
argument
allocate_gpu
(
const
shape
&
s
,
bool
host
)
{
auto
p
=
share
(
allocate_gpu
(
s
.
bytes
()
+
1
));
auto
p
=
share
(
allocate_gpu
(
s
.
bytes
()
+
1
,
host
));
return
{
s
,
[
p
]()
mutable
{
return
reinterpret_cast
<
char
*>
(
p
.
get
());
}};
}
argument
to_gpu
(
argument
arg
)
argument
to_gpu
(
argument
arg
,
bool
host
)
{
auto
p
=
share
(
write_to_gpu
(
arg
.
data
(),
arg
.
get_shape
().
bytes
()));
auto
p
=
share
(
write_to_gpu
(
arg
.
data
(),
arg
.
get_shape
().
bytes
()
,
host
));
return
{
arg
.
get_shape
(),
[
p
]()
mutable
{
return
reinterpret_cast
<
char
*>
(
p
.
get
());
}};
}
...
...
src/targets/gpu/include/migraph/gpu/eliminate_workspace.hpp
0 → 100644
View file @
038a4c52
#ifndef MIGRAPH_GUARD_RTGLIB_ELIMINATE_WORKSPACE_HPP
#define MIGRAPH_GUARD_RTGLIB_ELIMINATE_WORKSPACE_HPP
#include <string>
#include <migraph/instruction_ref.hpp>
namespace
migraph
{
struct
program
;
namespace
gpu
{
struct
eliminate_workspace
{
std
::
string
name
()
const
{
return
"eliminate_workspace"
;
}
void
apply
(
program
&
p
)
const
;
};
}
// namespace gpu
}
// namespace migraph
#endif
src/targets/gpu/include/migraph/gpu/hip.hpp
View file @
038a4c52
...
...
@@ -2,25 +2,27 @@
#define MIGRAPH_GUARD_MIGRAPHLIB_HIP_HPP
#include <migraph/operators.hpp>
#include <utility>
namespace
migraph
{
namespace
gpu
{
migraph
::
argument
allocate_gpu
(
migraph
::
shape
s
);
migraph
::
argument
allocate_gpu
(
const
migraph
::
shape
&
s
,
bool
host
=
false
);
migraph
::
argument
to_gpu
(
migraph
::
argument
arg
);
migraph
::
argument
to_gpu
(
migraph
::
argument
arg
,
bool
host
=
false
);
migraph
::
argument
from_gpu
(
migraph
::
argument
arg
);
struct
hip_allocate
{
std
::
string
tag
{};
std
::
string
name
()
const
{
return
"hip::allocate"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
shape
compute_shape
(
const
std
::
vector
<
shape
>
&
inputs
)
const
{
check_shapes
{
inputs
}.
has
(
1
);
return
inputs
.
front
();
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
)
const
argument
compute
(
context
&
,
const
shape
&
output_shape
,
const
std
::
vector
<
argument
>
&
)
const
{
return
allocate_gpu
(
output_shape
);
}
...
...
@@ -29,12 +31,12 @@ struct hip_allocate
struct
hip_write
{
std
::
string
name
()
const
{
return
"hip::write"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
shape
compute_shape
(
const
std
::
vector
<
shape
>
&
inputs
)
const
{
check_shapes
{
inputs
}.
has
(
1
);
return
inputs
.
front
();
}
argument
compute
(
context
&
,
shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
context
&
,
const
shape
&
,
const
std
::
vector
<
argument
>
&
args
)
const
{
return
to_gpu
(
args
.
front
());
}
...
...
src/targets/gpu/lowering.cpp
View file @
038a4c52
...
...
@@ -12,6 +12,7 @@
#include <migraph/iterator_for.hpp>
#include <migraph/gpu/rocblas.hpp>
#include <migraph/gpu/context.hpp>
#include <utility>
namespace
migraph
{
namespace
gpu
{
...
...
@@ -22,14 +23,15 @@ struct miopen_batch_norm_inference
std
::
string
name
()
const
{
return
"gpu::batch_norm_inference"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
shape
compute_shape
(
const
std
::
vector
<
shape
>
&
inputs
)
const
{
check_shapes
{
inputs
,
*
this
}.
has
(
6
);
return
op
.
compute_shape
(
{
inputs
.
at
(
0
),
inputs
.
at
(
1
),
inputs
.
at
(
2
),
inputs
.
at
(
3
),
inputs
.
at
(
4
)});
}
argument
compute
(
context
&
ctx
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
context
&
ctx
,
const
shape
&
output_shape
,
const
std
::
vector
<
argument
>&
args
)
const
{
auto
x_desc
=
make_tensor
(
args
[
0
].
get_shape
());
auto
y_desc
=
make_tensor
(
output_shape
);
...
...
@@ -63,12 +65,13 @@ struct miopen_convolution
miopenConvFwdAlgorithm_t
algo
{};
std
::
string
name
()
const
{
return
"gpu::convolution"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
shape
compute_shape
(
const
std
::
vector
<
shape
>
&
inputs
)
const
{
check_shapes
{
inputs
,
*
this
}.
has
(
4
).
standard
();
return
op
.
compute_shape
({
inputs
.
at
(
0
),
inputs
.
at
(
1
)});
}
argument
compute
(
context
&
ctx
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
context
&
ctx
,
const
shape
&
output_shape
,
const
std
::
vector
<
argument
>&
args
)
const
{
auto
x_desc
=
make_tensor
(
args
[
0
].
get_shape
());
auto
w_desc
=
make_tensor
(
args
[
1
].
get_shape
());
...
...
@@ -91,7 +94,7 @@ struct miopen_convolution
return
args
[
3
];
}
shape
compile
(
context
&
ctx
,
shape
output_shape
,
std
::
vector
<
instruction_ref
>
inputs
)
shape
compile
(
context
&
ctx
,
const
shape
&
output_shape
,
std
::
vector
<
instruction_ref
>
inputs
)
{
shape
workspace_shape
{};
auto
x_desc
=
make_tensor
(
inputs
[
0
]
->
get_shape
());
...
...
@@ -100,7 +103,7 @@ struct miopen_convolution
std
::
size_t
workspace_size
=
0
;
miopenConvolutionForwardGetWorkSpaceSize
(
ctx
.
handle
.
get
(),
x
_desc
.
get
(),
w
_desc
.
get
(),
cd
.
get
(),
y_desc
.
get
(),
&
workspace_size
);
ctx
.
handle
.
get
(),
w
_desc
.
get
(),
x
_desc
.
get
(),
cd
.
get
(),
y_desc
.
get
(),
&
workspace_size
);
workspace_shape
=
shape
{
shape
::
int8_type
,
{
workspace_size
}};
auto
x
=
to_gpu
(
generate_argument
(
inputs
[
0
]
->
get_shape
()));
...
...
@@ -108,7 +111,7 @@ struct miopen_convolution
auto
y
=
to_gpu
(
generate_argument
(
output_shape
));
auto
workspace
=
allocate_gpu
(
workspace_shape
);
int
algo_count
;
int
algo_count
=
1
;
miopenConvAlgoPerf_t
perf
;
miopenFindConvolutionForwardAlgorithm
(
ctx
.
handle
.
get
(),
x_desc
.
get
(),
...
...
@@ -125,7 +128,8 @@ struct miopen_convolution
workspace_size
,
false
);
algo
=
perf
.
fwd_algo
;
return
workspace_shape
;
return
algo
==
miopenConvolutionFwdAlgoWinograd
?
shape
{
shape
::
int8_type
,
{
0
}}
:
workspace_shape
;
}
};
...
...
@@ -135,12 +139,13 @@ struct miopen_pooling
shared
<
pooling_descriptor
>
pd
;
std
::
string
name
()
const
{
return
"gpu::pooling"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
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
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
context
&
ctx
,
const
shape
&
output_shape
,
const
std
::
vector
<
argument
>&
args
)
const
{
auto
x_desc
=
make_tensor
(
args
[
0
].
get_shape
());
auto
y_desc
=
make_tensor
(
output_shape
);
...
...
@@ -166,13 +171,14 @@ struct miopen_pooling
struct
miopen_add
{
std
::
string
name
()
const
{
return
"gpu::add"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
shape
compute_shape
(
const
std
::
vector
<
shape
>
&
inputs
)
const
{
check_shapes
{
inputs
,
*
this
}.
has
(
3
).
not_broadcasted
();
return
inputs
.
at
(
0
);
}
argument
compute
(
context
&
ctx
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
context
&
ctx
,
const
shape
&
output_shape
,
const
std
::
vector
<
argument
>&
args
)
const
{
if
(
args
[
1
].
get_shape
().
broadcasted
())
{
...
...
@@ -213,12 +219,13 @@ struct miopen_gemm
{
gemm
op
;
std
::
string
name
()
const
{
return
"gpu::convolution"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
shape
compute_shape
(
const
std
::
vector
<
shape
>
&
inputs
)
const
{
check_shapes
{
inputs
,
*
this
}.
has
(
3
);
return
op
.
compute_shape
({
inputs
.
at
(
0
),
inputs
.
at
(
1
)});
}
argument
compute
(
context
&
ctx
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
context
&
ctx
,
const
shape
&
output_shape
,
const
std
::
vector
<
argument
>&
args
)
const
{
float
alpha
=
1.0
f
;
float
beta
=
0.0
f
;
...
...
@@ -252,14 +259,14 @@ struct miopen_contiguous
{
contiguous
op
;
std
::
string
name
()
const
{
return
"gpu::contiguous"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
shape
compute_shape
(
const
std
::
vector
<
shape
>
&
inputs
)
const
{
check_shapes
{
inputs
,
*
this
}.
has
(
2
);
return
op
.
compute_shape
({
inputs
.
at
(
0
)});
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
context
&
,
shape
output_shape
,
const
std
::
vector
<
argument
>
&
args
)
const
{
hip_contiguous
(
output_shape
,
args
.
at
(
0
),
args
.
at
(
1
));
hip_contiguous
(
std
::
move
(
output_shape
)
,
args
.
at
(
0
),
args
.
at
(
1
));
return
args
.
at
(
1
);
}
};
...
...
@@ -268,13 +275,14 @@ struct miopen_relu
{
shared
<
activation_descriptor
>
ad
;
std
::
string
name
()
const
{
return
"gpu::relu"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
shape
compute_shape
(
const
std
::
vector
<
shape
>
&
inputs
)
const
{
check_shapes
{
inputs
,
*
this
}.
has
(
2
).
not_broadcasted
();
return
inputs
.
at
(
1
);
}
argument
compute
(
context
&
ctx
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
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
());
...
...
@@ -297,42 +305,50 @@ struct miopen_apply
program
*
prog
=
nullptr
;
context
ctx
{};
void
check_shape
(
shape
x
,
instruction_ref
i
)
{
assert
(
x
==
i
->
get_shape
());
(
void
)
x
;
(
void
)
i
;
}
void
apply
()
{
for
(
auto
it
=
prog
->
begin
();
it
!=
prog
->
end
();
it
++
)
{
auto
s
=
it
->
get_shape
();
if
(
it
->
op
.
name
()
==
"convolution"
)
{
apply_convolution
(
it
);
check_shape
(
s
,
apply_convolution
(
it
)
)
;
}
else
if
(
it
->
op
.
name
()
==
"activation"
)
{
apply_activation
(
it
);
check_shape
(
s
,
apply_activation
(
it
)
)
;
}
else
if
(
it
->
op
.
name
()
==
"pooling"
)
{
apply_pooling
(
it
);
check_shape
(
s
,
apply_pooling
(
it
)
)
;
}
else
if
(
it
->
op
.
name
()
==
"add"
)
{
apply_add
(
it
);
check_shape
(
s
,
apply_add
(
it
)
)
;
}
else
if
(
it
->
op
.
name
()
==
"gemm"
)
{
apply_gemm
(
it
);
check_shape
(
s
,
apply_gemm
(
it
)
)
;
}
else
if
(
it
->
op
.
name
()
==
"contiguous"
)
{
apply_contiguous
(
it
);
check_shape
(
s
,
apply_contiguous
(
it
)
)
;
}
else
if
(
it
->
op
.
name
()
==
"batch_norm_inference"
)
{
apply_batch_norm_inference
(
it
);
check_shape
(
s
,
apply_batch_norm_inference
(
it
)
)
;
}
}
}
instruction_ref
insert_allocation
(
instruction_ref
ins
,
const
shape
&
s
)
instruction_ref
insert_allocation
(
instruction_ref
ins
,
const
shape
&
s
,
std
::
string
tag
=
""
)
{
if
(
ins
==
--
prog
->
end
())
{
...
...
@@ -341,70 +357,71 @@ struct miopen_apply
else
{
auto
is
=
prog
->
add_outline
(
s
);
auto
result
=
prog
->
insert_instruction
(
ins
,
hip_allocate
{},
is
);
auto
result
=
prog
->
insert_instruction
(
ins
,
hip_allocate
{
std
::
move
(
tag
)
},
is
);
return
result
;
}
}
void
apply_convolution
(
instruction_ref
ins
)
instruction_ref
apply_convolution
(
instruction_ref
ins
)
{
auto
&&
op
=
any_cast
<
convolution
>
(
ins
->
op
);
auto
conv
=
miopen_convolution
{
op
,
make_conv
(
op
)};
auto
ws
=
conv
.
compile
(
ctx
,
ins
->
result
,
ins
->
arguments
);
auto
workspace
=
insert_allocation
(
ins
,
ws
);
auto
workspace
=
insert_allocation
(
ins
,
ws
,
"workspace"
);
auto
output
=
insert_allocation
(
ins
,
ins
->
result
);
prog
->
replace_instruction
(
return
prog
->
replace_instruction
(
ins
,
conv
,
ins
->
arguments
.
at
(
0
),
ins
->
arguments
.
at
(
1
),
workspace
,
output
);
}
void
apply_pooling
(
instruction_ref
ins
)
instruction_ref
apply_pooling
(
instruction_ref
ins
)
{
auto
&&
op
=
any_cast
<
pooling
>
(
ins
->
op
);
auto
pd
=
make_pooling
(
op
);
auto
output
=
insert_allocation
(
ins
,
ins
->
result
);
prog
->
replace_instruction
(
return
prog
->
replace_instruction
(
ins
,
miopen_pooling
{
op
,
std
::
move
(
pd
)},
ins
->
arguments
.
at
(
0
),
output
);
}
void
apply_activation
(
instruction_ref
ins
)
instruction_ref
apply_activation
(
instruction_ref
ins
)
{
auto
&&
op
=
any_cast
<
activation
>
(
ins
->
op
);
auto
ad
=
make_relu
();
if
(
op
.
mode
==
"relu"
)
{
auto
output
=
insert_allocation
(
ins
,
ins
->
result
);
prog
->
replace_instruction
(
return
prog
->
replace_instruction
(
ins
,
miopen_relu
{
std
::
move
(
ad
)},
ins
->
arguments
.
at
(
0
),
output
);
}
return
ins
;
}
void
apply_add
(
instruction_ref
ins
)
instruction_ref
apply_add
(
instruction_ref
ins
)
{
auto
output
=
insert_allocation
(
ins
,
ins
->
result
);
prog
->
replace_instruction
(
return
prog
->
replace_instruction
(
ins
,
miopen_add
{},
ins
->
arguments
.
at
(
0
),
ins
->
arguments
.
at
(
1
),
output
);
}
void
apply_gemm
(
instruction_ref
ins
)
instruction_ref
apply_gemm
(
instruction_ref
ins
)
{
auto
&&
op
=
any_cast
<
gemm
>
(
ins
->
op
);
auto
output
=
insert_allocation
(
ins
,
ins
->
result
);
prog
->
replace_instruction
(
return
prog
->
replace_instruction
(
ins
,
miopen_gemm
{
op
},
ins
->
arguments
.
at
(
0
),
ins
->
arguments
.
at
(
1
),
output
);
}
void
apply_contiguous
(
instruction_ref
ins
)
instruction_ref
apply_contiguous
(
instruction_ref
ins
)
{
auto
&&
op
=
any_cast
<
contiguous
>
(
ins
->
op
);
auto
output
=
insert_allocation
(
ins
,
ins
->
result
);
prog
->
replace_instruction
(
ins
,
miopen_contiguous
{
op
},
ins
->
arguments
.
at
(
0
),
output
);
return
prog
->
replace_instruction
(
ins
,
miopen_contiguous
{
op
},
ins
->
arguments
.
at
(
0
),
output
);
}
void
apply_batch_norm_inference
(
instruction_ref
ins
)
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
);
...
...
@@ -416,14 +433,14 @@ struct miopen_apply
ins
->
arguments
.
end
(),
std
::
back_inserter
(
reshapes
),
[
&
](
auto
i
)
{
return
prog
->
insert_instruction
(
ins
,
reshape_op
,
i
);
});
prog
->
replace_instruction
(
ins
,
miopen_batch_norm_inference
{
op
},
ins
->
arguments
.
at
(
0
),
reshapes
[
0
],
reshapes
[
1
],
reshapes
[
2
],
reshapes
[
3
],
output
);
return
prog
->
replace_instruction
(
ins
,
miopen_batch_norm_inference
{
op
},
ins
->
arguments
.
at
(
0
),
reshapes
[
0
],
reshapes
[
1
],
reshapes
[
2
],
reshapes
[
3
],
output
);
}
};
...
...
src/targets/gpu/target.cpp
View file @
038a4c52
...
...
@@ -2,6 +2,7 @@
#include <migraph/gpu/lowering.hpp>
#include <migraph/gpu/write_literals.hpp>
#include <migraph/gpu/context.hpp>
#include <migraph/gpu/eliminate_workspace.hpp>
#include <migraph/check_context.hpp>
#include <migraph/auto_contiguous.hpp>
#include <migraph/dead_code_elimination.hpp>
...
...
@@ -22,9 +23,9 @@ std::vector<pass> target::get_passes(migraph::context& gctx) const
//simplify_reshapes{},
//dead_code_elimination{},
lowering
{
ctx
},
//
eliminate_
contiguous
{},
//dead_code_elimination
{},
//writ
e_li
terals
{},
eliminate_
workspace
{},
eliminate_contiguous
{},
dead_cod
e_
e
li
mination
{},
write_literals
{},
//check_context<context>{},
dead_code_elimination
{}
...
...
test/cpu_ops_test.cpp
View file @
038a4c52
...
...
@@ -604,10 +604,8 @@ void transpose_test()
auto
result
=
p
.
eval
({});
result
.
visit
([
&
](
auto
output
)
{
std
::
vector
<
size_t
>
new_lens
=
{
1
,
3
,
2
,
2
};
std
::
vector
<
size_t
>
new_strides
=
{
12
,
1
,
6
,
3
};
std
::
vector
<
size_t
>
new_lens
=
{
1
,
3
,
2
,
2
};
EXPECT
(
bool
{
output
.
get_shape
().
lens
()
==
new_lens
});
EXPECT
(
bool
{
output
.
get_shape
().
strides
()
==
new_strides
});
});
}
{
...
...
test/gpu/miopen.cpp
View file @
038a4c52
...
...
@@ -104,6 +104,7 @@ void verify_program()
visit_all
(
cpu_arg_f
.
get
(),
gpu_arg
)([](
auto
cpu
,
auto
gpu
)
{
if
(
not
migraph
::
verify_range
(
cpu
,
gpu
))
{
// TODO: Check for nans
std
::
cout
<<
"FAILED: "
<<
migraph
::
get_type_name
<
V
>
()
<<
std
::
endl
;
}
});
...
...
@@ -272,6 +273,29 @@ struct test_transpose
}
};
struct
test_batchnorm_inference_2
{
const
size_t
width
=
14
;
const
size_t
height
=
14
;
const
size_t
channels
=
256
;
const
size_t
batches
=
1
;
migraph
::
program
create_program
()
const
{
migraph
::
program
p
;
migraph
::
shape
s
{
migraph
::
shape
::
float_type
,
{
batches
,
channels
,
height
,
width
}};
migraph
::
shape
vars
{
migraph
::
shape
::
float_type
,
{
channels
}};
auto
x
=
p
.
add_parameter
(
"x"
,
s
);
auto
mean
=
p
.
add_parameter
(
"mean"
,
vars
);
auto
variance
=
p
.
add_parameter
(
"variance"
,
vars
);
auto
scale
=
p
.
add_parameter
(
"scale"
,
vars
);
auto
bias
=
p
.
add_parameter
(
"bias"
,
vars
);
p
.
add_instruction
(
migraph
::
batch_norm_inference
{},
x
,
mean
,
variance
,
scale
,
bias
);
return
p
;
}
};
struct
test_batchnorm_inference
{
const
size_t
width
=
3
;
...
...
@@ -309,4 +333,5 @@ int main()
verify_program
<
test_contiguous
>
();
verify_program
<
test_transpose
>
();
verify_program
<
test_batchnorm_inference
>
();
verify_program
<
test_batchnorm_inference_2
>
();
}
test/include/basic_ops.hpp
View file @
038a4c52
...
...
@@ -6,7 +6,7 @@ struct sum_op
{
std
::
string
name
()
const
{
return
"sum"
;
}
migraph
::
argument
compute
(
migraph
::
context
&
,
migraph
::
shape
,
std
::
vector
<
migraph
::
argument
>
args
)
const
compute
(
migraph
::
context
&
,
const
migraph
::
shape
&
,
std
::
vector
<
migraph
::
argument
>
args
)
const
{
migraph
::
argument
result
;
if
(
args
.
size
()
!=
2
)
...
...
@@ -36,7 +36,7 @@ struct minus_op
{
std
::
string
name
()
const
{
return
"minus"
;
}
migraph
::
argument
compute
(
migraph
::
context
&
,
migraph
::
shape
,
std
::
vector
<
migraph
::
argument
>
args
)
const
compute
(
migraph
::
context
&
,
const
migraph
::
shape
&
,
std
::
vector
<
migraph
::
argument
>
args
)
const
{
migraph
::
argument
result
;
if
(
args
.
size
()
!=
2
)
...
...
@@ -66,7 +66,7 @@ struct pass_op
{
std
::
string
name
()
const
{
return
"pass"
;
}
migraph
::
argument
compute
(
migraph
::
context
&
,
migraph
::
shape
,
std
::
vector
<
migraph
::
argument
>
args
)
const
compute
(
migraph
::
context
&
,
const
migraph
::
shape
&
,
std
::
vector
<
migraph
::
argument
>
args
)
const
{
if
(
args
.
empty
())
return
{};
...
...
@@ -85,7 +85,7 @@ struct pass_standard_op
{
std
::
string
name
()
const
{
return
"pass"
;
}
migraph
::
argument
compute
(
migraph
::
context
&
,
migraph
::
shape
,
std
::
vector
<
migraph
::
argument
>
args
)
const
compute
(
migraph
::
context
&
,
const
migraph
::
shape
&
,
std
::
vector
<
migraph
::
argument
>
args
)
const
{
if
(
args
.
empty
())
return
{};
...
...
@@ -109,12 +109,12 @@ struct nop
{
std
::
string
name
()
const
{
return
"nop"
;
}
migraph
::
argument
compute
(
migraph
::
context
&
,
migraph
::
shape
,
std
::
vector
<
migraph
::
argument
>
)
const
compute
(
migraph
::
context
&
,
const
migraph
::
shape
&
,
const
std
::
vector
<
migraph
::
argument
>
&
)
const
{
return
{};
}
migraph
::
shape
compute_shape
(
std
::
vector
<
migraph
::
shape
>
)
const
{
return
{};
}
migraph
::
shape
compute_shape
(
const
std
::
vector
<
migraph
::
shape
>
&
)
const
{
return
{};
}
};
inline
migraph
::
literal
get_2x2
()
...
...
test/include/test.hpp
View file @
038a4c52
...
...
@@ -141,7 +141,7 @@ bool throws(F f)
}
template
<
class
F
,
class
Exception
>
bool
throws
(
F
f
,
std
::
string
msg
=
""
)
bool
throws
(
F
f
,
const
std
::
string
&
msg
=
""
)
{
try
{
...
...
test/op_shape_test.cpp
0 → 100644
View file @
038a4c52
#include <migraph/program.hpp>
#include <migraph/iterator_for.hpp>
#include <migraph/instruction.hpp>
#include <migraph/operators.hpp>
#include <sstream>
#include "test.hpp"
template
<
class
...
Ts
>
void
expect_shape
(
const
migraph
::
shape
&
expected
,
const
migraph
::
operation
&
op
,
Ts
...
xs
)
{
migraph
::
program
p
;
std
::
vector
<
migraph
::
shape
>
shapes
{
xs
...};
std
::
vector
<
migraph
::
instruction_ref
>
args
(
shapes
.
size
());
std
::
transform
(
shapes
.
begin
(),
shapes
.
end
(),
args
.
begin
(),
[
&
](
auto
&&
s
)
{
return
p
.
add_outline
(
s
);
});
p
.
add_instruction
(
op
,
args
);
if
(
p
.
get_shape
()
!=
expected
)
{
std
::
cout
<<
"FAILED: Incorrect shape for "
<<
op
.
name
()
<<
": "
;
std
::
cout
<<
expected
<<
" != "
<<
p
.
get_shape
()
<<
std
::
endl
;
for
(
auto
&&
s
:
shapes
)
std
::
cout
<<
" "
<<
s
<<
std
::
endl
;
}
}
template
<
class
...
Ts
>
void
throws_shape
(
const
migraph
::
operation
&
op
,
Ts
...
xs
)
{
migraph
::
program
p
;
std
::
vector
<
migraph
::
shape
>
shapes
{
xs
...};
std
::
vector
<
migraph
::
instruction_ref
>
args
(
shapes
.
size
());
std
::
transform
(
shapes
.
begin
(),
shapes
.
end
(),
args
.
begin
(),
[
&
](
auto
&&
s
)
{
return
p
.
add_outline
(
s
);
});
bool
thrown
=
test
::
throws
([
&
]
{
p
.
add_instruction
(
op
,
args
);
});
if
(
not
thrown
)
{
std
::
cout
<<
"FAILED: No error found for "
<<
op
.
name
()
<<
": "
;
for
(
auto
&&
s
:
shapes
)
std
::
cout
<<
" "
<<
s
<<
std
::
endl
;
}
}
template
<
class
...
>
struct
always_false
:
std
::
false_type
{
};
template
<
class
...
Ts
>
void
throws_shape
(
const
migraph
::
shape
&
,
Ts
...)
{
static_assert
(
always_false
<
Ts
...
>
{},
"An expected shape should not be passed to throws_shape function"
);
}
void
batch_norm_inference_shape
()
{
const
size_t
channels
=
3
;
migraph
::
shape
s
{
migraph
::
shape
::
float_type
,
{
4
,
channels
,
3
,
3
}};
migraph
::
shape
vars
{
migraph
::
shape
::
float_type
,
{
channels
}};
expect_shape
(
s
,
migraph
::
batch_norm_inference
{},
s
,
vars
,
vars
,
vars
,
vars
);
throws_shape
(
migraph
::
batch_norm_inference
{},
s
);
throws_shape
(
migraph
::
batch_norm_inference
{},
s
,
vars
,
vars
,
vars
,
vars
,
vars
);
}
void
convolution_shape
()
{
migraph
::
shape
output
{
migraph
::
shape
::
float_type
,
{
4
,
4
,
1
,
1
}};
migraph
::
shape
input
{
migraph
::
shape
::
float_type
,
{
4
,
3
,
3
,
3
}};
migraph
::
shape
weights
{
migraph
::
shape
::
float_type
,
{
4
,
3
,
3
,
3
}};
expect_shape
(
output
,
migraph
::
convolution
{},
input
,
weights
);
throws_shape
(
migraph
::
convolution
{},
input
);
migraph
::
shape
input2
{
migraph
::
shape
::
float_type
,
{
3
,
3
}};
migraph
::
shape
weights2
{
migraph
::
shape
::
float_type
,
{
3
,
3
}};
throws_shape
(
migraph
::
convolution
{},
input2
,
weights2
);
throws_shape
(
migraph
::
convolution
{},
input2
,
weights
);
}
void
transpose_shape
()
{
migraph
::
shape
input
{
migraph
::
shape
::
float_type
,
{
2
,
2
}};
migraph
::
shape
output
{
migraph
::
shape
::
float_type
,
{
2
,
2
},
{
1
,
2
}};
expect_shape
(
input
,
migraph
::
transpose
{{
0
,
1
}},
input
);
expect_shape
(
output
,
migraph
::
transpose
{{
1
,
0
}},
input
);
throws_shape
(
migraph
::
transpose
{{
1
,
2
}},
input
);
}
void
contiguous_shape
()
{
migraph
::
shape
output
{
migraph
::
shape
::
float_type
,
{
2
,
2
}};
migraph
::
shape
input
{
migraph
::
shape
::
float_type
,
{
2
,
2
},
{
1
,
2
}};
expect_shape
(
output
,
migraph
::
contiguous
{},
input
);
throws_shape
(
migraph
::
contiguous
{},
input
,
input
);
migraph
::
shape
single
{
migraph
::
shape
::
float_type
,
{
2
}};
throws_shape
(
migraph
::
contiguous
{},
single
);
}
void
reshape_shape
()
{
migraph
::
shape
input
{
migraph
::
shape
::
float_type
,
{
24
,
1
,
1
,
1
}};
for
(
auto
&&
new_shape
:
std
::
vector
<
std
::
vector
<
int64_t
>>
{{
8
,
3
,
1
,
1
},
{
1
,
3
,
4
,
2
},
{
1
,
3
,
4
,
2
}})
{
std
::
vector
<
std
::
size_t
>
lens
(
new_shape
.
size
());
std
::
copy
(
new_shape
.
begin
(),
new_shape
.
end
(),
lens
.
begin
());
migraph
::
shape
output
{
migraph
::
shape
::
float_type
,
lens
};
expect_shape
(
output
,
migraph
::
reshape
{
new_shape
},
input
);
}
for
(
auto
&&
new_shape
:
std
::
vector
<
std
::
vector
<
int64_t
>>
{{
8
,
3
,
2
,
2
},
{
1
,
3
,
-
1
,
-
1
}})
{
throws_shape
(
migraph
::
reshape
{
new_shape
},
input
);
}
}
void
flatten_shape
()
{
migraph
::
shape
input
{
migraph
::
shape
::
float_type
,
{
2
,
4
,
6
,
8
}};
expect_shape
(
migraph
::
shape
{
migraph
::
shape
::
float_type
,
{
1
,
2
*
4
*
6
*
8
}},
migraph
::
flatten
{
0
},
input
);
expect_shape
(
migraph
::
shape
{
migraph
::
shape
::
float_type
,
{
2
,
4
*
6
*
8
}},
migraph
::
flatten
{
1
},
input
);
expect_shape
(
migraph
::
shape
{
migraph
::
shape
::
float_type
,
{
2
*
4
,
6
*
8
}},
migraph
::
flatten
{
2
},
input
);
expect_shape
(
migraph
::
shape
{
migraph
::
shape
::
float_type
,
{
2
*
4
*
6
,
8
}},
migraph
::
flatten
{
3
},
input
);
expect_shape
(
migraph
::
shape
{
migraph
::
shape
::
float_type
,
{
2
*
4
*
6
*
8
,
1
}},
migraph
::
flatten
{
4
},
input
);
throws_shape
(
migraph
::
flatten
{
5
},
input
);
}
int
main
()
{
batch_norm_inference_shape
();
convolution_shape
();
transpose_shape
();
contiguous_shape
();
reshape_shape
();
flatten_shape
();
}
test/operation.cpp
View file @
038a4c52
...
...
@@ -8,12 +8,12 @@ struct simple_operation
{
int
data
=
1
;
std
::
string
name
()
const
{
return
"simple"
;
}
migraph
::
shape
compute_shape
(
std
::
vector
<
migraph
::
shape
>
)
const
migraph
::
shape
compute_shape
(
const
std
::
vector
<
migraph
::
shape
>
&
)
const
{
MIGRAPH_THROW
(
"not computable"
);
}
migraph
::
argument
compute
(
migraph
::
context
&
,
migraph
::
shape
,
std
::
vector
<
migraph
::
argument
>
)
const
compute
(
migraph
::
context
&
,
const
migraph
::
shape
&
,
const
std
::
vector
<
migraph
::
argument
>
&
)
const
{
MIGRAPH_THROW
(
"not computable"
);
}
...
...
@@ -27,12 +27,12 @@ struct simple_operation
struct
simple_operation_no_print
{
std
::
string
name
()
const
{
return
"simple"
;
}
migraph
::
shape
compute_shape
(
std
::
vector
<
migraph
::
shape
>
)
const
migraph
::
shape
compute_shape
(
const
std
::
vector
<
migraph
::
shape
>
&
)
const
{
MIGRAPH_THROW
(
"not computable"
);
}
migraph
::
argument
compute
(
migraph
::
context
&
,
migraph
::
shape
,
std
::
vector
<
migraph
::
argument
>
)
const
compute
(
migraph
::
context
&
,
const
migraph
::
shape
&
,
const
std
::
vector
<
migraph
::
argument
>
&
)
const
{
MIGRAPH_THROW
(
"not computable"
);
}
...
...
Prev
1
2
3
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