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
76f68df4
"src/module.cpp" did not exist on "8d21fdc9dd58e62192d9408132585eea94bbf79b"
Commit
76f68df4
authored
Jul 19, 2018
by
wsttiger
Browse files
Merged from master
parents
dc0c4810
8ae3ffea
Changes
35
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
928 additions
and
553 deletions
+928
-553
requirements.txt
requirements.txt
+1
-0
src/generate.cpp
src/generate.cpp
+13
-2
src/include/migraph/auto_any_cast.hpp
src/include/migraph/auto_any_cast.hpp
+37
-0
src/include/migraph/context.hpp
src/include/migraph/context.hpp
+6
-0
src/include/migraph/generate.hpp
src/include/migraph/generate.hpp
+4
-1
src/include/migraph/instruction.hpp
src/include/migraph/instruction.hpp
+1
-0
src/include/migraph/operation.hpp
src/include/migraph/operation.hpp
+8
-1
src/include/migraph/operators.hpp
src/include/migraph/operators.hpp
+20
-0
src/include/migraph/shape.hpp
src/include/migraph/shape.hpp
+5
-0
src/include/migraph/tensor_view.hpp
src/include/migraph/tensor_view.hpp
+2
-0
src/onnx/CMakeLists.txt
src/onnx/CMakeLists.txt
+4
-0
src/onnx/mnist.cpp
src/onnx/mnist.cpp
+141
-0
src/onnx/onnx.cpp
src/onnx/onnx.cpp
+39
-3
src/onnx/verify_onnx.cpp
src/onnx/verify_onnx.cpp
+1
-1
src/targets/cpu/CMakeLists.txt
src/targets/cpu/CMakeLists.txt
+1
-0
src/targets/cpu/cpu_lowering.cpp
src/targets/cpu/cpu_lowering.cpp
+595
-0
src/targets/cpu/cpu_target.cpp
src/targets/cpu/cpu_target.cpp
+2
-543
src/targets/cpu/include/migraph/cpu/cpu_lowering.hpp
src/targets/cpu/include/migraph/cpu/cpu_lowering.hpp
+19
-0
src/targets/miopen/CMakeLists.txt
src/targets/miopen/CMakeLists.txt
+9
-2
src/targets/miopen/include/migraph/miopen/context.hpp
src/targets/miopen/include/migraph/miopen/context.hpp
+20
-0
No files found.
requirements.txt
View file @
76f68df4
google/protobuf
-DCMAKE_POSITION_INDEPENDENT_CODE=On
RadeonOpenCompute/rocm-cmake@3f43e2d493f24abbab4dc189a9ab12cc3ad33baf
--build
ROCmSoftwarePlatform/MIOpen,http://gitlab1.amd.com/pfultz/miopen/-/archive/57dd8372fa043f4bb500ac297f2c479e1c819e89/miopen-57dd8372fa043f4bb500ac297f2c479e1c819e89.tar.bz2
-DMIOPEN_CACHE_DIR=""
ROCmSoftwarePlatform/rocBLAS@v14.0.1
src/generate.cpp
View file @
76f68df4
...
...
@@ -2,9 +2,9 @@
namespace
migraph
{
migraph
::
argument
generate_argument
(
migraph
::
shape
s
,
std
::
mt19937
::
result_type
seed
)
argument
generate_argument
(
shape
s
,
std
::
mt19937
::
result_type
seed
)
{
migraph
::
argument
result
;
argument
result
;
s
.
visit_type
([
&
](
auto
as
)
{
using
type
=
typename
decltype
(
as
)
::
type
;
auto
v
=
generate_tensor_data
<
type
>
(
s
,
seed
);
...
...
@@ -13,4 +13,15 @@ migraph::argument generate_argument(migraph::shape s, std::mt19937::result_type
return
result
;
}
literal
generate_literal
(
shape
s
,
std
::
mt19937
::
result_type
seed
)
{
literal
result
;
s
.
visit_type
([
&
](
auto
as
)
{
using
type
=
typename
decltype
(
as
)
::
type
;
auto
v
=
generate_tensor_data
<
type
>
(
s
,
seed
);
result
=
{
s
,
v
};
});
return
result
;
}
}
// namespace migraph
src/include/migraph/auto_any_cast.hpp
0 → 100644
View file @
76f68df4
#ifndef MIGRAPH_GUARD_RTGLIB_AUTO_ANY_CAST_HPP
#define MIGRAPH_GUARD_RTGLIB_AUTO_ANY_CAST_HPP
namespace
migraph
{
namespace
detail
{
template
<
class
U
>
void
any_cast
()
{
}
template
<
class
T
>
struct
auto_any_caster
{
T
&
x
;
template
<
class
U
>
operator
U
&
()
{
return
any_cast
<
U
>
(
x
);
}
operator
T
&
()
{
return
x
;
}
};
}
// namespace detail
template
<
class
T
>
detail
::
auto_any_caster
<
T
>
auto_any_cast
(
T
&
x
)
{
return
{
x
};
}
}
// namespace migraph
#endif
src/include/migraph/context.hpp
View file @
76f68df4
#ifndef MIGRAPH_GUARD_CONTEXT_HPP
#define MIGRAPH_GUARD_CONTEXT_HPP
#include <string>
#include <functional>
#include <memory>
#include <type_traits>
#include <utility>
namespace
migraph
{
/*
...
...
src/include/migraph/generate.hpp
View file @
76f68df4
...
...
@@ -2,6 +2,7 @@
#define MIGRAPH_GUARD_MIGRAPHLIB_GENERATE_HPP
#include <migraph/argument.hpp>
#include <migraph/literal.hpp>
#include <random>
namespace
migraph
{
...
...
@@ -16,7 +17,9 @@ std::vector<T> generate_tensor_data(migraph::shape s, std::mt19937::result_type
return
result
;
}
migraph
::
argument
generate_argument
(
migraph
::
shape
s
,
std
::
mt19937
::
result_type
seed
=
0
);
argument
generate_argument
(
shape
s
,
std
::
mt19937
::
result_type
seed
=
0
);
literal
generate_literal
(
shape
s
,
std
::
mt19937
::
result_type
seed
=
0
);
}
// namespace migraph
...
...
src/include/migraph/instruction.hpp
View file @
76f68df4
...
...
@@ -5,6 +5,7 @@
#include <migraph/shape.hpp>
#include <migraph/builtin.hpp>
#include <migraph/instruction_ref.hpp>
#include <migraph/operation.hpp>
#include <migraph/erase.hpp>
#include <string>
...
...
src/include/migraph/operation.hpp
View file @
76f68df4
...
...
@@ -9,6 +9,7 @@
#include <migraph/shape.hpp>
#include <migraph/argument.hpp>
#include <migraph/context.hpp>
#include <migraph/auto_any_cast.hpp>
namespace
migraph
{
...
...
@@ -22,6 +23,12 @@ auto operator<<(std::ostream& os, const T& x) -> decltype(os << x.name())
}
// namespace operation_stream
template
<
class
T
>
argument
compute_op
(
const
T
&
x
,
context
&
ctx
,
shape
output_shape
,
std
::
vector
<
argument
>
input
)
{
return
x
.
compute
(
auto_any_cast
(
ctx
),
output_shape
,
input
);
}
/*
* Type-erased interface for:
*
...
...
@@ -169,7 +176,7 @@ struct operation
argument
compute
(
context
&
ctx
,
shape
output
,
std
::
vector
<
argument
>
input
)
const
override
{
return
private_detail_te_value
.
compute
(
ctx
,
std
::
move
(
output
),
std
::
move
(
input
));
return
compute_op
(
private_detail_te_value
,
ctx
,
std
::
move
(
output
),
std
::
move
(
input
));
}
std
::
ostream
&
operator_shift_left
(
std
::
ostream
&
os
)
const
override
...
...
src/include/migraph/operators.hpp
View file @
76f68df4
...
...
@@ -103,6 +103,24 @@ struct not_computable
}
};
struct
batch_norm_inference
{
double
epsilon
=
1.0e-6
;
std
::
string
name
()
const
{
return
"batch_norm_inference"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
check_shapes
{
inputs
,
*
this
}.
has
(
5
);
return
inputs
.
front
();
}
argument
compute
(
context
&
,
shape
,
std
::
vector
<
argument
>
)
const
{
MIGRAPH_THROW
(
"not computable"
);
}
};
struct
convolution
{
std
::
array
<
std
::
size_t
,
2
>
padding
=
{{
0
,
0
}};
...
...
@@ -193,6 +211,7 @@ struct pooling
std
::
array
<
std
::
size_t
,
2
>
stride
=
{{
1
,
1
}};
std
::
array
<
std
::
size_t
,
2
>
lengths
=
{{
1
,
1
}};
std
::
string
name
()
const
{
return
"pooling"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
check_shapes
{
inputs
,
*
this
}.
has
(
1
).
only_dims
(
4
);
...
...
@@ -474,6 +493,7 @@ struct broadcast
auto
input
=
inputs
.
at
(
1
);
std
::
vector
<
size_t
>
bcast_strides
(
result
.
lens
().
size
(),
0
);
if
(
std
::
all_of
(
result
.
lens
().
cbegin
(),
result
.
lens
().
cend
(),
[
&
](
auto
x
)
{
return
x
==
1
;
}))
{
...
...
src/include/migraph/shape.hpp
View file @
76f68df4
...
...
@@ -45,6 +45,11 @@ struct shape
MIGRAPH_SHAPE_VISIT_TYPES
(
MIGRAPH_SHAPE_GET_TYPE
)
#undef MIGRAPH_SHAPE_GET_TYPE
template
<
class
T
>
struct
get_type
<
const
T
>
:
get_type
<
T
>
{
};
shape
();
shape
(
type_t
t
);
shape
(
type_t
t
,
std
::
vector
<
std
::
size_t
>
l
);
...
...
src/include/migraph/tensor_view.hpp
View file @
76f68df4
...
...
@@ -29,12 +29,14 @@ struct tensor_view
template
<
class
...
Ts
,
MIGRAPH_REQUIRES
(
std
::
is_integral
<
Ts
>{}...)
>
const
T
&
operator
()(
Ts
...
xs
)
const
{
assert
(
m_shape
.
index
({
static_cast
<
std
::
size_t
>
(
xs
)...})
<
m_shape
.
bytes
()
/
sizeof
(
T
));
return
m_data
[
m_shape
.
index
({
static_cast
<
std
::
size_t
>
(
xs
)...})];
}
template
<
class
...
Ts
,
MIGRAPH_REQUIRES
(
std
::
is_integral
<
Ts
>{}...)
>
T
&
operator
()(
Ts
...
xs
)
{
assert
(
m_shape
.
index
({
static_cast
<
std
::
size_t
>
(
xs
)...})
<
m_shape
.
bytes
()
/
sizeof
(
T
));
return
m_data
[
m_shape
.
index
({
static_cast
<
std
::
size_t
>
(
xs
)...})];
}
...
...
src/onnx/CMakeLists.txt
View file @
76f68df4
...
...
@@ -16,6 +16,10 @@ add_executable(read_onnx read_onnx.cpp)
rocm_clang_tidy_check
(
read_onnx
)
target_link_libraries
(
read_onnx migraph_onnx
)
add_executable
(
mnist mnist.cpp
)
rocm_clang_tidy_check
(
mnist
)
target_link_libraries
(
mnist migraph_cpu migraph_onnx
)
if
(
MIGRAPH_ENABLE_MIOPEN
)
add_executable
(
verify_onnx verify_onnx.cpp
)
rocm_clang_tidy_check
(
verify_onnx
)
...
...
src/onnx/mnist.cpp
0 → 100644
View file @
76f68df4
#include <cstdio>
#include <string>
#include <fstream>
#include <numeric>
#include <stdexcept>
#include <migraph/onnx.hpp>
#include <migraph/cpu/cpu_target.hpp>
#include <migraph/generate.hpp>
auto
reverse_int
(
unsigned
int
i
)
{
unsigned
char
c1
,
c2
,
c3
,
c4
;
c1
=
i
&
255u
;
c2
=
(
i
>>
8u
)
&
255u
;
c3
=
(
i
>>
16u
)
&
255u
;
c4
=
(
i
>>
24u
)
&
255u
;
return
(
static_cast
<
unsigned
int
>
(
c1
)
<<
24u
)
+
(
static_cast
<
unsigned
int
>
(
c2
)
<<
16u
)
+
(
static_cast
<
unsigned
int
>
(
c3
)
<<
8u
)
+
c4
;
};
std
::
vector
<
float
>
read_mnist_images
(
std
::
string
full_path
,
int
&
number_of_images
,
int
&
image_size
)
{
using
uchar
=
unsigned
char
;
std
::
ifstream
file
(
full_path
,
std
::
ios
::
binary
);
if
(
file
.
is_open
())
{
int
magic_number
=
0
,
n_rows
=
0
,
n_cols
=
0
;
file
.
read
(
reinterpret_cast
<
char
*>
(
&
magic_number
),
sizeof
(
magic_number
));
magic_number
=
reverse_int
(
magic_number
);
if
(
magic_number
!=
2051
)
throw
std
::
runtime_error
(
"Invalid MNIST image file!"
);
file
.
read
(
reinterpret_cast
<
char
*>
(
&
number_of_images
),
sizeof
(
number_of_images
));
number_of_images
=
reverse_int
(
number_of_images
);
file
.
read
(
reinterpret_cast
<
char
*>
(
&
n_rows
),
sizeof
(
n_rows
));
n_rows
=
reverse_int
(
n_rows
);
file
.
read
(
reinterpret_cast
<
char
*>
(
&
n_cols
),
sizeof
(
n_cols
));
n_cols
=
reverse_int
(
n_cols
);
image_size
=
n_rows
*
n_cols
;
std
::
vector
<
float
>
result
(
number_of_images
*
image_size
);
for
(
int
i
=
0
;
i
<
number_of_images
;
i
++
)
{
for
(
int
j
=
0
;
j
<
image_size
;
j
++
)
{
uchar
tmp
;
file
.
read
(
reinterpret_cast
<
char
*>
(
&
tmp
),
1
);
result
[
i
*
image_size
+
j
]
=
tmp
/
255.0
;
}
}
return
result
;
}
else
{
throw
std
::
runtime_error
(
"Cannot open file `"
+
full_path
+
"`!"
);
}
}
std
::
vector
<
int32_t
>
read_mnist_labels
(
std
::
string
full_path
,
int
&
number_of_labels
)
{
using
uchar
=
unsigned
char
;
std
::
ifstream
file
(
full_path
,
std
::
ios
::
binary
);
if
(
file
.
is_open
())
{
int
magic_number
=
0
;
file
.
read
(
reinterpret_cast
<
char
*>
(
&
magic_number
),
sizeof
(
magic_number
));
magic_number
=
reverse_int
(
magic_number
);
if
(
magic_number
!=
2049
)
throw
std
::
runtime_error
(
"Invalid MNIST label file!"
);
file
.
read
(
reinterpret_cast
<
char
*>
(
&
number_of_labels
),
sizeof
(
number_of_labels
));
number_of_labels
=
reverse_int
(
number_of_labels
);
std
::
vector
<
int32_t
>
result
(
number_of_labels
);
for
(
int
i
=
0
;
i
<
number_of_labels
;
i
++
)
{
uchar
tmp
;
file
.
read
(
reinterpret_cast
<
char
*>
(
&
tmp
),
1
);
result
[
i
]
=
tmp
;
}
return
result
;
}
else
{
throw
std
::
runtime_error
(
"Unable to open file `"
+
full_path
+
"`!"
);
}
}
std
::
vector
<
float
>
softmax
(
std
::
vector
<
float
>
p
)
{
size_t
n
=
p
.
size
();
std
::
vector
<
float
>
result
(
n
);
std
::
transform
(
p
.
begin
(),
p
.
end
(),
result
.
begin
(),
[](
auto
x
)
{
return
std
::
exp
(
x
);
});
float
s
=
std
::
accumulate
(
result
.
begin
(),
result
.
end
(),
0.0
f
,
std
::
plus
<
float
>
());
std
::
transform
(
result
.
begin
(),
result
.
end
(),
result
.
begin
(),
[
=
](
auto
x
)
{
return
x
/
s
;
});
return
result
;
}
int
main
(
int
argc
,
char
const
*
argv
[])
{
if
(
argc
>
3
)
{
std
::
string
datafile
=
argv
[
2
];
std
::
string
labelfile
=
argv
[
3
];
int
nimages
=
-
1
;
int
image_size
=
-
1
;
int
nlabels
=
-
1
;
std
::
vector
<
float
>
input
=
read_mnist_images
(
datafile
,
nimages
,
image_size
);
std
::
vector
<
int32_t
>
labels
=
read_mnist_labels
(
labelfile
,
nlabels
);
std
::
string
file
=
argv
[
1
];
auto
prog
=
migraph
::
parse_onnx
(
file
);
prog
.
compile
(
migraph
::
cpu
::
cpu_target
{});
auto
s
=
migraph
::
shape
{
migraph
::
shape
::
float_type
,
{
1
,
1
,
28
,
28
}};
std
::
cout
<<
s
<<
std
::
endl
;
auto
ptr
=
input
.
data
();
for
(
int
i
=
0
;
i
<
20
;
i
++
)
{
std
::
cout
<<
"label: "
<<
labels
[
i
]
<<
" ----> "
;
auto
input3
=
migraph
::
argument
{
s
,
&
ptr
[
784
*
i
]};
auto
result
=
prog
.
eval
({{
"Input3"
,
input3
}});
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
;
}
}
src/onnx/onnx.cpp
View file @
76f68df4
...
...
@@ -113,13 +113,49 @@ struct onnx_parser
}
return
prog
.
add_instruction
(
add
{},
args
);
});
add_op
(
"Sub"
,
[
this
](
attribute_map
,
std
::
vector
<
instruction_ref
>
args
)
{
add_op
(
"Sub"
,
[
this
](
attribute_map
attributes
,
std
::
vector
<
instruction_ref
>
args
)
{
if
(
contains
(
attributes
,
"broadcast"
))
{
uint64_t
broadcasted
=
parse_value
(
attributes
.
at
(
"broadcast"
)).
at
<
uint64_t
>
();
if
(
broadcasted
!=
0
)
{
uint64_t
axis
=
(
contains
(
attributes
,
"axis"
))
?
parse_value
(
attributes
.
at
(
"axis"
)).
at
<
uint64_t
>
()
:
0
;
auto
l
=
prog
.
add_instruction
(
broadcast
{
axis
},
args
);
return
prog
.
add_instruction
(
sub
{},
args
[
0
],
l
);
}
}
return
prog
.
add_instruction
(
sub
{},
args
);
});
add_op
(
"Mul"
,
[
this
](
attribute_map
,
std
::
vector
<
instruction_ref
>
args
)
{
add_op
(
"Mul"
,
[
this
](
attribute_map
attributes
,
std
::
vector
<
instruction_ref
>
args
)
{
if
(
contains
(
attributes
,
"broadcast"
))
{
uint64_t
broadcasted
=
parse_value
(
attributes
.
at
(
"broadcast"
)).
at
<
uint64_t
>
();
if
(
broadcasted
!=
0
)
{
uint64_t
axis
=
(
contains
(
attributes
,
"axis"
))
?
parse_value
(
attributes
.
at
(
"axis"
)).
at
<
uint64_t
>
()
:
0
;
auto
l
=
prog
.
add_instruction
(
broadcast
{
axis
},
args
);
return
prog
.
add_instruction
(
mul
{},
args
[
0
],
l
);
}
}
return
prog
.
add_instruction
(
mul
{},
args
);
});
add_op
(
"Div"
,
[
this
](
attribute_map
,
std
::
vector
<
instruction_ref
>
args
)
{
add_op
(
"Div"
,
[
this
](
attribute_map
attributes
,
std
::
vector
<
instruction_ref
>
args
)
{
if
(
contains
(
attributes
,
"broadcast"
))
{
uint64_t
broadcasted
=
parse_value
(
attributes
.
at
(
"broadcast"
)).
at
<
uint64_t
>
();
if
(
broadcasted
!=
0
)
{
uint64_t
axis
=
(
contains
(
attributes
,
"axis"
))
?
parse_value
(
attributes
.
at
(
"axis"
)).
at
<
uint64_t
>
()
:
0
;
auto
l
=
prog
.
add_instruction
(
broadcast
{
axis
},
args
);
return
prog
.
add_instruction
(
div
{},
args
[
0
],
l
);
}
}
return
prog
.
add_instruction
(
div
{},
args
);
});
}
...
...
src/onnx/verify_onnx.cpp
View file @
76f68df4
...
...
@@ -2,7 +2,7 @@
#include <migraph/onnx.hpp>
#include <migraph/cpu/cpu_target.hpp>
#include <migraph/miopen/
miopen_
target.hpp>
#include <migraph/miopen/target.hpp>
#include <migraph/miopen/hip.hpp>
#include <migraph/generate.hpp>
#include <miopen/miopen.h>
...
...
src/targets/cpu/CMakeLists.txt
View file @
76f68df4
add_library
(
migraph_cpu
cpu_target.cpp
cpu_lowering.cpp
)
rocm_clang_tidy_check
(
migraph_cpu
)
target_link_libraries
(
migraph_cpu migraph
)
...
...
src/targets/cpu/cpu_lowering.cpp
0 → 100644
View file @
76f68df4
#include <migraph/cpu/cpu_lowering.hpp>
#include <migraph/instruction.hpp>
#include <migraph/dfor.hpp>
#include <migraph/operators.hpp>
#include <migraph/shape_for_each.hpp>
#include <migraph/iterator_for.hpp>
#include <unordered_map>
namespace
migraph
{
namespace
cpu
{
template
<
typename
T
>
T
zero
(
const
T
&
)
{
return
T
(
0
);
}
//
// cpu implemenataion of batch norm for inference
//
// inputs are:
// args[0] -> input data buffer
// args[1] -> mini batch mean
// args[2] -> mini batch variance
// args[3] -> gamma
// args[4] -> beta
//
// The equation to compute batch norm for inference is:
//
// output[i] = beta + gamma * (input[i] + mean) / sqrt(variance + epsilon)
//
// the input data format should be nchw
//
struct
cpu_batch_norm_inference
{
batch_norm_inference
op
;
std
::
string
name
()
const
{
return
"cpu::batch_norm_inference"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
argument
output
{
output_shape
};
double
epsilon
=
op
.
epsilon
;
auto
input
=
args
[
0
];
auto
mini_batch_mean
=
args
[
1
].
at
<
float
>
();
auto
mini_batch_variance
=
args
[
2
].
at
<
float
>
();
auto
gamma
=
args
[
3
].
at
<
float
>
();
auto
beta
=
args
[
4
].
at
<
float
>
();
visit_all
(
output
,
input
)([
&
](
auto
result
,
auto
buffer
)
{
std
::
transform
(
buffer
.
begin
(),
buffer
.
end
(),
result
.
begin
(),
[
&
](
auto
x
)
{
return
gamma
*
(
x
-
mini_batch_mean
)
/
std
::
sqrt
(
mini_batch_variance
+
epsilon
)
+
beta
;
});
});
return
output
;
}
};
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
);
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
argument
result
{
output_shape
};
visit_all
(
result
,
args
[
0
],
args
[
1
])([
&
](
auto
output
,
auto
input
,
auto
weights
)
{
auto
in_h
=
input
.
get_shape
().
lens
()[
2
];
auto
in_w
=
input
.
get_shape
().
lens
()[
3
];
auto
wei_c
=
weights
.
get_shape
().
lens
()[
1
];
auto
wei_h
=
weights
.
get_shape
().
lens
()[
2
];
auto
wei_w
=
weights
.
get_shape
().
lens
()[
3
];
dfor
(
output_shape
.
lens
()[
0
],
output_shape
.
lens
()[
1
],
output_shape
.
lens
()[
2
],
output_shape
.
lens
()[
3
])(
[
&
](
std
::
size_t
o
,
std
::
size_t
w
,
std
::
size_t
i
,
std
::
size_t
j
)
{
const
int
start_x
=
i
*
op
.
stride
[
0
]
-
op
.
padding
[
0
];
const
int
start_y
=
j
*
op
.
stride
[
1
]
-
op
.
padding
[
1
];
double
acc
=
0
;
dfor
(
wei_c
,
wei_h
,
wei_w
)([
&
](
std
::
size_t
k
,
std
::
size_t
x
,
std
::
size_t
y
)
{
const
int
in_x
=
start_x
+
x
;
const
int
in_y
=
start_y
+
y
;
if
(
in_x
>=
0
&&
in_x
<
in_h
&&
in_y
>=
0
&&
in_y
<
in_w
)
{
acc
+=
input
(
o
,
k
,
in_x
,
in_y
)
*
weights
(
w
,
k
,
x
,
y
);
}
});
output
(
o
,
w
,
i
,
j
)
=
acc
;
});
});
return
result
;
}
};
struct
max_pool
{
static
std
::
string
name
()
{
return
"max"
;
}
static
double
start
()
{
return
std
::
numeric_limits
<
double
>::
lowest
();
}
static
double
apply
(
double
x
,
double
y
)
{
double
m
=
std
::
max
(
x
,
y
);
return
(
m
);
}
static
double
final
(
double
x
,
double
)
{
return
(
x
);
}
};
struct
avg_pool
{
static
std
::
string
name
()
{
return
"average"
;
}
static
double
start
()
{
return
0.0
;
}
static
double
apply
(
double
x
,
double
y
)
{
return
x
+
y
;
}
static
double
final
(
double
x
,
double
y
)
{
return
x
/
y
;
}
};
template
<
class
Op
>
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
{
argument
result
{
output_shape
};
visit_all
(
result
,
args
[
0
])([
&
](
auto
output
,
auto
input
)
{
using
type
=
typename
decltype
(
output
)
::
value_type
;
auto
in_h
=
input
.
get_shape
().
lens
()[
2
];
auto
in_w
=
input
.
get_shape
().
lens
()[
3
];
dfor
(
output_shape
.
lens
()[
0
],
output_shape
.
lens
()[
1
],
output_shape
.
lens
()[
2
],
output_shape
.
lens
()[
3
])(
[
&
](
std
::
size_t
o
,
std
::
size_t
w
,
std
::
size_t
i
,
std
::
size_t
j
)
{
const
int
start_x0
=
i
*
op
.
stride
[
0
]
-
op
.
padding
[
0
];
const
int
start_y0
=
j
*
op
.
stride
[
1
]
-
op
.
padding
[
1
];
const
int
hend
=
std
::
min
(
start_x0
+
op
.
lengths
[
0
],
in_h
);
const
int
wend
=
std
::
min
(
start_y0
+
op
.
lengths
[
1
],
in_w
);
const
int
start_x
=
std
::
max
(
start_x0
,
0
);
const
int
start_y
=
std
::
max
(
start_y0
,
0
);
const
int
w_h
=
(
hend
-
start_x
);
const
int
w_w
=
(
wend
-
start_y
);
const
int
pool_size
=
std
::
max
(
w_h
*
w_w
,
1
);
double
acc
=
Op
::
start
();
dfor
(
w_h
,
w_w
)([
&
](
int
x
,
int
y
)
{
const
int
in_x
=
start_x
+
x
;
const
int
in_y
=
start_y
+
y
;
if
(
in_x
>=
0
&&
in_x
<
in_h
&&
in_y
>=
0
&&
in_y
<
in_w
)
{
acc
=
Op
::
apply
(
acc
,
input
(
o
,
w
,
in_x
,
in_y
));
}
});
output
(
o
,
w
,
i
,
j
)
=
type
(
Op
::
final
(
acc
,
pool_size
));
});
});
return
result
;
}
};
struct
cpu_transpose
{
transpose
op
;
std
::
string
name
()
const
{
return
"cpu::transpose"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
return
{
output_shape
,
std
::
move
(
args
.
front
().
data
)};
}
};
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
{
argument
result
{
output_shape
};
visit_all
(
result
,
args
[
0
])([
&
](
auto
output
,
auto
input
)
{
shape_for_each
(
output
.
get_shape
(),
[
&
](
const
auto
&
idx
)
{
output
(
idx
.
begin
(),
idx
.
end
())
=
input
(
idx
.
begin
(),
idx
.
end
());
});
});
return
result
;
}
};
struct
cpu_reshape
{
reshape
op
;
std
::
string
name
()
const
{
return
"cpu::reshape"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
return
{
output_shape
,
std
::
move
(
args
.
front
().
data
)};
}
};
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
);
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
argument
result
{
output_shape
};
visit_all
(
result
,
args
[
0
],
args
[
1
])([
&
](
auto
cmat
,
auto
amat
,
auto
bmat
)
{
auto
m
=
amat
.
get_shape
().
lens
()[
0
];
auto
n
=
bmat
.
get_shape
().
lens
()[
1
];
auto
k
=
bmat
.
get_shape
().
lens
()[
0
];
auto
a
=
amat
.
data
();
auto
b
=
bmat
.
data
();
auto
c
=
cmat
.
data
();
for
(
int
ii
=
0
;
ii
<
m
;
ii
++
)
{
for
(
int
jj
=
0
;
jj
<
n
;
jj
++
)
{
c
[
ii
*
n
+
jj
]
=
0
;
}
}
for
(
int
ii
=
0
;
ii
<
m
;
ii
++
)
{
for
(
int
kk
=
0
;
kk
<
k
;
kk
++
)
{
auto
aik
=
a
[
ii
*
k
+
kk
];
auto
*
bkj
=
&
b
[
kk
*
n
];
auto
*
cij
=
&
c
[
ii
*
n
];
for
(
int
jj
=
0
;
jj
<
n
;
jj
++
,
cij
++
,
bkj
++
)
{
*
cij
+=
aik
*
(
*
bkj
);
}
}
}
});
return
result
;
}
};
struct
identity_op
{
std
::
string
name
()
const
{
return
"cpu::identity"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
x
;
};
}
};
struct
abs_op
{
std
::
string
name
()
const
{
return
"cpu::abs"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
abs
(
x
);
};
}
};
struct
exp_op
{
std
::
string
name
()
const
{
return
"cpu::exp"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
exp
(
x
);
};
}
};
struct
sin_op
{
std
::
string
name
()
const
{
return
"cpu::sin"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
sin
(
x
);
};
}
};
struct
cos_op
{
std
::
string
name
()
const
{
return
"cpu::cos"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
cos
(
x
);
};
}
};
struct
tan_op
{
std
::
string
name
()
const
{
return
"cpu::tan"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
tan
(
x
);
};
}
};
struct
asin_op
{
std
::
string
name
()
const
{
return
"cpu::asin"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
asin
(
x
);
};
}
};
struct
acos_op
{
std
::
string
name
()
const
{
return
"cpu::acos"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
acos
(
x
);
};
}
};
struct
atan_op
{
std
::
string
name
()
const
{
return
"cpu::atan"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
atan
(
x
);
};
}
};
struct
tanh_op
{
std
::
string
name
()
const
{
return
"cpu::tanh"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
tanh
(
x
);
};
}
};
struct
sigmoid_op
{
std
::
string
name
()
const
{
return
"cpu::sigmoid"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
1.
f
/
(
1.
f
+
std
::
exp
(
-
x
));
};
}
};
struct
neg_op
{
std
::
string
name
()
const
{
return
"cpu::neg"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
-
x
;
};
}
};
struct
relu_op
{
std
::
string
name
()
const
{
return
"cpu::relu"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
x
>
0
?
x
:
0
;
};
}
};
template
<
typename
Op
>
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
{
argument
result
{
output_shape
};
result
.
visit
([
&
](
auto
output
)
{
args
[
0
].
visit
([
&
](
auto
input
)
{
std
::
transform
(
input
.
begin
(),
input
.
end
(),
output
.
begin
(),
op
.
fcn
());
});
});
return
result
;
}
};
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
{
argument
result
{
output_shape
};
visit_all
(
result
,
args
[
0
])([
&
](
auto
output
,
auto
input
)
{
using
value_type
=
typename
decltype
(
input
)
::
value_type
;
auto
nb
=
input
.
get_shape
().
lens
()[
0
];
auto
nc
=
input
.
get_shape
().
lens
()[
1
];
auto
nh
=
input
.
get_shape
().
lens
()[
2
];
auto
nw
=
input
.
get_shape
().
lens
()[
3
];
dfor
(
nb
,
nh
,
nw
)([
&
](
std
::
size_t
b
,
std
::
size_t
i
,
std
::
size_t
j
)
{
value_type
cmax
=
std
::
numeric_limits
<
value_type
>::
lowest
();
for
(
int
c
=
0
;
c
<
nc
;
c
++
)
{
cmax
=
std
::
max
(
cmax
,
input
(
b
,
c
,
i
,
j
));
}
for
(
int
c
=
0
;
c
<
nc
;
c
++
)
{
output
(
b
,
c
,
i
,
j
)
=
std
::
exp
(
input
(
b
,
c
,
i
,
j
)
-
cmax
);
}
value_type
sum
=
value_type
(
0
);
for
(
int
c
=
0
;
c
<
nc
;
c
++
)
{
sum
+=
output
(
b
,
c
,
i
,
j
);
}
for
(
int
c
=
0
;
c
<
nc
;
c
++
)
{
output
(
b
,
c
,
i
,
j
)
=
output
(
b
,
c
,
i
,
j
)
/
sum
;
}
});
});
return
result
;
}
};
struct
add_op
{
std
::
string
name
()
const
{
return
"add"
;
}
auto
fcn
()
const
{
return
[](
auto
x
,
auto
y
)
{
return
x
+
y
;
};
}
};
struct
sub_op
{
std
::
string
name
()
const
{
return
"sub"
;
}
auto
fcn
()
const
{
return
[](
auto
x
,
auto
y
)
{
return
x
-
y
;
};
}
};
struct
mul_op
{
std
::
string
name
()
const
{
return
"mul"
;
}
auto
fcn
()
const
{
return
[](
auto
x
,
auto
y
)
{
return
x
*
y
;
};
}
};
struct
div_op
{
std
::
string
name
()
const
{
return
"div"
;
}
auto
fcn
()
const
{
return
[](
auto
x
,
auto
y
)
{
return
x
/
y
;
};
}
};
template
<
typename
Op
>
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
{
argument
result
{
output_shape
};
visit_all
(
result
,
args
[
0
],
args
[
1
])([
&
](
auto
output
,
auto
input1
,
auto
input2
)
{
if
(
input1
.
get_shape
().
packed
()
and
input2
.
get_shape
().
packed
())
{
std
::
transform
(
input1
.
begin
(),
input1
.
end
(),
input2
.
begin
(),
output
.
begin
(),
op
.
fcn
());
}
else
{
shape_for_each
(
output
.
get_shape
(),
[
&
](
const
auto
&
idx
)
{
output
(
idx
.
begin
(),
idx
.
end
())
=
op
.
fcn
()(
input1
(
idx
.
begin
(),
idx
.
end
()),
input2
(
idx
.
begin
(),
idx
.
end
()));
});
}
});
return
result
;
}
};
struct
cpu_apply
{
program
*
prog
;
std
::
unordered_map
<
std
::
string
,
std
::
function
<
void
(
instruction_ref
)
>>
apply_map
{};
template
<
class
T
>
auto
simple_op
()
{
return
[
this
](
instruction_ref
ins
)
{
apply_simple_op
<
T
>
(
ins
);
};
}
template
<
class
T
,
class
Op
>
auto
extend_op
()
{
return
[
this
](
instruction_ref
ins
)
{
apply_extend_op
<
T
,
Op
>
(
ins
);
};
}
void
init
()
{
apply_map
[
"convolution"
]
=
extend_op
<
cpu_convolution
,
convolution
>
();
apply_map
[
"gemm"
]
=
extend_op
<
cpu_gemm
,
gemm
>
();
apply_map
[
"batch_norm_inference"
]
=
extend_op
<
cpu_batch_norm_inference
,
batch_norm_inference
>
();
apply_map
[
"reshape"
]
=
extend_op
<
cpu_reshape
,
reshape
>
();
apply_map
[
"contiguous"
]
=
extend_op
<
cpu_contiguous
,
contiguous
>
();
apply_map
[
"transpose"
]
=
extend_op
<
cpu_transpose
,
transpose
>
();
apply_map
[
"identity"
]
=
simple_op
<
cpu_unary
<
identity_op
>>
();
apply_map
[
"tanh"
]
=
simple_op
<
cpu_unary
<
tanh_op
>>
();
apply_map
[
"sigmoid"
]
=
simple_op
<
cpu_unary
<
sigmoid_op
>>
();
apply_map
[
"exp"
]
=
simple_op
<
cpu_unary
<
exp_op
>>
();
apply_map
[
"neg"
]
=
simple_op
<
cpu_unary
<
neg_op
>>
();
apply_map
[
"sin"
]
=
simple_op
<
cpu_unary
<
sin_op
>>
();
apply_map
[
"cos"
]
=
simple_op
<
cpu_unary
<
cos_op
>>
();
apply_map
[
"tan"
]
=
simple_op
<
cpu_unary
<
tan_op
>>
();
apply_map
[
"add"
]
=
simple_op
<
cpu_binary
<
add_op
>>
();
apply_map
[
"sub"
]
=
simple_op
<
cpu_binary
<
sub_op
>>
();
apply_map
[
"mul"
]
=
simple_op
<
cpu_binary
<
mul_op
>>
();
apply_map
[
"div"
]
=
simple_op
<
cpu_binary
<
div_op
>>
();
apply_map
[
"softmax"
]
=
simple_op
<
softmax2d
>
();
}
void
apply
()
{
init
();
for
(
auto
it
:
iterator_for
(
*
prog
))
{
if
(
it
->
op
.
name
()
==
"activation"
)
{
apply_activation
(
it
);
}
else
if
(
it
->
op
.
name
()
==
"pooling"
)
{
apply_pooling
(
it
);
}
else
if
(
apply_map
.
count
(
it
->
op
.
name
())
>
0
)
{
apply_map
.
at
(
it
->
op
.
name
())(
it
);
}
}
}
template
<
class
T
>
void
apply_simple_op
(
instruction_ref
ins
)
{
prog
->
replace_instruction
(
ins
,
T
{},
ins
->
arguments
);
}
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
);
}
void
apply_activation
(
instruction_ref
ins
)
{
auto
&&
op
=
any_cast
<
activation
>
(
ins
->
op
);
if
(
op
.
mode
==
"relu"
)
prog
->
replace_instruction
(
ins
,
cpu_unary
<
relu_op
>
{},
ins
->
arguments
);
}
void
apply_pooling
(
instruction_ref
ins
)
{
auto
&&
op
=
any_cast
<
pooling
>
(
ins
->
op
);
if
(
op
.
mode
==
"max"
)
prog
->
replace_instruction
(
ins
,
cpu_pooling
<
max_pool
>
{
op
},
ins
->
arguments
);
else
if
(
op
.
mode
==
"average"
)
prog
->
replace_instruction
(
ins
,
cpu_pooling
<
avg_pool
>
{
op
},
ins
->
arguments
);
}
};
void
cpu_lowering
::
apply
(
program
&
p
)
const
{
cpu_apply
{
&
p
}.
apply
();
}
}
// namespace cpu
}
// namespace migraph
src/targets/cpu/cpu_target.cpp
View file @
76f68df4
#include <migraph/cpu/cpu_target.hpp>
#include <migraph/instruction.hpp>
#include <migraph/dfor.hpp>
#include <migraph/operators.hpp>
#include <migraph/shape_for_each.hpp>
#include <migraph/iterator_for.hpp>
#include <migraph/cpu/cpu_lowering.hpp>
namespace
migraph
{
namespace
cpu
{
template
<
typename
T
>
T
zero
(
const
T
&
)
{
return
T
(
0
);
}
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
);
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
argument
result
{
output_shape
};
visit_all
(
result
,
args
[
0
],
args
[
1
])([
&
](
auto
output
,
auto
input
,
auto
weights
)
{
auto
in_h
=
input
.
get_shape
().
lens
()[
2
];
auto
in_w
=
input
.
get_shape
().
lens
()[
3
];
auto
wei_c
=
weights
.
get_shape
().
lens
()[
1
];
auto
wei_h
=
weights
.
get_shape
().
lens
()[
2
];
auto
wei_w
=
weights
.
get_shape
().
lens
()[
3
];
dfor
(
output_shape
.
lens
()[
0
],
output_shape
.
lens
()[
1
],
output_shape
.
lens
()[
2
],
output_shape
.
lens
()[
3
])(
[
&
](
std
::
size_t
o
,
std
::
size_t
w
,
std
::
size_t
i
,
std
::
size_t
j
)
{
const
int
start_x
=
i
*
op
.
stride
[
0
]
-
op
.
padding
[
0
];
const
int
start_y
=
j
*
op
.
stride
[
1
]
-
op
.
padding
[
1
];
double
acc
=
0
;
dfor
(
wei_c
,
wei_h
,
wei_w
)([
&
](
std
::
size_t
k
,
std
::
size_t
x
,
std
::
size_t
y
)
{
const
int
in_x
=
start_x
+
x
;
const
int
in_y
=
start_y
+
y
;
if
(
in_x
>=
0
&&
in_x
<
in_h
&&
in_y
>=
0
&&
in_y
<
in_w
)
{
acc
+=
input
(
o
,
k
,
in_x
,
in_y
)
*
weights
(
w
,
k
,
x
,
y
);
}
});
output
(
o
,
w
,
i
,
j
)
=
acc
;
});
});
return
result
;
}
};
struct
max_pool
{
static
std
::
string
name
()
{
return
"max"
;
}
static
double
start
()
{
return
std
::
numeric_limits
<
double
>::
lowest
();
}
static
double
apply
(
double
x
,
double
y
)
{
double
m
=
std
::
max
(
x
,
y
);
return
(
m
);
}
static
double
final
(
double
x
,
double
)
{
return
(
x
);
}
};
struct
avg_pool
{
static
std
::
string
name
()
{
return
"average"
;
}
static
double
start
()
{
return
0.0
;
}
static
double
apply
(
double
x
,
double
y
)
{
return
x
+
y
;
}
static
double
final
(
double
x
,
double
y
)
{
return
x
/
y
;
}
};
template
<
class
Op
>
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
{
argument
result
{
output_shape
};
visit_all
(
result
,
args
[
0
])([
&
](
auto
output
,
auto
input
)
{
using
type
=
typename
decltype
(
output
)
::
value_type
;
auto
in_h
=
input
.
get_shape
().
lens
()[
2
];
auto
in_w
=
input
.
get_shape
().
lens
()[
3
];
dfor
(
output_shape
.
lens
()[
0
],
output_shape
.
lens
()[
1
],
output_shape
.
lens
()[
2
],
output_shape
.
lens
()[
3
])(
[
&
](
std
::
size_t
o
,
std
::
size_t
w
,
std
::
size_t
i
,
std
::
size_t
j
)
{
const
int
start_x0
=
i
*
op
.
stride
[
0
]
-
op
.
padding
[
0
];
const
int
start_y0
=
j
*
op
.
stride
[
1
]
-
op
.
padding
[
1
];
const
int
hend
=
std
::
min
(
start_x0
+
op
.
lengths
[
0
],
in_h
);
const
int
wend
=
std
::
min
(
start_y0
+
op
.
lengths
[
1
],
in_w
);
const
int
start_x
=
std
::
max
(
start_x0
,
0
);
const
int
start_y
=
std
::
max
(
start_y0
,
0
);
const
int
w_h
=
(
hend
-
start_x
);
const
int
w_w
=
(
wend
-
start_y
);
const
int
pool_size
=
std
::
max
(
w_h
*
w_w
,
1
);
double
acc
=
Op
::
start
();
dfor
(
w_h
,
w_w
)([
&
](
int
x
,
int
y
)
{
const
int
in_x
=
start_x
+
x
;
const
int
in_y
=
start_y
+
y
;
if
(
in_x
>=
0
&&
in_x
<
in_h
&&
in_y
>=
0
&&
in_y
<
in_w
)
{
acc
=
Op
::
apply
(
acc
,
input
(
o
,
w
,
in_x
,
in_y
));
}
});
output
(
o
,
w
,
i
,
j
)
=
type
(
Op
::
final
(
acc
,
pool_size
));
});
});
return
result
;
}
};
struct
cpu_transpose
{
transpose
op
;
std
::
string
name
()
const
{
return
"cpu::transpose"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
return
{
output_shape
,
std
::
move
(
args
.
front
().
data
)};
}
};
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
{
argument
result
{
output_shape
};
visit_all
(
result
,
args
[
0
])([
&
](
auto
output
,
auto
input
)
{
shape_for_each
(
output
.
get_shape
(),
[
&
](
const
auto
&
idx
)
{
output
(
idx
.
begin
(),
idx
.
end
())
=
input
(
idx
.
begin
(),
idx
.
end
());
});
});
return
result
;
}
};
struct
cpu_reshape
{
reshape
op
;
std
::
string
name
()
const
{
return
"cpu::reshape"
;
}
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
return
op
.
compute_shape
(
inputs
);
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
return
{
output_shape
,
std
::
move
(
args
.
front
().
data
)};
}
};
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
);
}
argument
compute
(
context
&
,
shape
output_shape
,
std
::
vector
<
argument
>
args
)
const
{
argument
result
{
output_shape
};
visit_all
(
result
,
args
[
0
],
args
[
1
])([
&
](
auto
cmat
,
auto
amat
,
auto
bmat
)
{
auto
m
=
amat
.
get_shape
().
lens
()[
0
];
auto
n
=
bmat
.
get_shape
().
lens
()[
1
];
auto
k
=
bmat
.
get_shape
().
lens
()[
0
];
auto
a
=
amat
.
data
();
auto
b
=
bmat
.
data
();
auto
c
=
cmat
.
data
();
for
(
int
ii
=
0
;
ii
<
m
;
ii
++
)
{
for
(
int
jj
=
0
;
jj
<
n
;
jj
++
)
{
c
[
ii
*
n
+
jj
]
=
0
;
}
}
for
(
int
ii
=
0
;
ii
<
m
;
ii
++
)
{
for
(
int
kk
=
0
;
kk
<
k
;
kk
++
)
{
auto
aik
=
a
[
ii
*
k
+
kk
];
auto
*
bkj
=
&
b
[
kk
*
n
];
auto
*
cij
=
&
c
[
ii
*
n
];
for
(
int
jj
=
0
;
jj
<
n
;
jj
++
,
cij
++
,
bkj
++
)
{
*
cij
+=
aik
*
(
*
bkj
);
}
}
}
});
return
result
;
}
};
struct
identity_op
{
std
::
string
name
()
const
{
return
"cpu::identity"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
x
;
};
}
};
struct
abs_op
{
std
::
string
name
()
const
{
return
"cpu::abs"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
abs
(
x
);
};
}
};
struct
exp_op
{
std
::
string
name
()
const
{
return
"cpu::exp"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
exp
(
x
);
};
}
};
struct
sin_op
{
std
::
string
name
()
const
{
return
"cpu::sin"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
sin
(
x
);
};
}
};
struct
cos_op
{
std
::
string
name
()
const
{
return
"cpu::cos"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
cos
(
x
);
};
}
};
struct
tan_op
{
std
::
string
name
()
const
{
return
"cpu::tan"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
tan
(
x
);
};
}
};
struct
asin_op
{
std
::
string
name
()
const
{
return
"cpu::asin"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
asin
(
x
);
};
}
};
struct
acos_op
{
std
::
string
name
()
const
{
return
"cpu::acos"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
acos
(
x
);
};
}
};
struct
atan_op
{
std
::
string
name
()
const
{
return
"cpu::atan"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
atan
(
x
);
};
}
};
struct
tanh_op
{
std
::
string
name
()
const
{
return
"cpu::tanh"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
std
::
tanh
(
x
);
};
}
};
struct
sigmoid_op
{
std
::
string
name
()
const
{
return
"cpu::sigmoid"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
1.
f
/
(
1.
f
+
std
::
exp
(
-
x
));
};
}
};
struct
neg_op
{
std
::
string
name
()
const
{
return
"cpu::neg"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
-
x
;
};
}
};
struct
relu_op
{
std
::
string
name
()
const
{
return
"cpu::relu"
;
}
auto
fcn
()
const
{
return
[](
auto
x
)
{
return
x
>
0
?
x
:
0
;
};
}
};
template
<
typename
Op
>
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
{
argument
result
{
output_shape
};
result
.
visit
([
&
](
auto
output
)
{
args
[
0
].
visit
([
&
](
auto
input
)
{
std
::
transform
(
input
.
begin
(),
input
.
end
(),
output
.
begin
(),
op
.
fcn
());
});
});
return
result
;
}
};
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
{
argument
result
{
output_shape
};
visit_all
(
result
,
args
[
0
])([
&
](
auto
output
,
auto
input
)
{
using
value_type
=
typename
decltype
(
input
)
::
value_type
;
auto
nb
=
input
.
get_shape
().
lens
()[
0
];
auto
nc
=
input
.
get_shape
().
lens
()[
1
];
auto
nh
=
input
.
get_shape
().
lens
()[
2
];
auto
nw
=
input
.
get_shape
().
lens
()[
3
];
dfor
(
nb
,
nh
,
nw
)([
&
](
std
::
size_t
b
,
std
::
size_t
i
,
std
::
size_t
j
)
{
value_type
cmax
=
std
::
numeric_limits
<
value_type
>::
lowest
();
for
(
int
c
=
0
;
c
<
nc
;
c
++
)
{
cmax
=
std
::
max
(
cmax
,
input
(
b
,
c
,
i
,
j
));
}
for
(
int
c
=
0
;
c
<
nc
;
c
++
)
{
output
(
b
,
c
,
i
,
j
)
=
std
::
exp
(
input
(
b
,
c
,
i
,
j
)
-
cmax
);
}
value_type
sum
=
value_type
(
0
);
for
(
int
c
=
0
;
c
<
nc
;
c
++
)
{
sum
+=
output
(
b
,
c
,
i
,
j
);
}
for
(
int
c
=
0
;
c
<
nc
;
c
++
)
{
output
(
b
,
c
,
i
,
j
)
=
output
(
b
,
c
,
i
,
j
)
/
sum
;
}
});
});
return
result
;
}
};
struct
add_op
{
std
::
string
name
()
const
{
return
"add"
;
}
auto
fcn
()
const
{
return
[](
auto
x
,
auto
y
)
{
return
x
+
y
;
};
}
};
struct
sub_op
{
std
::
string
name
()
const
{
return
"sub"
;
}
auto
fcn
()
const
{
return
[](
auto
x
,
auto
y
)
{
return
x
-
y
;
};
}
};
struct
mul_op
{
std
::
string
name
()
const
{
return
"mul"
;
}
auto
fcn
()
const
{
return
[](
auto
x
,
auto
y
)
{
return
x
*
y
;
};
}
};
struct
div_op
{
std
::
string
name
()
const
{
return
"div"
;
}
auto
fcn
()
const
{
return
[](
auto
x
,
auto
y
)
{
return
x
/
y
;
};
}
};
template
<
typename
Op
>
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
{
argument
result
{
output_shape
};
visit_all
(
result
,
args
[
0
],
args
[
1
])([
&
](
auto
output
,
auto
input1
,
auto
input2
)
{
if
(
input1
.
get_shape
().
packed
()
and
input2
.
get_shape
().
packed
())
{
std
::
transform
(
input1
.
begin
(),
input1
.
end
(),
input2
.
begin
(),
output
.
begin
(),
op
.
fcn
());
}
else
{
shape_for_each
(
output
.
get_shape
(),
[
&
](
const
auto
&
idx
)
{
output
(
idx
.
begin
(),
idx
.
end
())
=
op
.
fcn
()(
input1
(
idx
.
begin
(),
idx
.
end
()),
input2
(
idx
.
begin
(),
idx
.
end
()));
});
}
});
return
result
;
}
};
struct
cpu_apply
{
program
*
prog
;
std
::
unordered_map
<
std
::
string
,
std
::
function
<
void
(
instruction_ref
)
>>
apply_map
{};
template
<
class
T
>
auto
simple_op
()
{
return
[
this
](
instruction_ref
ins
)
{
apply_simple_op
<
T
>
(
ins
);
};
}
template
<
class
T
,
class
Op
>
auto
extend_op
()
{
return
[
this
](
instruction_ref
ins
)
{
apply_extend_op
<
T
,
Op
>
(
ins
);
};
}
void
init
()
{
apply_map
[
"convolution"
]
=
extend_op
<
cpu_convolution
,
convolution
>
();
apply_map
[
"gemm"
]
=
extend_op
<
cpu_gemm
,
gemm
>
();
apply_map
[
"reshape"
]
=
extend_op
<
cpu_reshape
,
reshape
>
();
apply_map
[
"contiguous"
]
=
extend_op
<
cpu_contiguous
,
contiguous
>
();
apply_map
[
"transpose"
]
=
extend_op
<
cpu_transpose
,
transpose
>
();
apply_map
[
"identity"
]
=
simple_op
<
cpu_unary
<
identity_op
>>
();
apply_map
[
"tanh"
]
=
simple_op
<
cpu_unary
<
tanh_op
>>
();
apply_map
[
"sigmoid"
]
=
simple_op
<
cpu_unary
<
sigmoid_op
>>
();
apply_map
[
"exp"
]
=
simple_op
<
cpu_unary
<
exp_op
>>
();
apply_map
[
"neg"
]
=
simple_op
<
cpu_unary
<
neg_op
>>
();
apply_map
[
"sin"
]
=
simple_op
<
cpu_unary
<
sin_op
>>
();
apply_map
[
"cos"
]
=
simple_op
<
cpu_unary
<
cos_op
>>
();
apply_map
[
"tan"
]
=
simple_op
<
cpu_unary
<
tan_op
>>
();
apply_map
[
"add"
]
=
simple_op
<
cpu_binary
<
add_op
>>
();
apply_map
[
"sub"
]
=
simple_op
<
cpu_binary
<
sub_op
>>
();
apply_map
[
"mul"
]
=
simple_op
<
cpu_binary
<
mul_op
>>
();
apply_map
[
"div"
]
=
simple_op
<
cpu_binary
<
div_op
>>
();
apply_map
[
"softmax"
]
=
simple_op
<
softmax2d
>
();
}
void
apply
()
{
init
();
for
(
auto
it
:
iterator_for
(
*
prog
))
{
if
(
it
->
op
.
name
()
==
"activation"
)
{
apply_activation
(
it
);
}
else
if
(
it
->
op
.
name
()
==
"pooling"
)
{
apply_pooling
(
it
);
}
else
if
(
apply_map
.
count
(
it
->
op
.
name
())
>
0
)
{
apply_map
.
at
(
it
->
op
.
name
())(
it
);
}
}
}
template
<
class
T
>
void
apply_simple_op
(
instruction_ref
ins
)
{
prog
->
replace_instruction
(
ins
,
T
{},
ins
->
arguments
);
}
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
);
}
void
apply_activation
(
instruction_ref
ins
)
{
auto
&&
op
=
any_cast
<
activation
>
(
ins
->
op
);
if
(
op
.
mode
==
"relu"
)
prog
->
replace_instruction
(
ins
,
cpu_unary
<
relu_op
>
{},
ins
->
arguments
);
}
void
apply_pooling
(
instruction_ref
ins
)
{
auto
&&
op
=
any_cast
<
pooling
>
(
ins
->
op
);
if
(
op
.
mode
==
"max"
)
prog
->
replace_instruction
(
ins
,
cpu_pooling
<
max_pool
>
{
op
},
ins
->
arguments
);
else
if
(
op
.
mode
==
"average"
)
prog
->
replace_instruction
(
ins
,
cpu_pooling
<
avg_pool
>
{
op
},
ins
->
arguments
);
}
};
struct
cpu_pass
{
std
::
string
name
()
const
{
return
"cpu::pass"
;
}
void
apply
(
program
&
p
)
const
{
cpu_apply
{
&
p
}.
apply
();
}
};
std
::
string
cpu_target
::
name
()
const
{
return
"cpu"
;
}
std
::
vector
<
pass
>
cpu_target
::
get_passes
(
context
&
)
const
{
return
{
cpu_
pass
{}};
}
std
::
vector
<
pass
>
cpu_target
::
get_passes
(
context
&
)
const
{
return
{
cpu_
lowering
{}};
}
}
// namespace cpu
...
...
src/targets/cpu/include/migraph/cpu/cpu_lowering.hpp
0 → 100644
View file @
76f68df4
#ifndef MIGRAPH_GUARD_RTGLIB_CPU_LOWERING_HPP
#define MIGRAPH_GUARD_RTGLIB_CPU_LOWERING_HPP
#include <migraph/program.hpp>
namespace
migraph
{
namespace
cpu
{
struct
cpu_lowering
{
std
::
string
name
()
const
{
return
"cpu::lowering"
;
}
void
apply
(
program
&
p
)
const
;
};
}
// namespace cpu
}
// namespace migraph
#endif
src/targets/miopen/CMakeLists.txt
View file @
76f68df4
...
...
@@ -2,6 +2,10 @@
list
(
APPEND CMAKE_PREFIX_PATH /opt/rocm /opt/rocm/hip /opt/rocm/hcc
)
find_package
(
miopen
)
# rocblas
find_package
(
rocblas REQUIRED PATHS /opt/rocm
)
message
(
STATUS
"Build with rocblas"
)
if
(
NOT TARGET MIOpen
)
message
(
SEND_ERROR
"Cant find miopen"
)
endif
()
...
...
@@ -15,8 +19,11 @@ target_include_directories(migraph_device PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRE
add_library
(
migraph_miopen
hip.cpp
miopen_target.cpp
target.cpp
lowering.cpp
write_literals.cpp
rocblas.cpp
)
rocm_clang_tidy_check
(
migraph_miopen
)
target_link_libraries
(
migraph_miopen migraph MIOpen migraph_device
)
target_link_libraries
(
migraph_miopen migraph MIOpen migraph_device
roc::rocblas
)
target_include_directories
(
migraph_miopen PUBLIC $<BUILD_INTERFACE:
${
CMAKE_CURRENT_SOURCE_DIR
}
/include>
)
src/targets/miopen/include/migraph/miopen/context.hpp
0 → 100644
View file @
76f68df4
#ifndef MIGRAPH_GUARD_RTGLIB_CONTEXT_HPP
#define MIGRAPH_GUARD_RTGLIB_CONTEXT_HPP
#include <migraph/miopen/miopen.hpp>
#include <migraph/miopen/rocblas.hpp>
namespace
migraph
{
namespace
miopen
{
struct
context
{
shared
<
miopen_handle
>
handle
;
shared
<
rocblas_handle_ptr
>
rbhandle
;
};
}
// namespace miopen
}
// namespace migraph
#endif
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