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
664b2f7c
Unverified
Commit
664b2f7c
authored
Dec 04, 2023
by
Chris Austen
Committed by
GitHub
Dec 04, 2023
Browse files
Merge branch 'develop' into navi-reduce
parents
20cdddac
9c46821c
Changes
275
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
2083 additions
and
146 deletions
+2083
-146
test/ref/scatternd_min.cpp
test/ref/scatternd_min.cpp
+191
-0
test/ref/slice.cpp
test/ref/slice.cpp
+163
-1
test/ref/unique.cpp
test/ref/unique.cpp
+342
-0
test/rewrite_pooling_test.cpp
test/rewrite_pooling_test.cpp
+487
-5
test/simplify_algebra_test.cpp
test/simplify_algebra_test.cpp
+49
-19
test/simplify_dyn_ops_test.cpp
test/simplify_dyn_ops_test.cpp
+342
-8
test/simplify_qdq_test.cpp
test/simplify_qdq_test.cpp
+366
-70
test/simplify_reshapes_test.cpp
test/simplify_reshapes_test.cpp
+7
-12
test/verify/gemm_2args_mm_8.cpp
test/verify/gemm_2args_mm_8.cpp
+11
-7
test/verify/gemm_softmax_gemm_relu.cpp
test/verify/gemm_softmax_gemm_relu.cpp
+56
-0
test/verify/test_abs.cpp
test/verify/test_abs.cpp
+7
-2
test/verify/test_acos.cpp
test/verify/test_acos.cpp
+7
-2
test/verify/test_acosh.cpp
test/verify/test_acosh.cpp
+12
-5
test/verify/test_add.cpp
test/verify/test_add.cpp
+7
-2
test/verify/test_asin.cpp
test/verify/test_asin.cpp
+7
-2
test/verify/test_asinh.cpp
test/verify/test_asinh.cpp
+7
-2
test/verify/test_atan.cpp
test/verify/test_atan.cpp
+7
-2
test/verify/test_atanh.cpp
test/verify/test_atanh.cpp
+13
-5
test/verify/test_avg_pooling_1d.cpp
test/verify/test_avg_pooling_1d.cpp
+1
-1
test/verify/test_avg_pooling_3d.cpp
test/verify/test_avg_pooling_3d.cpp
+1
-1
No files found.
test/ref/scatternd_min.cpp
0 → 100644
View file @
664b2f7c
/*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 Advanced Micro Devices, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <migraphx/instruction.hpp>
#include <migraphx/literal.hpp>
#include <migraphx/make_op.hpp>
#include <migraphx/program.hpp>
#include <migraphx/register_target.hpp>
#include <migraphx/verify.hpp>
#include <test.hpp>
TEST_CASE
(
scatternd_min_test_1
)
{
// r=1, q=2, k=1
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
auto
dtype
=
migraphx
::
shape
::
float_type
;
auto
itype
=
migraphx
::
shape
::
int64_type
;
migraphx
::
shape
ds
{
dtype
,
{
8
}};
migraphx
::
shape
is
{
itype
,
{
4
,
1
}};
migraphx
::
shape
us
{
dtype
,
{
4
}};
std
::
vector
<
float
>
data_vec
{
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
};
std
::
vector
<
int64_t
>
ind_vec
{
4
,
3
,
1
,
7
};
std
::
vector
<
float
>
upd_vec
{
9
,
3
,
1
,
12
};
auto
data
=
mm
->
add_literal
(
migraphx
::
literal
{
ds
,
data_vec
});
auto
indices
=
mm
->
add_literal
(
migraphx
::
literal
{
is
,
ind_vec
});
auto
updates
=
mm
->
add_literal
(
migraphx
::
literal
{
us
,
upd_vec
});
auto
scatternd
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"scatternd_min"
),
data
,
indices
,
updates
);
mm
->
add_return
({
scatternd
});
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
auto
result
=
p
.
eval
({}).
back
();
std
::
vector
<
float
>
results_vector
;
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
std
::
vector
<
float
>
gold
{
1
,
1
,
3
,
3
,
5
,
6
,
7
,
8
};
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
scatternd_min_test_2
)
{
// r=2, q=2, k=2
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
auto
dtype
=
migraphx
::
shape
::
float_type
;
auto
itype
=
migraphx
::
shape
::
int64_type
;
migraphx
::
shape
ds
{
dtype
,
{
2
,
2
}};
migraphx
::
shape
is
{
itype
,
{
2
,
2
}};
migraphx
::
shape
us
{
dtype
,
{
2
}};
std
::
vector
<
float
>
data_vec
{
1
,
2
,
3
,
4
};
std
::
vector
<
int64_t
>
ind_vec
{
0
,
0
,
0
,
1
};
std
::
vector
<
float
>
upd_vec
{
5
,
1
};
auto
data
=
mm
->
add_literal
(
migraphx
::
literal
{
ds
,
data_vec
});
auto
indices
=
mm
->
add_literal
(
migraphx
::
literal
{
is
,
ind_vec
});
auto
updates
=
mm
->
add_literal
(
migraphx
::
literal
{
us
,
upd_vec
});
auto
scatternd
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"scatternd_min"
),
data
,
indices
,
updates
);
mm
->
add_return
({
scatternd
});
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
auto
result
=
p
.
eval
({}).
back
();
std
::
vector
<
float
>
results_vector
;
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
std
::
vector
<
float
>
gold
{
1
,
1
,
3
,
4
};
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
scatternd_min_test_3
)
{
// r=3, q=3, k=3
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
auto
dtype
=
migraphx
::
shape
::
float_type
;
auto
itype
=
migraphx
::
shape
::
int64_type
;
migraphx
::
shape
ds
{
dtype
,
{
2
,
2
,
2
}};
migraphx
::
shape
is
{
itype
,
{
2
,
1
,
3
}};
migraphx
::
shape
us
{
dtype
,
{
2
,
1
}};
std
::
vector
<
float
>
data_vec
{
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
};
std
::
vector
<
int64_t
>
ind_vec
{
0
,
0
,
0
,
1
,
1
,
1
};
std
::
vector
<
float
>
upd_vec
{
9
,
1
};
auto
data
=
mm
->
add_literal
(
migraphx
::
literal
{
ds
,
data_vec
});
auto
indices
=
mm
->
add_literal
(
migraphx
::
literal
{
is
,
ind_vec
});
auto
updates
=
mm
->
add_literal
(
migraphx
::
literal
{
us
,
upd_vec
});
auto
scatternd
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"scatternd_min"
),
data
,
indices
,
updates
);
mm
->
add_return
({
scatternd
});
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
auto
result
=
p
.
eval
({}).
back
();
std
::
vector
<
float
>
results_vector
;
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
std
::
vector
<
float
>
gold
{
1
,
2
,
3
,
4
,
5
,
6
,
7
,
1
};
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
scatternd_min_test_4
)
{
// r=3, q=2, k=1
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
auto
dtype
=
migraphx
::
shape
::
float_type
;
auto
itype
=
migraphx
::
shape
::
int64_type
;
migraphx
::
shape
ds
{
dtype
,
{
4
,
4
,
4
}};
migraphx
::
shape
is
{
itype
,
{
2
,
1
}};
migraphx
::
shape
us
{
dtype
,
{
2
,
4
,
4
}};
std
::
vector
<
float
>
data_vec
{
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
8
,
7
,
6
,
5
,
4
,
3
,
2
,
1
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
8
,
7
,
6
,
5
,
4
,
3
,
2
,
1
,
8
,
7
,
6
,
5
,
4
,
3
,
2
,
1
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
8
,
7
,
6
,
5
,
4
,
3
,
2
,
1
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
};
std
::
vector
<
int64_t
>
ind_vec
{
0
,
2
};
std
::
vector
<
float
>
upd_vec
{
5
,
5
,
5
,
5
,
6
,
6
,
6
,
6
,
7
,
7
,
7
,
7
,
8
,
8
,
8
,
8
,
1
,
1
,
1
,
1
,
2
,
2
,
2
,
2
,
3
,
3
,
3
,
3
,
4
,
4
,
4
,
4
};
auto
data
=
mm
->
add_literal
(
migraphx
::
literal
{
ds
,
data_vec
});
auto
indices
=
mm
->
add_literal
(
migraphx
::
literal
{
is
,
ind_vec
});
auto
updates
=
mm
->
add_literal
(
migraphx
::
literal
{
us
,
upd_vec
});
auto
scatternd
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"scatternd_min"
),
data
,
indices
,
updates
);
mm
->
add_return
({
scatternd
});
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
auto
result
=
p
.
eval
({}).
back
();
std
::
vector
<
float
>
results_vector
;
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
std
::
vector
<
float
>
gold
{
1
,
2
,
3
,
4
,
5
,
6
,
6
,
6
,
7
,
7
,
6
,
5
,
4
,
3
,
2
,
1
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
8
,
7
,
6
,
5
,
4
,
3
,
2
,
1
,
1
,
1
,
1
,
1
,
2
,
2
,
2
,
1
,
1
,
2
,
3
,
3
,
4
,
4
,
4
,
4
,
8
,
7
,
6
,
5
,
4
,
3
,
2
,
1
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
};
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
scatternd_min_test_duplicate_idx
)
{
// r=3, q=2, k=1
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
auto
dtype
=
migraphx
::
shape
::
float_type
;
auto
itype
=
migraphx
::
shape
::
int64_type
;
migraphx
::
shape
ds
{
dtype
,
{
4
,
4
,
4
}};
migraphx
::
shape
is
{
itype
,
{
2
,
1
}};
migraphx
::
shape
us
{
dtype
,
{
2
,
4
,
4
}};
std
::
vector
<
float
>
data_vec
{
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
8
,
7
,
6
,
5
,
4
,
3
,
2
,
1
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
8
,
7
,
6
,
5
,
4
,
3
,
2
,
1
,
8
,
7
,
6
,
5
,
4
,
3
,
2
,
1
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
8
,
7
,
6
,
5
,
4
,
3
,
2
,
1
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
};
std
::
vector
<
int64_t
>
ind_vec
{
0
,
0
};
std
::
vector
<
float
>
upd_vec
{
5
,
5
,
5
,
5
,
2
,
2
,
2
,
2
,
7
,
7
,
7
,
7
,
4
,
4
,
4
,
4
,
1
,
1
,
1
,
1
,
6
,
6
,
6
,
6
,
3
,
3
,
3
,
3
,
8
,
8
,
8
,
8
};
auto
data
=
mm
->
add_literal
(
migraphx
::
literal
{
ds
,
data_vec
});
auto
indices
=
mm
->
add_literal
(
migraphx
::
literal
{
is
,
ind_vec
});
auto
updates
=
mm
->
add_literal
(
migraphx
::
literal
{
us
,
upd_vec
});
auto
scatternd
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"scatternd_min"
),
data
,
indices
,
updates
);
mm
->
add_return
({
scatternd
});
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
auto
result
=
p
.
eval
({}).
back
();
std
::
vector
<
float
>
results_vector
;
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
std
::
vector
<
float
>
gold
{
1
,
1
,
1
,
1
,
2
,
2
,
2
,
2
,
3
,
3
,
3
,
3
,
4
,
3
,
2
,
1
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
8
,
7
,
6
,
5
,
4
,
3
,
2
,
1
,
8
,
7
,
6
,
5
,
4
,
3
,
2
,
1
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
8
,
7
,
6
,
5
,
4
,
3
,
2
,
1
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
};
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
test/ref/slice.cpp
View file @
664b2f7c
...
...
@@ -157,7 +157,169 @@ TEST_CASE(slice_var_inputs_static2)
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
slice_var_inputs_dyn
)
TEST_CASE
(
slice_var_inputs_dyn0
)
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
migraphx
::
shape
s0
{
migraphx
::
shape
::
int32_type
,
{{
2
,
4
,
{
2
,
4
}},
{
2
,
4
,
{
2
,
4
}},
{
3
,
8
}}};
auto
input
=
mm
->
add_parameter
(
"input"
,
s0
);
migraphx
::
shape
s1
{
migraphx
::
shape
::
int32_type
,
{
1
}};
auto
starts
=
mm
->
add_parameter
(
"starts"
,
s1
);
mm
->
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"axes"
,
{
2
}},
{
"ends"
,
{
10
}}}),
input
,
starts
);
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
migraphx
::
parameter_map
params
;
migraphx
::
shape
s2
{
migraphx
::
shape
::
int32_type
,
{
2
,
2
,
3
}};
std
::
vector
<
int
>
input_data
(
2
*
2
*
3
);
std
::
iota
(
input_data
.
begin
(),
input_data
.
end
(),
0
);
std
::
vector
<
int
>
start_data
=
{
1
};
params
[
"input"
]
=
migraphx
::
argument
(
s2
,
input_data
.
data
());
params
[
"starts"
]
=
migraphx
::
argument
(
s1
,
start_data
.
data
());
auto
result
=
p
.
eval
(
params
).
back
();
std
::
vector
<
int
>
gold
=
{
1
,
2
,
4
,
5
,
7
,
8
,
10
,
11
};
std
::
vector
<
int
>
results_vector
(
2
*
2
*
2
);
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
slice_var_inputs_dyn1
)
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
migraphx
::
shape
s0
{
migraphx
::
shape
::
int32_type
,
{{
2
,
4
,
{
2
,
4
}},
{
2
,
4
,
{
2
,
4
}},
{
3
,
8
}}};
auto
input
=
mm
->
add_parameter
(
"input"
,
s0
);
migraphx
::
shape
s1
{
migraphx
::
shape
::
int32_type
,
{
1
}};
auto
ends
=
mm
->
add_parameter
(
"ends"
,
s1
);
mm
->
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"axes"
,
{
2
}},
{
"starts"
,
{
-
5
}}}),
input
,
ends
);
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
migraphx
::
parameter_map
params
;
migraphx
::
shape
s2
{
migraphx
::
shape
::
int32_type
,
{
2
,
2
,
3
}};
std
::
vector
<
int
>
input_data
(
2
*
2
*
3
);
std
::
iota
(
input_data
.
begin
(),
input_data
.
end
(),
0
);
std
::
vector
<
int
>
ends_data
=
{
3
};
params
[
"input"
]
=
migraphx
::
argument
(
s2
,
input_data
.
data
());
params
[
"ends"
]
=
migraphx
::
argument
(
s1
,
ends_data
.
data
());
auto
result
=
p
.
eval
(
params
).
back
();
std
::
vector
<
int
>
gold
=
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
11
};
std
::
vector
<
int
>
results_vector
(
2
*
2
*
3
);
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
slice_var_inputs_dyn2
)
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
migraphx
::
shape
s0
{
migraphx
::
shape
::
int32_type
,
{{
2
,
4
,
{
2
,
4
}},
{
2
,
4
,
{
2
,
4
}},
{
3
,
8
}}};
auto
input
=
mm
->
add_parameter
(
"input"
,
s0
);
migraphx
::
shape
s1
{
migraphx
::
shape
::
int32_type
,
{
1
}};
auto
axes
=
mm
->
add_parameter
(
"axes"
,
s1
);
mm
->
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"starts"
,
{
1
}},
{
"ends"
,
{
-
1
}}}),
input
,
axes
);
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
migraphx
::
parameter_map
params
;
migraphx
::
shape
s2
{
migraphx
::
shape
::
int32_type
,
{
2
,
2
,
3
}};
std
::
vector
<
int
>
input_data
(
2
*
2
*
3
);
std
::
iota
(
input_data
.
begin
(),
input_data
.
end
(),
0
);
std
::
vector
<
int
>
axes_data
=
{
2
};
params
[
"input"
]
=
migraphx
::
argument
(
s2
,
input_data
.
data
());
params
[
"axes"
]
=
migraphx
::
argument
(
s1
,
axes_data
.
data
());
auto
result
=
p
.
eval
(
params
).
back
();
std
::
vector
<
int
>
gold
=
{
1
,
4
,
7
,
10
};
std
::
vector
<
int
>
results_vector
(
2
*
2
*
1
);
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
slice_var_inputs_dyn3
)
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
migraphx
::
shape
s0
{
migraphx
::
shape
::
int32_type
,
{{
2
,
4
,
{
2
,
4
}},
{
2
,
4
,
{
2
,
4
}},
{
3
,
8
}}};
auto
input
=
mm
->
add_parameter
(
"input"
,
s0
);
migraphx
::
shape
s1
{
migraphx
::
shape
::
int32_type
,
{
1
}};
auto
starts
=
mm
->
add_parameter
(
"starts"
,
s1
);
auto
ends
=
mm
->
add_parameter
(
"ends"
,
s1
);
mm
->
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"axes"
,
{
2
}}}),
input
,
starts
,
ends
);
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
migraphx
::
parameter_map
params
;
migraphx
::
shape
s2
{
migraphx
::
shape
::
int32_type
,
{
2
,
2
,
3
}};
std
::
vector
<
int
>
input_data
(
2
*
2
*
3
);
std
::
iota
(
input_data
.
begin
(),
input_data
.
end
(),
0
);
std
::
vector
<
int
>
starts_data
=
{
1
};
std
::
vector
<
int
>
ends_data
=
{
std
::
numeric_limits
<
int
>::
max
()};
params
[
"input"
]
=
migraphx
::
argument
(
s2
,
input_data
.
data
());
params
[
"starts"
]
=
migraphx
::
argument
(
s1
,
starts_data
.
data
());
params
[
"ends"
]
=
migraphx
::
argument
(
s1
,
ends_data
.
data
());
auto
result
=
p
.
eval
(
params
).
back
();
std
::
vector
<
int
>
gold
=
{
1
,
2
,
4
,
5
,
7
,
8
,
10
,
11
};
std
::
vector
<
int
>
results_vector
(
2
*
2
*
2
);
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
slice_var_inputs_dyn4
)
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
migraphx
::
shape
s0
{
migraphx
::
shape
::
int32_type
,
{{
2
,
4
,
{
2
,
4
}},
{
2
,
4
,
{
2
,
4
}},
{
3
,
8
}}};
auto
input
=
mm
->
add_parameter
(
"input"
,
s0
);
migraphx
::
shape
s1
{
migraphx
::
shape
::
int32_type
,
{
1
}};
auto
starts
=
mm
->
add_parameter
(
"starts"
,
s1
);
auto
axes
=
mm
->
add_parameter
(
"axes"
,
s1
);
mm
->
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"ends"
,
{
std
::
numeric_limits
<
int
>::
max
()}}}),
input
,
starts
,
axes
);
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
migraphx
::
parameter_map
params
;
migraphx
::
shape
s2
{
migraphx
::
shape
::
int32_type
,
{
2
,
2
,
3
}};
std
::
vector
<
int
>
input_data
(
2
*
2
*
3
);
std
::
iota
(
input_data
.
begin
(),
input_data
.
end
(),
0
);
std
::
vector
<
int
>
starts_data
=
{
1
};
std
::
vector
<
int
>
axes_data
=
{
2
};
params
[
"input"
]
=
migraphx
::
argument
(
s2
,
input_data
.
data
());
params
[
"starts"
]
=
migraphx
::
argument
(
s1
,
starts_data
.
data
());
params
[
"axes"
]
=
migraphx
::
argument
(
s1
,
axes_data
.
data
());
auto
result
=
p
.
eval
(
params
).
back
();
std
::
vector
<
int
>
gold
=
{
1
,
2
,
4
,
5
,
7
,
8
,
10
,
11
};
std
::
vector
<
int
>
results_vector
(
2
*
2
*
2
);
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
slice_var_inputs_dyn5
)
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
migraphx
::
shape
s0
{
migraphx
::
shape
::
int32_type
,
{{
2
,
4
,
{
2
,
4
}},
{
2
,
4
,
{
2
,
4
}},
{
3
,
8
}}};
auto
input
=
mm
->
add_parameter
(
"input"
,
s0
);
migraphx
::
shape
s1
{
migraphx
::
shape
::
int32_type
,
{
1
}};
auto
ends
=
mm
->
add_parameter
(
"ends"
,
s1
);
auto
axes
=
mm
->
add_parameter
(
"axes"
,
s1
);
mm
->
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"starts"
,
{
-
4
}}}),
input
,
ends
,
axes
);
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
migraphx
::
parameter_map
params
;
migraphx
::
shape
s2
{
migraphx
::
shape
::
int32_type
,
{
2
,
2
,
3
}};
std
::
vector
<
int
>
input_data
(
2
*
2
*
3
);
std
::
iota
(
input_data
.
begin
(),
input_data
.
end
(),
0
);
std
::
vector
<
int
>
ends_data
=
{
2
};
std
::
vector
<
int
>
axes_data
=
{
2
};
params
[
"input"
]
=
migraphx
::
argument
(
s2
,
input_data
.
data
());
params
[
"ends"
]
=
migraphx
::
argument
(
s1
,
ends_data
.
data
());
params
[
"axes"
]
=
migraphx
::
argument
(
s1
,
axes_data
.
data
());
auto
result
=
p
.
eval
(
params
).
back
();
std
::
vector
<
int
>
gold
=
{
0
,
1
,
3
,
4
,
6
,
7
,
9
,
10
};
std
::
vector
<
int
>
results_vector
(
2
*
2
*
2
);
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
slice_var_inputs_dyn6
)
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
...
...
test/ref/unique.cpp
0 → 100644
View file @
664b2f7c
/*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 Advanced Micro Devices, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <migraphx/instruction.hpp>
#include <migraphx/literal.hpp>
#include <migraphx/make_op.hpp>
#include <migraphx/onnx.hpp>
#include <migraphx/register_target.hpp>
#include <migraphx/verify.hpp>
#include <optional>
#include <test.hpp>
namespace
{
migraphx
::
program
create_program
(
const
migraphx
::
shape
&
data_shape
,
int64_t
sorted
,
std
::
optional
<
int64_t
>
axis
)
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
auto
data
=
mm
->
add_parameter
(
"X"
,
data_shape
);
auto
op
=
axis
?
migraphx
::
make_op
(
"unique"
,
{{
"axis"
,
*
axis
},
{
"sorted"
,
sorted
}})
:
migraphx
::
make_op
(
"unique"
,
{{
"sorted"
,
sorted
}});
auto
r
=
mm
->
add_instruction
(
op
,
data
);
auto
r0
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"get_tuple_elem"
,
{{
"index"
,
0
}}),
r
);
auto
r1
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"get_tuple_elem"
,
{{
"index"
,
1
}}),
r
);
auto
r2
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"get_tuple_elem"
,
{{
"index"
,
2
}}),
r
);
auto
r3
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"get_tuple_elem"
,
{{
"index"
,
3
}}),
r
);
mm
->
add_return
({
r0
,
r1
,
r2
,
r3
});
return
p
;
};
template
<
typename
T
>
auto
run_program
(
T
&
data
,
const
migraphx
::
shape
&
data_shape
,
int
sorted
,
std
::
optional
<
int64_t
>
axis
=
std
::
nullopt
)
{
auto
p
=
create_program
(
data_shape
,
sorted
,
axis
);
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
migraphx
::
parameter_map
pp
;
pp
[
"X"
]
=
migraphx
::
argument
(
data_shape
,
data
.
data
());
auto
rets
=
p
.
eval
(
pp
);
std
::
vector
<
typename
std
::
remove_reference_t
<
decltype
(
data
)
>::
value_type
>
y
;
rets
[
0
].
visit
([
&
](
auto
v
)
{
y
.
assign
(
v
.
begin
(),
v
.
end
());
});
std
::
vector
<
int64_t
>
y_idx
;
rets
[
1
].
visit
([
&
](
auto
v
)
{
y_idx
.
assign
(
v
.
begin
(),
v
.
end
());
});
std
::
vector
<
int64_t
>
x_rev_idx
;
rets
[
2
].
visit
([
&
](
auto
v
)
{
x_rev_idx
.
assign
(
v
.
begin
(),
v
.
end
());
});
std
::
vector
<
int64_t
>
y_ct
;
rets
[
3
].
visit
([
&
](
auto
v
)
{
y_ct
.
assign
(
v
.
begin
(),
v
.
end
());
});
return
std
::
make_tuple
(
y
,
y_idx
,
x_rev_idx
,
y_ct
);
}
}
// namespace
// sorted. single entry
TEST_CASE
(
unique_sorted_single_entry_test
)
{
std
::
vector
<
int
>
data
=
{
2
};
int64_t
axis
=
0
;
int64_t
sorted
=
1
;
std
::
vector
<
size_t
>
lens
=
{
1
};
migraphx
::
shape
data_shape
{
migraphx
::
shape
::
int32_type
,
lens
};
const
auto
&
[
y
,
idx
,
x_rev
,
ct
]
=
run_program
(
data
,
data_shape
,
sorted
,
axis
);
std
::
vector
<
int
>
gold_val
=
{
2
};
EXPECT
(
y
==
gold_val
);
std
::
vector
<
int64_t
>
gold_y_idx
=
{
0
};
EXPECT
(
idx
==
gold_y_idx
);
std
::
vector
<
int64_t
>
gold_x_rev
=
{
0
};
EXPECT
(
x_rev
==
gold_x_rev
);
std
::
vector
<
int64_t
>
gold_ct
=
{
1
};
EXPECT
(
ct
==
gold_ct
);
}
// unsorted. single entry
TEST_CASE
(
unique_unsorted_single_entry_test
)
{
std
::
vector
<
float
>
data
=
{
3.33
};
int64_t
axis
=
-
1
;
int64_t
sorted
=
0
;
std
::
vector
<
size_t
>
lens
=
{
1
};
migraphx
::
shape
data_shape
{
migraphx
::
shape
::
float_type
,
lens
};
const
auto
&
[
y
,
idx
,
x_rev
,
ct
]
=
run_program
(
data
,
data_shape
,
sorted
,
axis
);
std
::
vector
<
float
>
gold_val
=
{
3.33
};
EXPECT
(
y
==
gold_val
);
std
::
vector
<
int64_t
>
gold_y_idx
=
{
0
};
EXPECT
(
idx
==
gold_y_idx
);
std
::
vector
<
int64_t
>
gold_x_rev
=
{
0
};
EXPECT
(
x_rev
==
gold_x_rev
);
std
::
vector
<
int64_t
>
gold_ct
=
{
1
};
EXPECT
(
ct
==
gold_ct
);
}
// case 2 sorted. all unique input..
TEST_CASE
(
unique_sorted_all_unique_test
)
{
std
::
vector
<
float
>
data
=
{
2.1
,
2.3
,
2.4
,
2.5
,
1.9
};
int64_t
axis
=
0
;
int64_t
sorted
=
1
;
std
::
vector
<
size_t
>
lens
=
{
5
};
migraphx
::
shape
data_shape
{
migraphx
::
shape
::
float_type
,
lens
};
const
auto
&
[
y
,
idx
,
x_rev
,
ct
]
=
run_program
(
data
,
data_shape
,
sorted
,
axis
);
std
::
vector
<
float
>
gold_val
=
{
1.9
,
2.1
,
2.3
,
2.4
,
2.5
};
EXPECT
(
y
==
gold_val
);
std
::
vector
<
int64_t
>
gold_y_idx
=
{
4
,
0
,
1
,
2
,
3
};
EXPECT
(
idx
==
gold_y_idx
);
std
::
vector
<
int64_t
>
gold_x_rev
=
{
1
,
2
,
3
,
4
,
0
};
EXPECT
(
x_rev
==
gold_x_rev
);
std
::
vector
<
int64_t
>
gold_ct
=
{
1
,
1
,
1
,
1
,
1
};
EXPECT
(
ct
==
gold_ct
);
}
// case 3 unsorted. all unique input
TEST_CASE
(
unique_unsorted_all_unique_test
)
{
std
::
vector
<
float
>
data
=
{
2.1
,
2.3
,
2.4
,
2.5
,
1.9
};
int64_t
axis
=
0
;
int64_t
sorted
=
0
;
std
::
vector
<
size_t
>
lens
=
{
5
};
migraphx
::
shape
data_shape
{
migraphx
::
shape
::
float_type
,
lens
};
const
auto
&
[
y
,
idx
,
x_rev
,
ct
]
=
run_program
(
data
,
data_shape
,
sorted
,
axis
);
std
::
vector
<
float
>
gold_val
=
{
2.1
,
2.3
,
2.4
,
2.5
,
1.9
};
EXPECT
(
y
==
gold_val
);
std
::
vector
<
int64_t
>
gold_y_idx
=
{
0
,
1
,
2
,
3
,
4
};
EXPECT
(
idx
==
gold_y_idx
);
std
::
vector
<
int64_t
>
gold_x_rev
=
{
0
,
1
,
2
,
3
,
4
};
EXPECT
(
x_rev
==
gold_x_rev
);
std
::
vector
<
int64_t
>
gold_ct
=
{
1
,
1
,
1
,
1
,
1
};
EXPECT
(
ct
==
gold_ct
);
}
// case 4 sorted (with dup entries)
TEST_CASE
(
unique_sorted_dupes_test
)
{
std
::
vector
<
double
>
data
=
{
2.1
,
2.3
,
2.4
,
2.5
,
1.9
,
2.5
,
2.3
,
2.5
};
int64_t
axis
=
0
;
int64_t
sorted
=
1
;
std
::
vector
<
size_t
>
lens
=
{
8
};
migraphx
::
shape
data_shape
{
migraphx
::
shape
::
double_type
,
lens
};
const
auto
&
[
y
,
idx
,
x_rev
,
ct
]
=
run_program
(
data
,
data_shape
,
sorted
,
axis
);
std
::
vector
<
double
>
gold_val
=
{
1.9
,
2.1
,
2.3
,
2.4
,
2.5
};
EXPECT
(
y
==
gold_val
);
std
::
vector
<
int64_t
>
gold_ct
=
{
1
,
1
,
2
,
1
,
3
};
EXPECT
(
ct
==
gold_ct
);
}
// case 5 unsorted (with dup entries)
TEST_CASE
(
unique_unsorted_dupes_test
)
{
std
::
vector
<
float
>
data
=
{
2.1
,
2.3
,
2.4
,
2.5
,
1.9
,
2.5
,
2.3
,
2.1
};
int64_t
axis
=
-
1
;
int64_t
sorted
=
0
;
std
::
vector
<
size_t
>
lens
=
{
8
};
migraphx
::
shape
data_shape
{
migraphx
::
shape
::
float_type
,
lens
};
const
auto
&
[
y
,
idx
,
x_rev
,
ct
]
=
run_program
(
data
,
data_shape
,
sorted
,
axis
);
std
::
vector
<
float
>
gold_val
=
{
2.1
,
2.3
,
2.4
,
2.5
,
1.9
};
EXPECT
(
y
==
gold_val
);
std
::
vector
<
int64_t
>
gold_y_idx
=
{
0
,
1
,
2
,
3
,
4
};
EXPECT
(
idx
==
gold_y_idx
);
std
::
vector
<
int64_t
>
gold_x_rev
=
{
0
,
1
,
2
,
3
,
4
,
3
,
1
,
0
};
EXPECT
(
x_rev
==
gold_x_rev
);
std
::
vector
<
int64_t
>
gold_ct
=
{
2
,
2
,
1
,
2
,
1
};
EXPECT
(
ct
==
gold_ct
);
}
TEST_CASE
(
unique_3D_no_axis_test
)
{
// sorted 3D (with dup entries). no axis
int
sorted
=
1
;
std
::
vector
<
double
>
data_3d
=
{
2.1
,
2.3
,
2.4
,
2.5
,
1.9
,
2.5
,
2.3
,
2.5
};
std
::
vector
<
size_t
>
lens
=
{
2
,
2
,
2
};
// 3D data. type double
migraphx
::
shape
data_shape
{
migraphx
::
shape
::
double_type
,
lens
};
const
auto
&
[
y
,
idx
,
x_rev
,
ct
]
=
run_program
(
data_3d
,
data_shape
,
sorted
);
std
::
vector
<
double
>
gold_val
=
{
1.9
,
2.1
,
2.3
,
2.4
,
2.5
};
EXPECT
(
y
==
gold_val
);
std
::
vector
<
int64_t
>
gold_ct
=
{
1
,
1
,
2
,
1
,
3
};
EXPECT
(
ct
==
gold_ct
);
}
TEST_CASE
(
unique_3D_no_axis_unsorted_test
)
// unsorted 3D (with dup entries). no axis
{
int
sorted
=
0
;
std
::
vector
<
float
>
data
=
{
2.1
,
2.3
,
2.4
,
2.5
,
1.9
,
2.5
,
2.3
,
2.1
};
std
::
vector
<
size_t
>
lens
=
{
2
,
1
,
4
};
// 3D data. type float
migraphx
::
shape
data_shape
{
migraphx
::
shape
::
float_type
,
lens
};
const
auto
&
[
y
,
idx
,
x_rev
,
ct
]
=
run_program
(
data
,
data_shape
,
sorted
);
std
::
vector
<
float
>
gold_val
=
{
2.1
,
2.3
,
2.4
,
2.5
,
1.9
};
EXPECT
(
y
==
gold_val
);
std
::
vector
<
int64_t
>
gold_y_idx
=
{
0
,
1
,
2
,
3
,
4
};
EXPECT
(
idx
==
gold_y_idx
);
std
::
vector
<
int64_t
>
gold_x_rev
=
{
0
,
1
,
2
,
3
,
4
,
3
,
1
,
0
};
EXPECT
(
x_rev
==
gold_x_rev
);
std
::
vector
<
int64_t
>
gold_ct
=
{
2
,
2
,
1
,
2
,
1
};
EXPECT
(
ct
==
gold_ct
);
}
// unique integer sub-tensors: sorted (with dup entries)
TEST_CASE
(
unique_subtensors_sorted_test
)
{
/*
input_X = [[1, 0, 0], [1, 0, 0], [2, 3, 4]]
attribute_sorted = 1
attribute_axis = 0
output_Y = [[1, 0, 0], [2, 3, 4]]
output_indices = [0, 2]
output_inverse_indices = [0, 0, 1]
output_counts = [2, 1]
*/
int
axis
=
0
;
int
sorted
=
1
;
std
::
vector
<
int32_t
>
data
=
{
1
,
0
,
0
,
1
,
0
,
0
,
2
,
3
,
4
};
std
::
vector
<
size_t
>
lens
=
{
3
,
3
};
migraphx
::
shape
data_shape
{
migraphx
::
shape
::
int32_type
,
lens
};
const
auto
&
[
y
,
idx
,
x_rev
,
ct
]
=
run_program
(
data
,
data_shape
,
sorted
,
axis
);
std
::
vector
<
int32_t
>
gold_val
=
{
1
,
0
,
0
,
2
,
3
,
4
};
EXPECT
(
y
==
gold_val
);
std
::
vector
<
int64_t
>
gold_y_idx
=
{
0
,
2
};
EXPECT
(
idx
==
gold_y_idx
);
std
::
vector
<
int64_t
>
gold_x_rev
=
{
0
,
0
,
1
};
EXPECT
(
x_rev
==
gold_x_rev
);
std
::
vector
<
int64_t
>
gold_ct
=
{
2
,
1
};
EXPECT
(
ct
==
gold_ct
);
}
// unique integer sub-tensors: un-sorted (with dup entries)
TEST_CASE
(
unique_subtensors_neg_axis_test
)
{
/*
input_X = [[1, 0, 0], [1, 0, 0], [2, 3, 4]]
attribute_sorted = 0
attribute_axis = 0
output_Y = [[1, 0, 0], [2, 3, 4]]
output_indices = [0, 2]
output_inverse_indices = [0, 0, 1]
output_counts = [2, 1]
*/
int
axis
=
-
2
;
// == 0
int
sorted
=
0
;
std
::
vector
<
int32_t
>
data
=
{
1
,
0
,
0
,
1
,
0
,
0
,
2
,
3
,
4
};
std
::
vector
<
size_t
>
lens
=
{
3
,
3
};
migraphx
::
shape
data_shape
{
migraphx
::
shape
::
int32_type
,
lens
};
const
auto
&
[
y
,
idx
,
x_rev
,
ct
]
=
run_program
(
data
,
data_shape
,
sorted
,
axis
);
std
::
vector
<
int32_t
>
gold_val
=
{
1
,
0
,
0
,
2
,
3
,
4
};
EXPECT
(
y
==
gold_val
);
std
::
vector
<
int64_t
>
gold_y_idx
=
{
0
,
2
};
EXPECT
(
idx
==
gold_y_idx
);
std
::
vector
<
int64_t
>
gold_x_rev
=
{
0
,
0
,
1
};
EXPECT
(
x_rev
==
gold_x_rev
);
std
::
vector
<
int64_t
>
gold_ct
=
{
2
,
1
};
EXPECT
(
ct
==
gold_ct
);
}
// unique float sub-tensors: sorted (with dup entries) axis = 0
TEST_CASE
(
unique_subtensors_zero_axis_test
)
{
/*
input_x = [[[1., 1.], [0., 1.], [2., 1.], [0., 1.]],
[[1., 1.], [0., 1.], [2., 1.], [0., 1.]]]
attribute_sorted = 1
attribute_axis = 0
*/
int
axis
=
0
;
int
sorted
=
1
;
std
::
vector
<
float
>
data
=
{
1.
,
1.
,
0.
,
1.
,
2.
,
1.
,
0.
,
1.
,
1.
,
1.
,
0.
,
1.
,
2.
,
1.
,
0.
,
1.
};
std
::
vector
<
size_t
>
lens
=
{
2
,
4
,
2
};
migraphx
::
shape
data_shape
{
migraphx
::
shape
::
float_type
,
lens
};
const
auto
&
[
y
,
idx
,
x_rev
,
ct
]
=
run_program
(
data
,
data_shape
,
sorted
,
axis
);
std
::
vector
<
float
>
gold_val
=
{
1.
,
1.
,
0.
,
1.
,
2.
,
1.
,
0.
,
1.
};
EXPECT
(
y
==
gold_val
);
std
::
vector
<
int64_t
>
gold_y_idx
=
{
0
};
EXPECT
(
idx
==
gold_y_idx
);
std
::
vector
<
int64_t
>
gold_x_rev
=
{
0
,
0
};
EXPECT
(
x_rev
==
gold_x_rev
);
std
::
vector
<
int64_t
>
gold_ct
=
{
2
};
EXPECT
(
ct
==
gold_ct
);
}
test/rewrite_pooling_test.cpp
View file @
664b2f7c
...
...
@@ -53,7 +53,8 @@ TEST_CASE(rewrite_pooling_test)
{{
"mode"
,
mode
},
{
"padding"
,
{
0
,
0
,
0
}},
{
"stride"
,
{
1
,
1
,
1
}},
{
"lengths"
,
{
3
,
4
,
5
}}}),
{
"lengths"
,
{
3
,
4
,
5
}},
{
"dilations"
,
{
1
,
1
,
1
}}}),
input
);
m
.
add_return
({
ret
});
return
m
;
...
...
@@ -80,6 +81,483 @@ TEST_CASE(rewrite_pooling_test)
migraphx
::
make_op
(
"reduce_max"
,
{{
"axes"
,
{
2
,
3
,
4
}}}));
}
TEST_CASE
(
rewrite_pooling_dialtions_test
)
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
1
,
1
,
5
,
5
}};
auto
pooling_program
=
[
&
](
const
migraphx
::
op
::
pooling_mode
mode
)
{
migraphx
::
module
m
;
auto
input
=
m
.
add_parameter
(
"x"
,
s
);
auto
ret
=
m
.
add_instruction
(
migraphx
::
make_op
(
"pooling"
,
{{
"mode"
,
mode
},
{
"padding"
,
{
0
,
0
}},
{
"stride"
,
{
1
,
1
}},
{
"lengths"
,
{
2
,
2
}},
{
"dilations"
,
{
2
,
2
}}}),
input
);
m
.
add_return
({
ret
});
return
m
;
};
auto
opt_program
=
[
&
](
const
migraphx
::
op
::
pooling_mode
mode
)
{
migraphx
::
module
m
;
auto
input
=
m
.
add_parameter
(
"x"
,
s
);
std
::
vector
<
int
>
indices
{
0
,
2
,
1
,
3
,
2
,
4
};
migraphx
::
shape
s_indices
{
migraphx
::
shape
::
int32_type
,
{
indices
.
size
()}};
auto
i1
=
m
.
add_literal
(
migraphx
::
literal
{
s_indices
,
indices
});
auto
g1
=
m
.
add_instruction
(
migraphx
::
make_op
(
"gather"
,
{{
"axis"
,
2
}}),
input
,
i1
);
auto
i2
=
m
.
add_literal
(
migraphx
::
literal
{
s_indices
,
indices
});
auto
g2
=
m
.
add_instruction
(
migraphx
::
make_op
(
"gather"
,
{{
"axis"
,
3
}}),
g1
,
i2
);
auto
ret
=
m
.
add_instruction
(
migraphx
::
make_op
(
"pooling"
,
{{
"mode"
,
mode
},
{
"padding"
,
{
0
,
0
}},
{
"stride"
,
{
2
,
2
}},
{
"lengths"
,
{
2
,
2
}},
{
"dilations"
,
{
1
,
1
}}}),
g2
);
m
.
add_return
({
ret
});
return
m
;
};
auto
test_rewrite
=
[
&
](
const
migraphx
::
op
::
pooling_mode
mode
)
{
migraphx
::
module
m1
=
pooling_program
(
mode
);
migraphx
::
module
m2
=
opt_program
(
mode
);
opt_pooling
(
m1
);
EXPECT
(
m1
==
m2
);
};
test_rewrite
(
migraphx
::
op
::
pooling_mode
::
average
);
test_rewrite
(
migraphx
::
op
::
pooling_mode
::
max
);
}
TEST_CASE
(
rewrite_pooling_dialtions_test2
)
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
1
,
1
,
5
,
5
,
5
}};
auto
pooling_program
=
[
&
](
const
migraphx
::
op
::
pooling_mode
mode
)
{
migraphx
::
module
m
;
auto
input
=
m
.
add_parameter
(
"x"
,
s
);
auto
ret
=
m
.
add_instruction
(
migraphx
::
make_op
(
"pooling"
,
{{
"mode"
,
mode
},
{
"padding"
,
{
0
,
0
,
0
}},
{
"stride"
,
{
1
,
1
,
1
}},
{
"lengths"
,
{
2
,
2
,
2
}},
{
"dilations"
,
{
2
,
2
,
2
}}}),
input
);
m
.
add_return
({
ret
});
return
m
;
};
auto
opt_program
=
[
&
](
const
migraphx
::
op
::
pooling_mode
mode
)
{
migraphx
::
module
m
;
auto
input
=
m
.
add_parameter
(
"x"
,
s
);
std
::
vector
<
int
>
indices
{
0
,
2
,
1
,
3
,
2
,
4
};
migraphx
::
shape
s_indices
{
migraphx
::
shape
::
int32_type
,
{
indices
.
size
()}};
auto
i1
=
m
.
add_literal
(
migraphx
::
literal
{
s_indices
,
indices
});
auto
g1
=
m
.
add_instruction
(
migraphx
::
make_op
(
"gather"
,
{{
"axis"
,
2
}}),
input
,
i1
);
auto
i2
=
m
.
add_literal
(
migraphx
::
literal
{
s_indices
,
indices
});
auto
g2
=
m
.
add_instruction
(
migraphx
::
make_op
(
"gather"
,
{{
"axis"
,
3
}}),
g1
,
i2
);
auto
i3
=
m
.
add_literal
(
migraphx
::
literal
{
s_indices
,
indices
});
auto
g3
=
m
.
add_instruction
(
migraphx
::
make_op
(
"gather"
,
{{
"axis"
,
4
}}),
g2
,
i3
);
auto
ret
=
m
.
add_instruction
(
migraphx
::
make_op
(
"pooling"
,
{{
"mode"
,
mode
},
{
"padding"
,
{
0
,
0
,
0
}},
{
"stride"
,
{
2
,
2
,
2
}},
{
"lengths"
,
{
2
,
2
,
2
}},
{
"dilations"
,
{
1
,
1
,
1
}}}),
g3
);
m
.
add_return
({
ret
});
return
m
;
};
auto
test_rewrite
=
[
&
](
const
migraphx
::
op
::
pooling_mode
mode
)
{
migraphx
::
module
m1
=
pooling_program
(
mode
);
migraphx
::
module
m2
=
opt_program
(
mode
);
opt_pooling
(
m1
);
EXPECT
(
m1
==
m2
);
};
test_rewrite
(
migraphx
::
op
::
pooling_mode
::
average
);
test_rewrite
(
migraphx
::
op
::
pooling_mode
::
max
);
}
TEST_CASE
(
rewrite_pooling_dialtions_test3
)
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
2
,
2
,
5
}};
auto
pooling_program
=
[
&
]()
{
migraphx
::
module
m
;
auto
input
=
m
.
add_parameter
(
"x"
,
s
);
auto
ret
=
m
.
add_instruction
(
migraphx
::
make_op
(
"pooling"
,
{{
"mode"
,
migraphx
::
op
::
pooling_mode
::
average
},
{
"padding"
,
{
1
}},
{
"stride"
,
{
1
}},
{
"lengths"
,
{
3
}},
{
"dilations"
,
{
2
}}}),
input
);
m
.
add_return
({
ret
});
return
m
;
};
migraphx
::
module
m1
=
pooling_program
();
migraphx
::
module
m2
=
m1
;
opt_pooling
(
m1
);
EXPECT
(
m1
==
m2
);
}
TEST_CASE
(
rewrite_pooling_dialtions_test4
)
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
1
,
1
,
5
,
5
}};
auto
pooling_program
=
[
&
](
const
migraphx
::
op
::
pooling_mode
mode
)
{
migraphx
::
module
m
;
auto
input
=
m
.
add_parameter
(
"x"
,
s
);
auto
ret
=
m
.
add_instruction
(
migraphx
::
make_op
(
"pooling"
,
{{
"mode"
,
mode
},
{
"padding"
,
{
1
,
0
}},
{
"stride"
,
{
1
,
3
}},
{
"lengths"
,
{
3
,
1
}},
{
"dilations"
,
{
1
,
2
}}}),
input
);
m
.
add_return
({
ret
});
return
m
;
};
auto
opt_program
=
[
&
](
const
migraphx
::
op
::
pooling_mode
mode
)
{
migraphx
::
module
m
;
auto
input
=
m
.
add_parameter
(
"x"
,
s
);
std
::
vector
<
int
>
col_indices
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
11
,
12
,
13
,
14
};
migraphx
::
shape
s_col_indices
{
migraphx
::
shape
::
int32_type
,
{
col_indices
.
size
()}};
std
::
vector
<
int
>
row_indices
{
0
,
3
};
migraphx
::
shape
s_row_indices
{
migraphx
::
shape
::
int32_type
,
{
row_indices
.
size
()}};
auto
p
=
m
.
add_instruction
(
migraphx
::
make_op
(
"pad"
,
{{
"pads"
,
{
0
,
0
,
1
,
0
,
0
,
0
,
1
,
0
}},
{
"value"
,
std
::
numeric_limits
<
float
>::
lowest
()}}),
input
);
auto
i1
=
m
.
add_literal
(
migraphx
::
literal
{
s_col_indices
,
col_indices
});
auto
g1
=
m
.
add_instruction
(
migraphx
::
make_op
(
"gather"
,
{{
"axis"
,
2
}}),
p
,
i1
);
auto
i2
=
m
.
add_literal
(
migraphx
::
literal
{
s_row_indices
,
row_indices
});
auto
g2
=
m
.
add_instruction
(
migraphx
::
make_op
(
"gather"
,
{{
"axis"
,
3
}}),
g1
,
i2
);
auto
ret
=
m
.
add_instruction
(
migraphx
::
make_op
(
"pooling"
,
{{
"mode"
,
mode
},
{
"padding"
,
{
0
,
0
}},
{
"stride"
,
{
3
,
1
}},
{
"lengths"
,
{
3
,
1
}},
{
"dilations"
,
{
1
,
1
}}}),
g2
);
m
.
add_return
({
ret
});
return
m
;
};
auto
test_rewrite
=
[
&
](
const
migraphx
::
op
::
pooling_mode
mode
)
{
migraphx
::
module
m1
=
pooling_program
(
mode
);
migraphx
::
module
m2
=
opt_program
(
mode
);
opt_pooling
(
m1
);
EXPECT
(
m1
==
m2
);
};
// Average won't work because of padding
test_rewrite
(
migraphx
::
op
::
pooling_mode
::
max
);
}
TEST_CASE
(
rewrite_pooling_dialtions_test5
)
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
1
,
1
,
5
,
5
}};
auto
pooling_program
=
[
&
](
const
migraphx
::
op
::
pooling_mode
mode
)
{
migraphx
::
module
m
;
auto
input
=
m
.
add_parameter
(
"x"
,
s
);
auto
ret
=
m
.
add_instruction
(
migraphx
::
make_op
(
"pooling"
,
{{
"mode"
,
mode
},
{
"padding"
,
{
0
,
0
}},
{
"stride"
,
{
2
,
3
}},
{
"lengths"
,
{
2
,
1
}},
{
"dilations"
,
{
1
,
2
}}}),
input
);
m
.
add_return
({
ret
});
return
m
;
};
auto
opt_program
=
[
&
](
const
migraphx
::
op
::
pooling_mode
mode
)
{
migraphx
::
module
m
;
auto
input
=
m
.
add_parameter
(
"x"
,
s
);
std
::
vector
<
int
>
col_indices
{
0
,
1
,
2
,
3
};
migraphx
::
shape
s_col_indices
{
migraphx
::
shape
::
int32_type
,
{
col_indices
.
size
()}};
std
::
vector
<
int
>
row_indices
{
0
,
3
};
migraphx
::
shape
s_row_indices
{
migraphx
::
shape
::
int32_type
,
{
row_indices
.
size
()}};
auto
i1
=
m
.
add_literal
(
migraphx
::
literal
{
s_col_indices
,
col_indices
});
auto
g1
=
m
.
add_instruction
(
migraphx
::
make_op
(
"gather"
,
{{
"axis"
,
2
}}),
input
,
i1
);
auto
i2
=
m
.
add_literal
(
migraphx
::
literal
{
s_row_indices
,
row_indices
});
auto
g2
=
m
.
add_instruction
(
migraphx
::
make_op
(
"gather"
,
{{
"axis"
,
3
}}),
g1
,
i2
);
auto
ret
=
m
.
add_instruction
(
migraphx
::
make_op
(
"pooling"
,
{{
"mode"
,
mode
},
{
"padding"
,
{
0
,
0
}},
{
"stride"
,
{
2
,
1
}},
{
"lengths"
,
{
2
,
1
}},
{
"dilations"
,
{
1
,
1
}}}),
g2
);
m
.
add_return
({
ret
});
return
m
;
};
auto
test_rewrite
=
[
&
](
const
migraphx
::
op
::
pooling_mode
mode
)
{
migraphx
::
module
m1
=
pooling_program
(
mode
);
migraphx
::
module
m2
=
opt_program
(
mode
);
opt_pooling
(
m1
);
EXPECT
(
m1
==
m2
);
};
test_rewrite
(
migraphx
::
op
::
pooling_mode
::
average
);
test_rewrite
(
migraphx
::
op
::
pooling_mode
::
max
);
}
TEST_CASE
(
rewrite_avgpool_rank3_dil_test
)
{
// 1D case 1, input is 3D
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
auto
s
=
migraphx
::
shape
{
migraphx
::
shape
::
float_type
,
{
1
,
3
,
4
}};
auto
op
=
migraphx
::
op
::
pooling
{
migraphx
::
op
::
pooling_mode
::
average
};
op
.
lengths
=
{
2
};
op
.
padding
=
{
0
};
op
.
stride
=
{
1
};
op
.
dilations
=
{
2
};
std
::
vector
<
float
>
data
{
0.3
,
0.2
,
0.4
,
0.1
,
0.8
,
0.5
,
0.9
,
0.1
,
0.1
,
0.7
,
0.1
,
0.6
};
auto
l0
=
mm
->
add_literal
(
migraphx
::
literal
{
s
,
data
});
mm
->
add_instruction
(
op
,
l0
);
opt_pooling
(
*
mm
);
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
auto
result
=
p
.
eval
({}).
back
();
std
::
vector
<
float
>
results_vector
;
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
std
::
vector
<
float
>
gold
{
0.35
,
0.15
,
0.85
,
0.3
,
0.1
,
0.65
};
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
rewrite_avgpool_rank3_dil_test2
)
{
// 1D case 1, input is 3D
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
auto
s
=
migraphx
::
shape
{
migraphx
::
shape
::
float_type
,
{
1
,
3
,
4
}};
auto
op
=
migraphx
::
op
::
pooling
{
migraphx
::
op
::
pooling_mode
::
average
};
op
.
lengths
=
{
2
};
op
.
padding
=
{
0
};
op
.
stride
=
{
1
};
op
.
dilations
=
{
3
};
std
::
vector
<
float
>
data
{
0.3
,
0.2
,
0.4
,
0.1
,
0.8
,
0.5
,
0.9
,
0.1
,
0.1
,
0.7
,
0.1
,
0.6
};
auto
l0
=
mm
->
add_literal
(
migraphx
::
literal
{
s
,
data
});
mm
->
add_instruction
(
op
,
l0
);
opt_pooling
(
*
mm
);
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
auto
result
=
p
.
eval
({}).
back
();
std
::
vector
<
float
>
results_vector
;
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
std
::
vector
<
float
>
gold
{
0.2
,
0.45
,
0.35
};
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
rewrite_avgpool_rank4_test
)
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
auto
s
=
migraphx
::
shape
{
migraphx
::
shape
::
float_type
,
{
1
,
1
,
5
,
5
}};
auto
op
=
migraphx
::
op
::
pooling
{
migraphx
::
op
::
pooling_mode
::
average
};
op
.
lengths
=
{
2
,
1
};
op
.
padding
=
{
0
,
0
};
op
.
stride
=
{
2
,
3
};
op
.
dilations
=
{
1
,
2
};
std
::
vector
<
float
>
data
(
25
);
std
::
iota
(
data
.
begin
(),
data
.
end
(),
1
);
auto
l0
=
mm
->
add_literal
(
migraphx
::
literal
{
s
,
data
});
mm
->
add_instruction
(
op
,
l0
);
opt_pooling
(
*
mm
);
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
auto
result
=
p
.
eval
({}).
back
();
std
::
vector
<
float
>
results_vector
;
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
std
::
vector
<
float
>
gold
{
3.5
,
6.5
,
13.5
,
16.5
};
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
rewrite_maxpool_rank3_test
)
{
// 1D case 1, input is 3D
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
auto
s
=
migraphx
::
shape
{
migraphx
::
shape
::
float_type
,
{
1
,
3
,
4
}};
auto
op
=
migraphx
::
op
::
pooling
{
migraphx
::
op
::
pooling_mode
::
max
};
op
.
lengths
=
{
2
};
op
.
padding
=
{
0
};
op
.
stride
=
{
1
};
op
.
dilations
=
{
2
};
std
::
vector
<
float
>
data
{
0.3
,
0.2
,
0.4
,
0.1
,
0.8
,
0.5
,
0.9
,
0.1
,
0.1
,
0.7
,
0.1
,
0.6
};
auto
l0
=
mm
->
add_literal
(
migraphx
::
literal
{
s
,
data
});
mm
->
add_instruction
(
op
,
l0
);
opt_pooling
(
*
mm
);
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
auto
result
=
p
.
eval
({}).
back
();
std
::
vector
<
float
>
results_vector
;
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
std
::
vector
<
float
>
gold
{
0.4
,
0.2
,
0.9
,
0.5
,
0.1
,
0.7
};
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
rewrite_maxpool_rank3_test2
)
{
// 1D case 1, input is 3D
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
auto
s
=
migraphx
::
shape
{
migraphx
::
shape
::
float_type
,
{
1
,
3
,
4
}};
auto
op
=
migraphx
::
op
::
pooling
{
migraphx
::
op
::
pooling_mode
::
max
};
op
.
lengths
=
{
2
};
op
.
padding
=
{
1
};
op
.
stride
=
{
1
};
op
.
dilations
=
{
3
};
std
::
vector
<
float
>
data
{
0.3
,
0.2
,
0.4
,
0.1
,
0.8
,
0.5
,
0.9
,
0.1
,
0.1
,
0.7
,
0.1
,
0.6
};
auto
l0
=
mm
->
add_literal
(
migraphx
::
literal
{
s
,
data
});
mm
->
add_instruction
(
op
,
l0
);
opt_pooling
(
*
mm
);
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
auto
result
=
p
.
eval
({}).
back
();
std
::
vector
<
float
>
results_vector
;
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
std
::
vector
<
float
>
gold
{
0.4
,
0.3
,
0.2
,
0.9
,
0.8
,
0.5
,
0.1
,
0.6
,
0.7
};
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
rewrite_maxpool_rank3_test3
)
{
// 1D case 1, input is 3D
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
auto
s
=
migraphx
::
shape
{
migraphx
::
shape
::
float_type
,
{
1
,
3
,
4
}};
auto
op
=
migraphx
::
op
::
pooling
{
migraphx
::
op
::
pooling_mode
::
max
};
op
.
lengths
=
{
3
};
op
.
padding
=
{
2
};
op
.
stride
=
{
2
};
op
.
dilations
=
{
3
};
std
::
vector
<
float
>
data
{
0.3
,
0.2
,
0.4
,
0.1
,
0.8
,
0.5
,
0.9
,
0.1
,
0.1
,
0.7
,
0.1
,
0.6
};
auto
l0
=
mm
->
add_literal
(
migraphx
::
literal
{
s
,
data
});
mm
->
add_instruction
(
op
,
l0
);
opt_pooling
(
*
mm
);
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
auto
result
=
p
.
eval
({}).
back
();
std
::
vector
<
float
>
results_vector
;
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
std
::
vector
<
float
>
gold
{
0.2
,
0.5
,
0.7
};
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
rewrite_maxpool_rank4_test
)
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
auto
s
=
migraphx
::
shape
{
migraphx
::
shape
::
float_type
,
{
1
,
1
,
5
,
5
}};
auto
op
=
migraphx
::
op
::
pooling
{
migraphx
::
op
::
pooling_mode
::
max
};
op
.
lengths
=
{
3
,
1
};
op
.
padding
=
{
1
,
0
};
op
.
stride
=
{
1
,
3
};
op
.
dilations
=
{
1
,
2
};
std
::
vector
<
float
>
data
(
25
);
std
::
iota
(
data
.
begin
(),
data
.
end
(),
1
);
auto
l0
=
mm
->
add_literal
(
migraphx
::
literal
{
s
,
data
});
mm
->
add_instruction
(
op
,
l0
);
opt_pooling
(
*
mm
);
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
auto
result
=
p
.
eval
({}).
back
();
std
::
vector
<
float
>
results_vector
;
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
std
::
vector
<
float
>
gold
{
6
,
9
,
11
,
14
,
16
,
19
,
21
,
24
,
21
,
24
};
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
maxpool_rank5_test
)
{
// 3D, input is 5D
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
auto
s
=
migraphx
::
shape
{
migraphx
::
shape
::
float_type
,
{
2
,
2
,
3
,
3
,
3
}};
auto
op
=
migraphx
::
op
::
pooling
{
migraphx
::
op
::
pooling_mode
::
max
};
op
.
lengths
=
{
2
,
2
,
2
};
op
.
padding
=
{
0
,
0
,
0
};
op
.
stride
=
{
1
,
1
,
1
};
op
.
dilations
=
{
2
,
2
,
2
};
std
::
vector
<
float
>
data
{
-
2.8029
,
0.5861
,
0.7015
,
0.1297
,
-
1.44
,
-
1.9472
,
0.7812
,
2.408
,
-
0.3145
,
0.3405
,
-
0.9146
,
0.0624
,
1.5064
,
-
0.8345
,
1.7977
,
1.8949
,
1.0073
,
-
0.2102
,
-
0.042
,
-
0.7146
,
0.6227
,
-
0.5263
,
-
2.2598
,
0.1713
,
0.449
,
0.5303
,
-
0.8622
,
-
0.5691
,
0.907
,
-
0.0569
,
-
1.5348
,
-
0.4109
,
-
0.1461
,
-
0.5445
,
0.4266
,
0.2282
,
1.3655
,
-
2.1519
,
0.6068
,
-
0.2001
,
-
0.4702
,
0.3864
,
1.7083
,
0.9096
,
0.4286
,
-
1.8866
,
0.7034
,
0.0293
,
1.4587
,
0.7672
,
-
2.8614
,
0.8124
,
-
0.053
,
1.0449
,
0.845
,
-
0.0131
,
0.1139
,
-
0.859
,
-
1.2681
,
-
0.6337
,
-
0.4644
,
0.1938
,
0.2889
,
0.9035
,
0.7118
,
-
0.5767
,
0.4577
,
-
0.0549
,
0.2237
,
0.5756
,
0.0677
,
-
0.0223
,
-
0.329
,
0.2364
,
2.7666
,
-
0.7417
,
-
1.3196
,
-
0.2655
,
0.1698
,
-
0.1777
,
-
0.9427
,
2.6859
,
-
0.7501
,
0.5175
,
1.0029
,
-
2.6436
,
-
0.4388
,
-
1.2348
,
-
0.1539
,
-
0.6229
,
-
0.4136
,
0.5085
,
0.4136
,
-
0.6439
,
-
1.1953
,
-
0.406
,
-
0.0195
,
0.1869
,
-
0.8664
,
1.1364
,
0.5041
,
0.0647
,
0.1941
,
-
1.0819
,
-
0.4629
,
-
0.5107
,
0.3612
,
-
0.3583
};
auto
l0
=
mm
->
add_literal
(
migraphx
::
literal
{
s
,
data
});
mm
->
add_instruction
(
op
,
l0
);
opt_pooling
(
*
mm
);
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
auto
result
=
p
.
eval
({}).
back
();
std
::
vector
<
float
>
results_vector
;
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
std
::
vector
<
float
>
gold
{
0.7812
,
1.0449
,
2.7666
,
2.6859
};
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
maxpool_rank5_test2
)
{
// 3D, input is 5D
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
auto
s
=
migraphx
::
shape
{
migraphx
::
shape
::
float_type
,
{
2
,
2
,
3
,
3
,
3
}};
auto
op
=
migraphx
::
op
::
pooling
{
migraphx
::
op
::
pooling_mode
::
max
};
op
.
lengths
=
{
2
,
2
,
2
};
op
.
padding
=
{
2
,
2
,
2
};
op
.
stride
=
{
2
,
2
,
2
};
op
.
dilations
=
{
3
,
3
,
3
};
std
::
vector
<
float
>
data
{
-
2.8029
,
0.5861
,
0.7015
,
0.1297
,
-
1.44
,
-
1.9472
,
0.7812
,
2.408
,
-
0.3145
,
0.3405
,
-
0.9146
,
0.0624
,
1.5064
,
-
0.8345
,
1.7977
,
1.8949
,
1.0073
,
-
0.2102
,
-
0.042
,
-
0.7146
,
0.6227
,
-
0.5263
,
-
2.2598
,
0.1713
,
0.449
,
0.5303
,
-
0.8622
,
-
0.5691
,
0.907
,
-
0.0569
,
-
1.5348
,
-
0.4109
,
-
0.1461
,
-
0.5445
,
0.4266
,
0.2282
,
1.3655
,
-
2.1519
,
0.6068
,
-
0.2001
,
-
0.4702
,
0.3864
,
1.7083
,
0.9096
,
0.4286
,
-
1.8866
,
0.7034
,
0.0293
,
1.4587
,
0.7672
,
-
2.8614
,
0.8124
,
-
0.053
,
1.0449
,
0.845
,
-
0.0131
,
0.1139
,
-
0.859
,
-
1.2681
,
-
0.6337
,
-
0.4644
,
0.1938
,
0.2889
,
0.9035
,
0.7118
,
-
0.5767
,
0.4577
,
-
0.0549
,
0.2237
,
0.5756
,
0.0677
,
-
0.0223
,
-
0.329
,
0.2364
,
2.7666
,
-
0.7417
,
-
1.3196
,
-
0.2655
,
0.1698
,
-
0.1777
,
-
0.9427
,
2.6859
,
-
0.7501
,
0.5175
,
1.0029
,
-
2.6436
,
-
0.4388
,
-
1.2348
,
-
0.1539
,
-
0.6229
,
-
0.4136
,
0.5085
,
0.4136
,
-
0.6439
,
-
1.1953
,
-
0.406
,
-
0.0195
,
0.1869
,
-
0.8664
,
1.1364
,
0.5041
,
0.0647
,
0.1941
,
-
1.0819
,
-
0.4629
,
-
0.5107
,
0.3612
,
-
0.3583
};
auto
l0
=
mm
->
add_literal
(
migraphx
::
literal
{
s
,
data
});
mm
->
add_instruction
(
op
,
l0
);
opt_pooling
(
*
mm
);
p
.
compile
(
migraphx
::
make_target
(
"ref"
));
auto
result
=
p
.
eval
({}).
back
();
std
::
vector
<
float
>
results_vector
;
result
.
visit
([
&
](
auto
output
)
{
results_vector
.
assign
(
output
.
begin
(),
output
.
end
());
});
std
::
vector
<
float
>
gold
{
-
0.8345
,
1.5064
,
-
0.9146
,
0.3405
,
-
1.44
,
0.1297
,
0.5861
,
-
2.8029
,
-
0.4702
,
-
0.2001
,
-
2.1519
,
1.3655
,
-
0.4109
,
-
1.5348
,
0.907
,
-
0.5691
,
-
0.0549
,
0.4577
,
0.7118
,
0.9035
,
-
1.2681
,
-
0.859
,
-
0.0131
,
0.845
,
-
1.1953
,
-
0.6439
,
0.5085
,
-
0.4136
,
-
2.6436
,
1.0029
,
-
0.7501
,
2.6859
};
EXPECT
(
migraphx
::
verify
::
verify_rms_range
(
results_vector
,
gold
));
}
TEST_CASE
(
rewrite_avepooling_na1_test
)
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
2
,
2
,
3
,
4
,
5
}};
...
...
@@ -92,7 +570,8 @@ TEST_CASE(rewrite_avepooling_na1_test)
{{
"mode"
,
migraphx
::
op
::
pooling_mode
::
average
},
{
"padding"
,
{
0
,
1
,
0
}},
{
"stride"
,
{
1
,
1
,
1
}},
{
"lengths"
,
{
3
,
4
,
5
}}}),
{
"lengths"
,
{
3
,
4
,
5
}},
{
"dilations"
,
{
1
,
1
,
1
}}}),
input
);
m
.
add_return
({
ret
});
return
m
;
...
...
@@ -117,7 +596,8 @@ TEST_CASE(rewrite_avepooling_na2_test)
{{
"mode"
,
migraphx
::
op
::
pooling_mode
::
average
},
{
"padding"
,
{
0
,
0
,
0
}},
{
"stride"
,
{
1
,
2
,
1
}},
{
"lengths"
,
{
3
,
4
,
5
}}}),
{
"lengths"
,
{
3
,
4
,
5
}},
{
"dilations"
,
{
1
,
1
,
1
}}}),
input
);
m
.
add_return
({
ret
});
return
m
;
...
...
@@ -141,7 +621,8 @@ TEST_CASE(rewrite_avepooling_na3_test)
{{
"mode"
,
migraphx
::
op
::
pooling_mode
::
max
},
{
"padding"
,
{
0
,
0
,
0
}},
{
"stride"
,
{
1
,
1
,
1
}},
{
"lengths"
,
{
3
,
3
,
5
}}}),
{
"lengths"
,
{
3
,
3
,
5
}},
{
"dilations"
,
{
1
,
1
,
1
}}}),
input
);
m
.
add_return
({
ret
});
return
m
;
...
...
@@ -169,7 +650,8 @@ TEST_CASE(literal_rewrite_pooling_test)
{{
"mode"
,
mode
},
{
"padding"
,
{
0
,
0
,
0
}},
{
"stride"
,
{
1
,
1
,
1
}},
{
"lengths"
,
{
3
,
4
,
5
}}}),
{
"lengths"
,
{
3
,
4
,
5
}},
{
"dilations"
,
{
1
,
1
,
1
}}}),
input
);
mm
->
add_return
({
ret
});
return
p
;
...
...
test/simplify_algebra_test.cpp
View file @
664b2f7c
...
...
@@ -1017,6 +1017,40 @@ TEST_CASE(simplify_concat_add_relu_broadcast_same_axis)
EXPECT
(
m1
==
m2
);
}
TEST_CASE
(
concat_convert_fusion
)
{
auto
s
=
migraphx
::
shape
{
migraphx
::
shape
::
float_type
,
{
64
}};
migraphx
::
module
m1
;
{
auto
x
=
m1
.
add_parameter
(
"x"
,
s
);
auto
y
=
m1
.
add_parameter
(
"y"
,
s
);
auto
xh
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"convert"
,
{{
"target_type"
,
migraphx
::
to_value
(
migraphx
::
shape
::
half_type
)}}),
x
);
auto
yh
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"convert"
,
{{
"target_type"
,
migraphx
::
to_value
(
migraphx
::
shape
::
half_type
)}}),
y
);
auto
concat
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"concat"
,
{{
"axis"
,
0
}}),
xh
,
yh
);
m1
.
add_instruction
(
pass_op
{},
concat
);
}
run_pass
(
m1
);
migraphx
::
module
m2
;
{
auto
x
=
m2
.
add_parameter
(
"x"
,
s
);
auto
y
=
m2
.
add_parameter
(
"y"
,
s
);
auto
concat
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"concat"
,
{{
"axis"
,
0
}}),
x
,
y
);
auto
concath
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"convert"
,
{{
"target_type"
,
migraphx
::
to_value
(
migraphx
::
shape
::
half_type
)}}),
concat
);
m2
.
add_instruction
(
pass_op
{},
concath
);
}
EXPECT
(
m1
==
m2
);
}
TEST_CASE
(
simplify_div_const
)
{
migraphx
::
module
m1
;
...
...
@@ -1897,12 +1931,17 @@ TEST_CASE(simplify_split_add_relu_reshape)
auto
concatb
=
m2
.
add_instruction
(
b
,
concat
);
auto
sum
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"add"
),
input
,
concatb
);
auto
relu
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"relu"
),
sum
);
auto
rsp
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
,
{{
"dims"
,
{
3
,
8
}}}),
relu
);
auto
slc1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"axes"
,
{
1
}},
{
"starts"
,
{
0
}},
{
"ends"
,
{
4
}}}),
rsp
);
migraphx
::
make_op
(
"slice"
,
{{
"axes"
,
{
1
}},
{
"starts"
,
{
0
}},
{
"ends"
,
{
1
}}}),
relu
);
auto
rsp1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
,
{{
"dims"
,
{
3
,
4
}}}),
slc1
);
auto
slc2
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"axes"
,
{
1
}},
{
"starts"
,
{
4
}},
{
"ends"
,
{
8
}}}),
rsp
);
auto
add
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"add"
),
slc1
,
slc2
);
migraphx
::
make_op
(
"slice"
,
{{
"axes"
,
{
1
}},
{
"starts"
,
{
1
}},
{
"ends"
,
{
2
}}}),
relu
);
auto
rsp2
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
,
{{
"dims"
,
{
3
,
4
}}}),
slc2
);
auto
add
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"add"
),
rsp1
,
rsp2
);
m2
.
add_instruction
(
pass_op
{},
add
);
}
EXPECT
(
m1
.
sort
()
==
m2
.
sort
());
...
...
@@ -2323,9 +2362,7 @@ TEST_CASE(simplify_dot_horiz_reshape)
migraphx
::
make_op
(
"slice"
,
{{
"axes"
,
{
2
}},
{
"starts"
,
{
0
}},
{
"ends"
,
{
4
}}}),
dot
);
auto
y
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"axes"
,
{
2
}},
{
"starts"
,
{
4
}},
{
"ends"
,
{
8
}}}),
dot
);
auto
x_cont
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"contiguous"
),
x
);
auto
x_rsp
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
,
{{
"dims"
,
{
3
,
4
,
2
,
2
}}}),
x_cont
);
auto
x_rsp
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
,
{{
"dims"
,
{
3
,
4
,
2
,
2
}}}),
x
);
auto
y_rsp
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"unsqueeze"
,
{{
"axes"
,
{
2
}},
{
"steps"
,
{
2
}}}),
y
);
auto
sum
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"add"
),
{
x_rsp
,
y_rsp
});
...
...
@@ -2688,12 +2725,8 @@ void reorder_reshape_slice()
{
s
=
migraphx
::
shape
{
migraphx
::
shape
::
float_type
,
{
BS
,
128
,
1920
},
{
165120
,
1
,
128
}};
}
auto
input
=
m2
.
add_parameter
(
"input"
,
s
);
auto
rsp_input
=
input
;
if
(
TransposeInput
)
{
rsp_input
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"contiguous"
),
{
input
});
}
auto
input
=
m2
.
add_parameter
(
"input"
,
s
);
auto
rsp_input
=
input
;
std
::
vector
<
int64_t
>
lens
=
{
static_cast
<
int64_t
>
(
BS
),
128
,
30
,
64
};
auto
r
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
,
{{
"dims"
,
lens
}}),
rsp_input
);
...
...
@@ -2976,9 +3009,8 @@ TEST_CASE(reorder_reshape_slice_multi_rsp)
auto
input
=
m2
.
add_parameter
(
"input"
,
s
);
auto
t1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"transpose"
,
{{
"permutation"
,
{
2
,
0
,
3
,
1
,
4
}}}),
input
);
auto
c_t1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"contiguous"
),
t1
);
auto
rsp1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
,
{{
"dims"
,
{
384
,
128
,
80
}}}),
c_
t1
);
m2
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
,
{{
"dims"
,
{
384
,
128
,
80
}}}),
t1
);
auto
slc0
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"axes"
,
{
0
}},
{
"starts"
,
{
256
}},
{
"ends"
,
{
384
}}}),
rsp1
);
auto
slc1
=
m2
.
add_instruction
(
...
...
@@ -2993,9 +3025,8 @@ TEST_CASE(reorder_reshape_slice_multi_rsp)
auto
dot
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"dot"
),
slc2
,
c_t_slc1
);
auto
c_t1_1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"contiguous"
),
t1
);
auto
rsp2
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
,
{{
"dims"
,
{
12
,
32
,
128
,
80
}}}),
c_t1_
1
);
m2
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
,
{{
"dims"
,
{
12
,
32
,
128
,
80
}}}),
t
1
);
auto
slc2_1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"axes"
,
{
0
}},
{
"starts"
,
{
4
}},
{
"ends"
,
{
8
}}}),
rsp2
);
...
...
@@ -3372,9 +3403,8 @@ TEST_CASE(dot_fusion_reshape)
auto
s1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"axes"
,
{
2
}},
{
"starts"
,
{
320
}},
{
"ends"
,
{
640
}}}),
d
);
auto
cont0
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"contiguous"
),
s0
);
auto
r0
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
,
{{
"dims"
,
{
2
,
4096
,
8
,
40
}}}),
cont
0
);
m2
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
,
{{
"dims"
,
{
2
,
4096
,
8
,
40
}}}),
s
0
);
m2
.
add_return
({
r0
,
s1
});
};
...
...
test/simplify_dyn_ops_test.cpp
View file @
664b2f7c
...
...
@@ -155,29 +155,187 @@ TEST_CASE(after_split_dyn_broadcast_match)
EXPECT
(
p0
==
p1
);
}
TEST_CASE
(
const_slice_
3
input
)
TEST_CASE
(
const_slice_
2
input
_ends_axes
)
{
migraphx
::
module
m0
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
6
,
4
,
4
}};
auto
input
=
m0
.
add_parameter
(
"data"
,
s
);
auto
slice_ins
=
m0
.
add_instruction
(
auto
input
=
m0
.
add_parameter
(
"data"
,
s
);
migraphx
::
shape
s1
{
migraphx
::
shape
::
int32_type
,
{
1
}};
auto
input_starts
=
m0
.
add_literal
(
migraphx
::
literal
{
s1
,
{
0
}});
auto
slice_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"ends"
,
{
3
}},
{
"axes"
,
{
0
}}}),
input
,
input_starts
);
m0
.
add_return
({
slice_ins
});
}
run_pass
(
m0
);
migraphx
::
module
m1
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
6
,
4
,
4
}};
auto
input
=
m1
.
add_parameter
(
"data"
,
s
);
auto
slice_ins
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"starts"
,
{
0
}},
{
"ends"
,
{
3
}},
{
"axes"
,
{
0
}}}),
input
);
m1
.
add_return
({
slice_ins
});
}
EXPECT
(
m0
==
m1
);
}
TEST_CASE
(
const_slice_2input_starts_axes
)
{
migraphx
::
module
m0
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
6
,
4
,
4
}};
auto
input
=
m0
.
add_parameter
(
"data"
,
s
);
migraphx
::
shape
s1
{
migraphx
::
shape
::
int32_type
,
{
1
}};
auto
input_ends
=
m0
.
add_literal
(
migraphx
::
literal
{
s1
,
{
3
}});
auto
slice_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"starts"
,
{
0
}},
{
"axes"
,
{
0
}}}),
input
,
input_ends
);
m0
.
add_return
({
slice_ins
});
}
run_pass
(
m0
);
migraphx
::
module
m1
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
6
,
4
,
4
}};
auto
input
=
m1
.
add_parameter
(
"data"
,
s
);
auto
input
=
m1
.
add_parameter
(
"data"
,
s
);
auto
slice_ins
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"starts"
,
{
0
}},
{
"ends"
,
{
3
}},
{
"axes"
,
{
0
}}}),
input
);
m1
.
add_return
({
slice_ins
});
}
EXPECT
(
m0
==
m1
);
}
TEST_CASE
(
const_slice_2input_starts_ends
)
{
migraphx
::
module
m0
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
6
,
4
,
4
}};
auto
input
=
m0
.
add_parameter
(
"data"
,
s
);
migraphx
::
shape
s1
{
migraphx
::
shape
::
int32_type
,
{
1
}};
auto
input_starts
=
m1
.
add_literal
(
migraphx
::
literal
{
s1
,
{
0
}});
auto
input_ends
=
m1
.
add_literal
(
migraphx
::
literal
{
s1
,
{
3
}});
auto
slice_ins
=
m1
.
add_instruction
(
auto
input_axes
=
m0
.
add_literal
(
migraphx
::
literal
{
s1
,
{
0
}});
auto
slice_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"starts"
,
{
0
}},
{
"ends"
,
{
3
}}}),
input
,
input_axes
);
m0
.
add_return
({
slice_ins
});
}
run_pass
(
m0
);
migraphx
::
module
m1
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
6
,
4
,
4
}};
auto
input
=
m1
.
add_parameter
(
"data"
,
s
);
auto
slice_ins
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"starts"
,
{
0
}},
{
"ends"
,
{
3
}},
{
"axes"
,
{
0
}}}),
input
);
m1
.
add_return
({
slice_ins
});
}
EXPECT
(
m0
==
m1
);
}
TEST_CASE
(
const_slice_3input_axes_only
)
{
migraphx
::
module
m0
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
6
,
4
,
4
}};
auto
input
=
m0
.
add_parameter
(
"data"
,
s
);
migraphx
::
shape
s1
{
migraphx
::
shape
::
int32_type
,
{
1
}};
auto
input_starts
=
m0
.
add_literal
(
migraphx
::
literal
{
s1
,
{
0
}});
auto
input_ends
=
m0
.
add_literal
(
migraphx
::
literal
{
s1
,
{
3
}});
auto
slice_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"axes"
,
{
0
}}}),
input
,
input_starts
,
input_ends
);
m0
.
add_return
({
slice_ins
});
}
run_pass
(
m0
);
migraphx
::
module
m1
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
6
,
4
,
4
}};
auto
input
=
m1
.
add_parameter
(
"data"
,
s
);
auto
slice_ins
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"starts"
,
{
0
}},
{
"ends"
,
{
3
}},
{
"axes"
,
{
0
}}}),
input
);
m1
.
add_return
({
slice_ins
});
}
EXPECT
(
m0
==
m1
);
}
TEST_CASE
(
const_slice_3input_ends_only
)
{
migraphx
::
module
m0
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
6
,
4
,
4
}};
auto
input
=
m0
.
add_parameter
(
"data"
,
s
);
migraphx
::
shape
s1
{
migraphx
::
shape
::
int32_type
,
{
1
}};
auto
input_starts
=
m0
.
add_literal
(
migraphx
::
literal
{
s1
,
{
0
}});
auto
input_axes
=
m0
.
add_literal
(
migraphx
::
literal
{
s1
,
{
0
}});
auto
slice_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"ends"
,
{
3
}}}),
input
,
input_starts
,
input_axes
);
m0
.
add_return
({
slice_ins
});
}
run_pass
(
m0
);
migraphx
::
module
m1
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
6
,
4
,
4
}};
auto
input
=
m1
.
add_parameter
(
"data"
,
s
);
auto
slice_ins
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"starts"
,
{
0
}},
{
"ends"
,
{
3
}},
{
"axes"
,
{
0
}}}),
input
);
m1
.
add_return
({
slice_ins
});
}
EXPECT
(
m0
==
m1
);
}
TEST_CASE
(
const_slice_3inputs_starts_only
)
{
migraphx
::
module
m0
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
6
,
4
,
4
}};
auto
input
=
m0
.
add_parameter
(
"data"
,
s
);
migraphx
::
shape
s1
{
migraphx
::
shape
::
int32_type
,
{
1
}};
auto
input_ends
=
m0
.
add_literal
(
migraphx
::
literal
{
s1
,
{
3
}});
auto
input_axes
=
m0
.
add_literal
(
migraphx
::
literal
{
s1
,
{
0
}});
auto
slice_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"starts"
,
{
0
}}}),
input
,
input_ends
,
input_axes
);
m0
.
add_return
({
slice_ins
});
}
run_pass
(
m0
);
migraphx
::
module
m1
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
6
,
4
,
4
}};
auto
input
=
m1
.
add_parameter
(
"data"
,
s
);
auto
slice_ins
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"starts"
,
{
0
}},
{
"ends"
,
{
3
}},
{
"axes"
,
{
0
}}}),
input
);
m1
.
add_return
({
slice_ins
});
}
EXPECT
(
m0
==
m1
);
}
TEST_CASE
(
const_slice_2input_ends_axes_dyn
)
{
migraphx
::
module
m0
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{{
6
,
6
},
{
2
,
4
,
{
2
,
4
}},
{
2
,
4
,
{
2
,
4
}}}};
auto
input
=
m0
.
add_parameter
(
"data"
,
s
);
migraphx
::
shape
s1
{
migraphx
::
shape
::
int32_type
,
{
1
}};
auto
input_starts
=
m0
.
add_literal
(
migraphx
::
literal
{
s1
,
{
0
}});
auto
slice_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"ends"
,
{
3
}},
{
"axes"
,
{
0
}}}),
input
,
input_starts
);
m0
.
add_return
({
slice_ins
});
}
run_pass
(
m0
);
migraphx
::
module
m1
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{{
6
,
6
},
{
2
,
4
,
{
2
,
4
}},
{
2
,
4
,
{
2
,
4
}}}};
auto
input
=
m1
.
add_parameter
(
"data"
,
s
);
auto
slice_ins
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"starts"
,
{
0
}},
{
"ends"
,
{
3
}},
{
"axes"
,
{
0
}}}),
input
);
m1
.
add_return
({
slice_ins
});
}
run_pass
(
m1
);
EXPECT
(
m0
==
m1
);
}
...
...
@@ -237,4 +395,180 @@ TEST_CASE(const_slice_4input)
EXPECT
(
m0
==
m1
);
}
TEST_CASE
(
static_dimensions_of0
)
{
// dead_code_elimination will get rid of atan
migraphx
::
module
m0
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
2
,
4
,
4
}};
auto
input
=
m0
.
add_parameter
(
"data"
,
s
);
auto
atan_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"atan"
),
input
);
auto
dimensions_of_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"dimensions_of"
,
{{
"end"
,
3
}}),
atan_ins
);
m0
.
add_return
({
dimensions_of_ins
});
}
run_pass
(
m0
);
migraphx
::
module
m1
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
2
,
4
,
4
}};
m1
.
add_parameter
(
"data"
,
s
);
migraphx
::
shape
lit_shape
{
migraphx
::
shape
::
int64_type
,
{
3
}};
std
::
vector
<
int64_t
>
lit_data
=
{
2
,
4
,
4
};
auto
lit_ins
=
m1
.
add_literal
(
migraphx
::
literal
{
lit_shape
,
lit_data
});
m1
.
add_return
({
lit_ins
});
}
EXPECT
(
m0
==
m1
);
}
TEST_CASE
(
static_dimensions_of1
)
{
// dead_code_elimination will get rid of atan
migraphx
::
module
m0
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{{
2
,
4
,
{
2
,
4
}},
{
4
,
4
},
{
4
,
4
}}};
auto
input
=
m0
.
add_parameter
(
"data"
,
s
);
auto
atan_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"atan"
),
input
);
auto
dimensions_of_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"dimensions_of"
,
{{
"start"
,
1
},
{
"end"
,
3
}}),
atan_ins
);
m0
.
add_return
({
dimensions_of_ins
});
}
run_pass
(
m0
);
migraphx
::
module
m1
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{{
2
,
4
,
{
2
,
4
}},
{
4
,
4
},
{
4
,
4
}}};
m1
.
add_parameter
(
"data"
,
s
);
migraphx
::
shape
lit_shape
{
migraphx
::
shape
::
int64_type
,
{
2
}};
std
::
vector
<
int64_t
>
lit_data
=
{
4
,
4
};
auto
lit_ins
=
m1
.
add_literal
(
migraphx
::
literal
{
lit_shape
,
lit_data
});
m1
.
add_return
({
lit_ins
});
}
EXPECT
(
m0
==
m1
);
}
// Does nothing because the dynamic_dimensions from start to end
// are not all fixed
TEST_CASE
(
static_dimensions_of_nonfixed
)
{
// dead_code_elimination will get rid of atan
migraphx
::
module
m0
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{{
2
,
4
,
{
2
,
4
}},
{
4
,
8
},
{
4
,
8
}}};
auto
input
=
m0
.
add_parameter
(
"data"
,
s
);
auto
atan_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"atan"
),
input
);
auto
dimensions_of_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"dimensions_of"
,
{{
"start"
,
1
},
{
"end"
,
3
}}),
atan_ins
);
m0
.
add_return
({
dimensions_of_ins
});
}
run_pass
(
m0
);
migraphx
::
module
m1
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{{
2
,
4
,
{
2
,
4
}},
{
4
,
8
},
{
4
,
8
}}};
auto
input
=
m1
.
add_parameter
(
"data"
,
s
);
auto
atan_ins
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"atan"
),
input
);
auto
dimensions_of_ins
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"dimensions_of"
,
{{
"start"
,
1
},
{
"end"
,
3
}}),
atan_ins
);
m1
.
add_return
({
dimensions_of_ins
});
}
EXPECT
(
m0
==
m1
);
}
TEST_CASE
(
constant_alloc_reshape
)
{
migraphx
::
module
m0
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
3
,
32
}};
auto
input
=
m0
.
add_parameter
(
"data"
,
s
);
migraphx
::
shape
lit_s
{
migraphx
::
shape
::
int64_type
,
{
3
}};
auto
literal_ins
=
m0
.
add_literal
(
migraphx
::
literal
{
lit_s
,
{
3
,
4
,
8
}});
auto
alloc_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"allocate"
,
{{
"buf_type"
,
migraphx
::
shape
::
float_type
}}),
literal_ins
);
auto
reshape_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
),
input
,
alloc_ins
);
m0
.
add_return
({
reshape_ins
});
}
run_pass
(
m0
);
migraphx
::
module
m1
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
3
,
32
}};
auto
input
=
m1
.
add_parameter
(
"data"
,
s
);
auto
reshape_ins
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
,
{{
"dims"
,
{
3
,
4
,
8
}}}),
input
);
m1
.
add_return
({
reshape_ins
});
}
EXPECT
(
m0
==
m1
);
}
// A more contrived example to test static dimensions_of and constant reshape
TEST_CASE
(
static_dimensions_of_to_constant_alloc_reshape
)
{
migraphx
::
module
m0
;
{
migraphx
::
shape
input_shape
{
migraphx
::
shape
::
float_type
,
{
3
,
4
,
8
}};
auto
x_param
=
m0
.
add_parameter
(
"x"
,
input_shape
);
auto
dimensions_of_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"dimensions_of"
,
{{
"end"
,
3
}}),
x_param
);
migraphx
::
shape
lit_shape
{
migraphx
::
shape
::
int64_type
,
{
1
}};
auto
lit0
=
m0
.
add_literal
(
migraphx
::
literal
{
lit_shape
,
{
0
}});
auto
gather_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"gather"
,
{{
"axis"
,
0
}}),
dimensions_of_ins
,
lit0
);
auto
slice_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"slice"
,
{{
"starts"
,
{
1
}},
{
"ends"
,
{
3
}},
{
"axes"
,
{
0
}}}),
dimensions_of_ins
);
auto
reduce_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"reduce_prod"
,
{{
"axes"
,
{
0
}}}),
slice_ins
);
auto
concat_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"concat"
,
{{
"axis"
,
0
}}),
gather_ins
,
reduce_ins
);
auto
alloc_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"allocate"
,
{{
"buf_type"
,
migraphx
::
shape
::
float_type
}}),
concat_ins
);
auto
reshape_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
),
x_param
,
alloc_ins
);
m0
.
add_return
({
reshape_ins
});
}
run_pass
(
m0
);
migraphx
::
module
m1
;
{
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
3
,
4
,
8
}};
auto
x_param
=
m1
.
add_parameter
(
"x"
,
s
);
auto
reshape_ins
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
,
{{
"dims"
,
{
3
,
32
}}}),
x_param
);
m1
.
add_return
({
reshape_ins
});
}
EXPECT
(
m0
==
m1
);
}
TEST_CASE
(
const_alloc_fill
)
{
migraphx
::
module
m0
;
{
migraphx
::
shape
val_shape
{
migraphx
::
shape
::
int64_type
,
{
1
},
{
0
}};
std
::
vector
<
int64_t
>
lit_data
=
{
3
};
auto
value_lit
=
m0
.
add_literal
(
migraphx
::
literal
{
val_shape
,
lit_data
});
migraphx
::
shape
lit_s
{
migraphx
::
shape
::
int64_type
,
{
3
}};
auto
output_dim_lit
=
m0
.
add_literal
(
migraphx
::
literal
{
lit_s
,
{
3
,
4
,
4
}});
auto
alloc_ins
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"allocate"
,
{{
"buf_type"
,
migraphx
::
shape
::
int64_type
}}),
output_dim_lit
);
auto
ret
=
m0
.
add_instruction
(
migraphx
::
make_op
(
"fill"
),
value_lit
,
alloc_ins
);
m0
.
add_return
({
ret
});
}
run_pass
(
m0
);
migraphx
::
module
m1
;
{
migraphx
::
shape
lit_shape
{
migraphx
::
shape
::
int64_type
,
{
3
,
4
,
4
}};
std
::
vector
<
int64_t
>
lit_data
(
3
*
4
*
4
,
3
);
auto
ret
=
m1
.
add_literal
(
migraphx
::
literal
{
lit_shape
,
lit_data
});
m1
.
add_return
({
ret
});
}
EXPECT
(
m0
==
m1
);
}
int
main
(
int
argc
,
const
char
*
argv
[])
{
test
::
run
(
argc
,
argv
);
}
test/simplify_qdq_test.cpp
View file @
664b2f7c
...
...
@@ -44,20 +44,34 @@ void run_pass(migraphx::module& m)
sqdq
.
apply
(
m
);
}
migraphx
::
instruction_ref
add_quantize_op
(
migraphx
::
module
&
m
,
const
std
::
string
&
name
,
migraphx
::
instruction_ref
x
,
migraphx
::
instruction_ref
broadcast_scale
(
migraphx
::
module
&
m
,
migraphx
::
instruction_ref
scale
,
migraphx
::
instruction_ref
shift
)
const
std
::
vector
<
std
::
size_t
>&
out_lens
,
std
::
size_t
axis
)
{
auto
lens
=
x
->
get_shape
().
lens
();
if
(
scale
->
get_shape
().
lens
()
==
out_lens
)
return
scale
;
migraphx
::
instruction_ref
scale_mb
;
if
(
scale
->
get_shape
().
lens
().
front
()
==
1
)
auto
scale_lens
=
scale
->
get_shape
().
lens
();
if
(
scale_lens
.
front
()
==
1
and
scale_lens
.
size
()
==
1
)
scale_mb
=
m
.
add_instruction
(
migraphx
::
make_op
(
"multibroadcast"
,
{{
"out_lens"
,
lens
}}),
scale
);
m
.
add_instruction
(
migraphx
::
make_op
(
"multibroadcast"
,
{{
"out_lens"
,
out_
lens
}}),
scale
);
else
scale_mb
=
m
.
add_instruction
(
migraphx
::
make_op
(
"broadcast"
,
{{
"axis"
,
1
},
{
"out_lens"
,
lens
}}),
scale
);
migraphx
::
make_op
(
"broadcast"
,
{{
"axis"
,
axis
},
{
"out_lens"
,
out_lens
}}),
scale
);
return
scale_mb
;
}
migraphx
::
instruction_ref
add_quantize_op
(
migraphx
::
module
&
m
,
const
std
::
string
&
name
,
migraphx
::
instruction_ref
x
,
migraphx
::
instruction_ref
scale
,
migraphx
::
instruction_ref
shift
,
std
::
size_t
q_axis
=
1
)
{
auto
lens
=
x
->
get_shape
().
lens
();
auto
scale_mb
=
broadcast_scale
(
m
,
scale
,
lens
,
q_axis
);
auto
shift_mb
=
m
.
add_instruction
(
migraphx
::
make_op
(
"multibroadcast"
,
{{
"out_lens"
,
lens
}}),
shift
);
return
m
.
add_instruction
(
migraphx
::
make_op
(
name
),
x
,
scale_mb
,
shift_mb
);
...
...
@@ -66,19 +80,26 @@ migraphx::instruction_ref add_quantize_op(migraphx::module& m,
migraphx
::
instruction_ref
add_quantize_op
(
migraphx
::
module
&
m
,
const
std
::
string
&
name
,
migraphx
::
instruction_ref
x
,
migraphx
::
instruction_ref
scale
)
migraphx
::
instruction_ref
scale
,
std
::
size_t
q_axis
=
1
)
{
auto
lens
=
x
->
get_shape
().
lens
();
migraphx
::
instruction_ref
scale_mb
;
if
(
scale
->
get_shape
().
lens
().
front
()
==
1
)
scale_mb
=
m
.
add_instruction
(
migraphx
::
make_op
(
"multibroadcast"
,
{{
"out_lens"
,
lens
}}),
scale
);
else
scale_mb
=
m
.
add_instruction
(
migraphx
::
make_op
(
"broadcast"
,
{{
"axis"
,
1
},
{
"out_lens"
,
lens
}}),
scale
);
auto
lens
=
x
->
get_shape
().
lens
();
auto
scale_mb
=
broadcast_scale
(
m
,
scale
,
lens
,
q_axis
);
return
m
.
add_instruction
(
migraphx
::
make_op
(
name
),
x
,
scale_mb
);
}
migraphx
::
instruction_ref
add_scale_mul
(
migraphx
::
module
&
m
,
migraphx
::
instruction_ref
scale1
,
migraphx
::
instruction_ref
scale2
,
std
::
size_t
axis1
,
std
::
size_t
axis2
,
const
std
::
vector
<
std
::
size_t
>&
out_lens
)
{
auto
scale1_mb
=
broadcast_scale
(
m
,
scale1
,
out_lens
,
axis1
);
auto
scale2_mb
=
broadcast_scale
(
m
,
scale2
,
out_lens
,
axis2
);
return
m
.
add_instruction
(
migraphx
::
make_op
(
"mul"
),
scale1_mb
,
scale2_mb
);
}
TEST_CASE
(
remove_qdq
)
{
migraphx
::
shape
sh1
{
migraphx
::
shape
::
float_type
,
{
100
,
100
}};
...
...
@@ -159,18 +180,62 @@ TEST_CASE(dot)
m1
.
add_return
({
dot
});
}
migraphx
::
module
m2
;
{
auto
t1
=
m2
.
add_parameter
(
"t1"
,
sh1
);
auto
t2
=
m2
.
add_parameter
(
"t2"
,
sh2
);
auto
scale
=
m2
.
add_literal
(
0.5
f
);
auto
zero
=
m2
.
add_literal
(
std
::
int8_t
{
0
});
auto
q1
=
add_quantize_op
(
m2
,
"quantizelinear"
,
t1
,
scale
,
zero
);
auto
q2
=
add_quantize_op
(
m2
,
"quantizelinear"
,
t2
,
scale
,
zero
);
auto
dot
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"quant_dot"
),
q1
,
q2
);
auto
out_scale
=
add_scale_mul
(
m2
,
scale
,
scale
,
1
,
1
,
dot
->
get_shape
().
lens
());
auto
d3
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
dot
,
out_scale
);
m2
.
add_return
({
d3
});
}
run_pass
(
m1
);
EXPECT
(
m1
==
m2
);
}
TEST_CASE
(
dot_multi_scale
)
{
migraphx
::
shape
sh1
{
migraphx
::
shape
::
float_type
,
{
1280
,
1000
}};
migraphx
::
shape
sh2
{
migraphx
::
shape
::
float_type
,
{
1000
,
1024
}};
migraphx
::
shape
sh3
{
migraphx
::
shape
::
float_type
,
{
1280
}};
migraphx
::
module
m1
;
{
auto
t1
=
m1
.
add_parameter
(
"t1"
,
sh1
);
auto
t2
=
m1
.
add_parameter
(
"t2"
,
sh2
);
auto
scale1
=
m1
.
add_literal
(
migraphx
::
generate_literal
(
sh3
,
0
));
auto
scale2
=
m1
.
add_literal
(
0.4
f
);
auto
zero
=
m1
.
add_literal
(
std
::
int8_t
{
0
});
auto
q1
=
add_quantize_op
(
m1
,
"quantizelinear"
,
t1
,
scale1
,
zero
,
0
);
auto
d1
=
add_quantize_op
(
m1
,
"dequantizelinear"
,
q1
,
scale1
,
zero
,
0
);
auto
q2
=
add_quantize_op
(
m1
,
"quantizelinear"
,
t2
,
scale2
,
zero
,
1
);
auto
d2
=
add_quantize_op
(
m1
,
"dequantizelinear"
,
q2
,
scale2
,
zero
,
1
);
auto
dot
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"dot"
),
d1
,
d2
);
m1
.
add_return
({
dot
});
}
migraphx
::
module
m2
;
{
auto
t1
=
m2
.
add_parameter
(
"t1"
,
sh1
);
auto
t2
=
m2
.
add_parameter
(
"t2"
,
sh2
);
auto
scale
=
m2
.
add_literal
(
0.5
f
);
auto
scale1
=
m2
.
add_literal
(
migraphx
::
generate_literal
(
sh3
,
0
));
auto
scale2
=
m2
.
add_literal
(
0.4
f
);
auto
zero
=
m2
.
add_literal
(
std
::
int8_t
{
0
});
auto
scale1
=
m2
.
add_literal
(
0.25
f
);
auto
q1
=
add_quantize_op
(
m2
,
"quantizelinear"
,
t1
,
scale
,
zero
);
auto
q2
=
add_quantize_op
(
m2
,
"quantizelinear"
,
t2
,
scale
,
zero
);
auto
dot
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"quant_dot"
),
q1
,
q2
);
auto
d3
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
dot
,
scale1
);
auto
q1
=
add_quantize_op
(
m2
,
"quantizelinear"
,
t1
,
scale1
,
zero
,
0
);
auto
q2
=
add_quantize_op
(
m2
,
"quantizelinear"
,
t2
,
scale2
,
zero
,
1
);
auto
dot
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"quant_dot"
),
q1
,
q2
);
auto
out_scale
=
add_scale_mul
(
m2
,
scale1
,
scale2
,
0
,
1
,
dot
->
get_shape
().
lens
());
auto
d3
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
dot
,
out_scale
);
m2
.
add_return
({
d3
});
}
...
...
@@ -178,6 +243,180 @@ TEST_CASE(dot)
EXPECT
(
m1
==
m2
);
}
TEST_CASE
(
dot_broadcasted
)
{
migraphx
::
shape
sh1
{
migraphx
::
shape
::
float_type
,
{
2
,
1280
,
1000
}};
migraphx
::
shape
sh2
{
migraphx
::
shape
::
float_type
,
{
1000
,
1024
}};
migraphx
::
module
m1
;
{
auto
t1
=
m1
.
add_parameter
(
"t1"
,
sh1
);
auto
t2
=
m1
.
add_parameter
(
"t2"
,
sh2
);
auto
scale
=
m1
.
add_literal
(
0.5
f
);
auto
zero
=
m1
.
add_literal
(
std
::
int8_t
{
0
});
auto
q1
=
add_quantize_op
(
m1
,
"quantizelinear"
,
t1
,
scale
,
zero
);
auto
d1
=
add_quantize_op
(
m1
,
"dequantizelinear"
,
q1
,
scale
,
zero
);
auto
q2
=
add_quantize_op
(
m1
,
"quantizelinear"
,
t2
,
scale
,
zero
);
auto
d2
=
add_quantize_op
(
m1
,
"dequantizelinear"
,
q2
,
scale
,
zero
);
auto
d2_mb
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"multibroadcast"
,
{{
"out_lens"
,
{
2
,
1000
,
1024
}}}),
d2
);
auto
dot
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"dot"
),
d1
,
d2_mb
);
m1
.
add_return
({
dot
});
}
migraphx
::
module
m2
;
{
auto
t1
=
m2
.
add_parameter
(
"t1"
,
sh1
);
auto
t2
=
m2
.
add_parameter
(
"t2"
,
sh2
);
auto
scale
=
m2
.
add_literal
(
0.5
f
);
auto
zero
=
m2
.
add_literal
(
std
::
int8_t
{
0
});
auto
q1
=
add_quantize_op
(
m2
,
"quantizelinear"
,
t1
,
scale
,
zero
);
auto
q2
=
add_quantize_op
(
m2
,
"quantizelinear"
,
t2
,
scale
,
zero
);
auto
q2_mb
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"multibroadcast"
,
{{
"out_lens"
,
{
2
,
1000
,
1024
}}}),
q2
);
auto
dot
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"quant_dot"
),
q1
,
q2_mb
);
auto
out_scale
=
add_scale_mul
(
m2
,
scale
,
scale
,
1
,
1
,
dot
->
get_shape
().
lens
());
auto
d3
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
dot
,
out_scale
);
m2
.
add_return
({
d3
});
}
run_pass
(
m1
);
EXPECT
(
m1
==
m2
);
}
TEST_CASE
(
dot_transposed
)
{
migraphx
::
shape
sh1
{
migraphx
::
shape
::
float_type
,
{
1280
,
1000
}};
migraphx
::
shape
sh2
{
migraphx
::
shape
::
float_type
,
{
1024
,
1000
}};
migraphx
::
module
m1
;
{
auto
t1
=
m1
.
add_parameter
(
"t1"
,
sh1
);
auto
t2
=
m1
.
add_parameter
(
"t2"
,
sh2
);
auto
scale
=
m1
.
add_literal
(
0.5
f
);
auto
zero
=
m1
.
add_literal
(
std
::
int8_t
{
0
});
auto
q1
=
add_quantize_op
(
m1
,
"quantizelinear"
,
t1
,
scale
,
zero
);
auto
d1
=
add_quantize_op
(
m1
,
"dequantizelinear"
,
q1
,
scale
,
zero
);
auto
q2
=
add_quantize_op
(
m1
,
"quantizelinear"
,
t2
,
scale
,
zero
);
auto
d2
=
add_quantize_op
(
m1
,
"dequantizelinear"
,
q2
,
scale
,
zero
);
auto
d2_t
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"transpose"
,
{{
"permutation"
,
{
1
,
0
}}}),
d2
);
auto
dot
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"dot"
),
d1
,
d2_t
);
m1
.
add_return
({
dot
});
}
migraphx
::
module
m2
;
{
auto
t1
=
m2
.
add_parameter
(
"t1"
,
sh1
);
auto
t2
=
m2
.
add_parameter
(
"t2"
,
sh2
);
auto
scale
=
m2
.
add_literal
(
0.5
f
);
auto
zero
=
m2
.
add_literal
(
std
::
int8_t
{
0
});
auto
q1
=
add_quantize_op
(
m2
,
"quantizelinear"
,
t1
,
scale
,
zero
);
auto
q2
=
add_quantize_op
(
m2
,
"quantizelinear"
,
t2
,
scale
,
zero
);
auto
q2_t
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"transpose"
,
{{
"permutation"
,
{
1
,
0
}}}),
q2
);
auto
dot
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"quant_dot"
),
q1
,
q2_t
);
auto
out_scale
=
add_scale_mul
(
m2
,
scale
,
scale
,
1
,
1
,
dot
->
get_shape
().
lens
());
auto
d3
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
dot
,
out_scale
);
m2
.
add_return
({
d3
});
}
run_pass
(
m1
);
EXPECT
(
m1
==
m2
);
}
TEST_CASE
(
dot_multi_scale_transposed_broadcasted
)
{
migraphx
::
shape
sh1
{
migraphx
::
shape
::
float_type
,
{
2
,
3
,
1280
,
1000
}};
migraphx
::
shape
sh2
{
migraphx
::
shape
::
float_type
,
{
1024
,
1000
}};
migraphx
::
shape
sh3
{
migraphx
::
shape
::
float_type
,
{
1280
}};
migraphx
::
shape
sh4
{
migraphx
::
shape
::
float_type
,
{
1024
}};
migraphx
::
module
m1
;
{
auto
t1
=
m1
.
add_parameter
(
"t1"
,
sh1
);
auto
t2
=
m1
.
add_parameter
(
"t2"
,
sh2
);
auto
scale1
=
m1
.
add_literal
(
migraphx
::
generate_literal
(
sh3
,
0
));
auto
scale2
=
m1
.
add_literal
(
migraphx
::
generate_literal
(
sh4
,
0
));
auto
zero
=
m1
.
add_literal
(
std
::
int8_t
{
0
});
auto
q1
=
add_quantize_op
(
m1
,
"quantizelinear"
,
t1
,
scale1
,
zero
,
2
);
auto
d1
=
add_quantize_op
(
m1
,
"dequantizelinear"
,
q1
,
scale1
,
zero
,
2
);
auto
q2
=
add_quantize_op
(
m1
,
"quantizelinear"
,
t2
,
scale2
,
zero
,
0
);
auto
d2
=
add_quantize_op
(
m1
,
"dequantizelinear"
,
q2
,
scale2
,
zero
,
0
);
auto
d2_t
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"transpose"
,
{{
"permutation"
,
{
1
,
0
}}}),
d2
);
auto
d2_mb
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"multibroadcast"
,
{{
"out_lens"
,
{
2
,
3
,
1000
,
1024
}}}),
d2_t
);
auto
dot
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"dot"
),
d1
,
d2_mb
);
m1
.
add_return
({
dot
});
}
migraphx
::
module
m2
;
{
auto
t1
=
m2
.
add_parameter
(
"t1"
,
sh1
);
auto
t2
=
m2
.
add_parameter
(
"t2"
,
sh2
);
auto
scale1
=
m2
.
add_literal
(
migraphx
::
generate_literal
(
sh3
,
0
));
auto
scale2
=
m2
.
add_literal
(
migraphx
::
generate_literal
(
sh4
,
0
));
auto
zero
=
m2
.
add_literal
(
std
::
int8_t
{
0
});
auto
q1
=
add_quantize_op
(
m2
,
"quantizelinear"
,
t1
,
scale1
,
zero
,
2
);
auto
q2
=
add_quantize_op
(
m2
,
"quantizelinear"
,
t2
,
scale2
,
zero
,
0
);
auto
q2_t
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"transpose"
,
{{
"permutation"
,
{
1
,
0
}}}),
q2
);
auto
q2_mb
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"multibroadcast"
,
{{
"out_lens"
,
{
2
,
3
,
1000
,
1024
}}}),
q2_t
);
auto
dot
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"quant_dot"
),
q1
,
q2_mb
);
auto
out_scale
=
add_scale_mul
(
m2
,
scale1
,
scale2
,
2
,
3
,
dot
->
get_shape
().
lens
());
auto
d3
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
dot
,
out_scale
);
m2
.
add_return
({
d3
});
}
run_pass
(
m1
);
EXPECT
(
m1
==
m2
);
}
TEST_CASE
(
dot_multi_scale_unsupported_axis
)
{
migraphx
::
shape
sh1
{
migraphx
::
shape
::
float_type
,
{
1280
,
1000
}};
migraphx
::
shape
sh2
{
migraphx
::
shape
::
float_type
,
{
1000
,
1024
}};
migraphx
::
shape
sh3
{
migraphx
::
shape
::
float_type
,
{
1000
}};
migraphx
::
module
m1
;
{
auto
t1
=
m1
.
add_parameter
(
"t1"
,
sh1
);
auto
t2
=
m1
.
add_parameter
(
"t2"
,
sh2
);
auto
scale1
=
m1
.
add_literal
(
migraphx
::
generate_literal
(
sh3
,
0
));
auto
scale2
=
m1
.
add_literal
(
0.4
f
);
auto
zero
=
m1
.
add_literal
(
std
::
int8_t
{
0
});
auto
q1
=
add_quantize_op
(
m1
,
"quantizelinear"
,
t1
,
scale1
,
zero
,
1
);
auto
d1
=
add_quantize_op
(
m1
,
"dequantizelinear"
,
q1
,
scale1
,
zero
,
1
);
auto
q2
=
add_quantize_op
(
m1
,
"quantizelinear"
,
t2
,
scale2
,
zero
,
1
);
auto
d2
=
add_quantize_op
(
m1
,
"dequantizelinear"
,
q2
,
scale2
,
zero
,
1
);
auto
dot
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"dot"
),
d1
,
d2
);
m1
.
add_return
({
dot
});
}
migraphx
::
module
m2
;
{
auto
t1
=
m2
.
add_parameter
(
"t1"
,
sh1
);
auto
t2
=
m2
.
add_parameter
(
"t2"
,
sh2
);
auto
dot
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"dot"
),
t1
,
t2
);
m2
.
add_return
({
dot
});
}
run_pass
(
m1
);
EXPECT
(
m1
==
m2
);
}
TEST_CASE
(
dot_non_zero_point
)
{
migraphx
::
shape
sh1
{
migraphx
::
shape
::
float_type
,
{
1280
,
1000
}};
...
...
@@ -269,18 +508,18 @@ TEST_CASE(dot_add)
migraphx
::
module
m2
;
{
auto
t1
=
m2
.
add_parameter
(
"t1"
,
sh1
);
auto
t2
=
m2
.
add_parameter
(
"t2"
,
sh2
);
auto
ab
=
m2
.
add_parameter
(
"ab"
,
sh3
);
auto
scale
=
m2
.
add_literal
(
0.5
f
);
auto
zero
=
m2
.
add_literal
(
std
::
int8_t
{
0
});
auto
scale1
=
m2
.
add_literal
(
0.25
f
);
auto
q
1
=
add_quantize_op
(
m2
,
"quantizelinear"
,
t
1
,
scale
,
zero
);
auto
q2
=
add_
quantiz
e_op
(
m2
,
"quant
izelinear"
,
t2
,
scale
,
zero
);
auto
dot
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"quant_dot"
),
q1
,
q2
);
auto
d3
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
dot
,
scale
1
);
auto
add
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"add"
),
d3
,
ab
);
auto
t1
=
m2
.
add_parameter
(
"t1"
,
sh1
);
auto
t2
=
m2
.
add_parameter
(
"t2"
,
sh2
);
auto
ab
=
m2
.
add_parameter
(
"ab"
,
sh3
);
auto
scale
=
m2
.
add_literal
(
0.5
f
);
auto
zero
=
m2
.
add_literal
(
std
::
int8_t
{
0
});
auto
q1
=
add_quantize_op
(
m2
,
"quantizelinear"
,
t1
,
scale
,
zero
);
auto
q
2
=
add_quantize_op
(
m2
,
"quantizelinear"
,
t
2
,
scale
,
zero
);
auto
dot
=
m2
.
add_
instruction
(
migraphx
::
mak
e_op
(
"quant
_dot"
),
q1
,
q2
);
auto
out_scale
=
add_scale_mul
(
m2
,
scale
,
scale
,
1
,
1
,
dot
->
get_shape
().
lens
()
);
auto
d3
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
dot
,
out_
scale
);
auto
add
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"add"
),
d3
,
ab
);
m2
.
add_return
({
add
});
}
...
...
@@ -320,26 +559,80 @@ TEST_CASE(conv)
auto
weights
=
m2
.
add_parameter
(
"weights"
,
s4
);
auto
scale
=
m2
.
add_literal
(
0.5
f
);
auto
zero
=
m2
.
add_literal
(
std
::
int8_t
{
0
});
auto
scale1
=
m2
.
add_literal
(
0.25
f
);
auto
q1
=
add_quantize_op
(
m2
,
"quantizelinear"
,
input
,
scale
,
zero
);
auto
c1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"quant_convolution"
,
auto
q1
=
add_quantize_op
(
m2
,
"quantizelinear"
,
input
,
scale
,
zero
);
auto
c1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"quant_convolution"
,
{{
"padding"
,
{
0
,
0
,
0
,
0
}},
{
"stride"
,
{
1
,
1
}},
{
"dilation"
,
{
1
,
1
}},
{
"group"
,
1
},
{
"padding_mode"
,
0
}}),
q1
,
weights
);
auto
out_scale
=
add_scale_mul
(
m2
,
scale
,
scale
,
1
,
1
,
c1
->
get_shape
().
lens
());
auto
d6
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
c1
,
out_scale
);
m2
.
add_return
({
d6
});
}
run_pass
(
m1
);
EXPECT
(
m1
==
m2
);
}
TEST_CASE
(
conv_multi_scale
)
{
migraphx
::
shape
s4
{
migraphx
::
shape
::
int8_type
,
{
1280
,
320
,
1
,
1
}};
migraphx
::
shape
s7
{
migraphx
::
shape
::
float_type
,
{
1
,
320
,
7
,
7
}};
migraphx
::
shape
s8
{
migraphx
::
shape
::
float_type
,
{
1280
}};
migraphx
::
module
m1
;
{
auto
input
=
m1
.
add_parameter
(
"input"
,
s7
);
auto
weights
=
m1
.
add_parameter
(
"weights"
,
s4
);
auto
w_scale
=
m1
.
add_literal
(
migraphx
::
generate_literal
(
s8
,
0
));
auto
inp_scale
=
m1
.
add_literal
(
0.5
f
);
auto
zero
=
m1
.
add_literal
(
std
::
int8_t
{
0
});
auto
d1
=
add_quantize_op
(
m1
,
"dequantizelinear"
,
weights
,
w_scale
,
zero
,
0
);
auto
q1
=
add_quantize_op
(
m1
,
"quantizelinear"
,
input
,
inp_scale
,
zero
);
auto
d5
=
add_quantize_op
(
m1
,
"dequantizelinear"
,
q1
,
inp_scale
,
zero
);
auto
c1
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"convolution"
,
{{
"padding"
,
{
0
,
0
,
0
,
0
}},
{
"stride"
,
{
1
,
1
}},
{
"dilation"
,
{
1
,
1
}},
{
"group"
,
1
},
{
"padding_mode"
,
0
}}),
q1
,
d5
,
d1
);
m1
.
add_return
({
c1
});
}
migraphx
::
module
m2
;
{
auto
input
=
m2
.
add_parameter
(
"input"
,
s7
);
auto
weights
=
m2
.
add_parameter
(
"weights"
,
s4
);
auto
w_scale
=
m2
.
add_literal
(
migraphx
::
generate_literal
(
s8
,
0
));
auto
inp_scale
=
m2
.
add_literal
(
0.5
f
);
auto
zero
=
m2
.
add_literal
(
std
::
int8_t
{
0
});
auto
q_inp
=
add_quantize_op
(
m2
,
"quantizelinear"
,
input
,
inp_scale
,
zero
);
auto
c1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"quant_convolution"
,
{{
"padding"
,
{
0
,
0
,
0
,
0
}},
{
"stride"
,
{
1
,
1
}},
{
"dilation"
,
{
1
,
1
}},
{
"group"
,
1
},
{
"padding_mode"
,
0
}}),
q_inp
,
weights
);
auto
d6
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
c1
,
scale1
);
m2
.
add_return
({
d6
});
auto
out_scale
=
add_scale_mul
(
m2
,
inp_scale
,
w_scale
,
1
,
1
,
c1
->
get_shape
().
lens
());
auto
d1
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
c1
,
out_scale
);
m2
.
add_return
({
d1
});
}
run_pass
(
m1
);
EXPECT
(
m1
==
m2
);
}
TEST_CASE
(
conv_multi_scale
)
TEST_CASE
(
conv_multi_scale
_unsupported_axis
)
{
migraphx
::
shape
s4
{
migraphx
::
shape
::
int8_type
,
{
1280
,
320
,
1
,
1
}};
migraphx
::
shape
s7
{
migraphx
::
shape
::
float_type
,
{
1
,
320
,
7
,
7
}};
...
...
@@ -430,20 +723,20 @@ TEST_CASE(conv_bias_add)
auto
scale
=
m2
.
add_literal
(
0.5
f
);
auto
zero
=
m2
.
add_literal
(
std
::
int8_t
{
0
});
auto
zero32
=
m2
.
add_literal
(
std
::
int32_t
{
0
});
auto
scale1
=
m2
.
add_literal
(
0.25
f
);
auto
d2
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
bias
,
scale
,
zero32
);
auto
q1
=
add_quantize_op
(
m2
,
"quantizelinear"
,
input
,
scale
,
zero
);
auto
c1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"quant_convolution"
,
{{
"padding"
,
{
0
,
0
,
0
,
0
}},
{
"stride"
,
{
1
,
1
}},
{
"dilation"
,
{
1
,
1
}},
{
"group"
,
1
},
{
"padding_mode"
,
0
}}),
auto
d2
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
bias
,
scale
,
zero32
);
auto
q1
=
add_quantize_op
(
m2
,
"quantizelinear"
,
input
,
scale
,
zero
);
auto
c1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"quant_convolution"
,
{{
"padding"
,
{
0
,
0
,
0
,
0
}},
{
"stride"
,
{
1
,
1
}},
{
"dilation"
,
{
1
,
1
}},
{
"group"
,
1
},
{
"padding_mode"
,
0
}}),
q1
,
weights
);
auto
d6
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
c1
,
scale1
);
auto
b1
=
m2
.
add_instruction
(
auto
out_scale
=
add_scale_mul
(
m2
,
scale
,
scale
,
1
,
1
,
c1
->
get_shape
().
lens
());
auto
d6
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
c1
,
out_scale
);
auto
b1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"broadcast"
,
{{
"axis"
,
1
},
{
"out_lens"
,
{
1
,
1280
,
7
,
7
}}}),
d2
);
auto
a1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"add"
),
d6
,
b1
);
m2
.
add_return
({
a1
});
...
...
@@ -495,6 +788,7 @@ TEST_CASE(conv_pooling_dot)
{
"padding"
,
{
0
,
0
,
0
,
0
}},
{
"stride"
,
{
1
,
1
}},
{
"lengths"
,
{
7
,
7
}},
{
"dilations"
,
{
1
,
1
}},
{
"ceil_mode"
,
0
}}),
a1
);
auto
fl
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"flatten"
,
{{
"axis"
,
1
}}),
ap
);
...
...
@@ -519,22 +813,21 @@ TEST_CASE(conv_pooling_dot)
auto
scale
=
m2
.
add_literal
(
0.5
f
);
auto
zero
=
m2
.
add_literal
(
std
::
int8_t
{
0
});
auto
zero32
=
m2
.
add_literal
(
std
::
int32_t
{
0
});
auto
scale1
=
m2
.
add_literal
(
0.25
f
);
auto
scale2
=
m2
.
add_literal
(
0.25
f
);
auto
d2
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
bias
,
scale
,
zero32
);
auto
d3
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
ab
,
scale
,
zero
);
auto
q1
=
add_quantize_op
(
m2
,
"quantizelinear"
,
input
,
scale
,
zero
);
auto
c1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"quant_convolution"
,
{{
"padding"
,
{
0
,
0
,
0
,
0
}},
{
"stride"
,
{
1
,
1
}},
{
"dilation"
,
{
1
,
1
}},
{
"group"
,
1
},
{
"padding_mode"
,
0
}}),
auto
d2
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
bias
,
scale
,
zero32
);
auto
d3
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
ab
,
scale
,
zero
);
auto
q1
=
add_quantize_op
(
m2
,
"quantizelinear"
,
input
,
scale
,
zero
);
auto
c1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"quant_convolution"
,
{{
"padding"
,
{
0
,
0
,
0
,
0
}},
{
"stride"
,
{
1
,
1
}},
{
"dilation"
,
{
1
,
1
}},
{
"group"
,
1
},
{
"padding_mode"
,
0
}}),
q1
,
weights
);
auto
d5
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
c1
,
scale1
);
auto
bc1
=
m2
.
add_instruction
(
auto
out_scale1
=
add_scale_mul
(
m2
,
scale
,
scale
,
1
,
1
,
c1
->
get_shape
().
lens
());
auto
d5
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
c1
,
out_scale1
);
auto
bc1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"broadcast"
,
{{
"axis"
,
1
},
{
"out_lens"
,
{
1
,
1280
,
7
,
7
}}}),
d2
);
auto
a1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"add"
),
d5
,
bc1
);
auto
ap
=
...
...
@@ -543,12 +836,14 @@ TEST_CASE(conv_pooling_dot)
{
"padding"
,
{
0
,
0
,
0
,
0
}},
{
"stride"
,
{
1
,
1
}},
{
"lengths"
,
{
7
,
7
}},
{
"dilations"
,
{
1
,
1
}},
{
"ceil_mode"
,
0
}}),
a1
);
auto
fl
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"flatten"
,
{{
"axis"
,
1
}}),
ap
);
auto
q4
=
add_quantize_op
(
m2
,
"quantizelinear"
,
fl
,
scale
,
zero
);
auto
dot
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"quant_dot"
),
q4
,
db
);
auto
d9
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
dot
,
scale2
);
auto
fl
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"flatten"
,
{{
"axis"
,
1
}}),
ap
);
auto
q4
=
add_quantize_op
(
m2
,
"quantizelinear"
,
fl
,
scale
,
zero
);
auto
dot
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"quant_dot"
),
q4
,
db
);
auto
out_scale2
=
add_scale_mul
(
m2
,
scale
,
scale
,
1
,
0
,
dot
->
get_shape
().
lens
());
auto
d9
=
add_quantize_op
(
m2
,
"dequantizelinear"
,
dot
,
out_scale2
);
auto
mb1
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"multibroadcast"
,
{{
"out_lens"
,
{
1
,
1000
}}}),
d3
);
auto
a2
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"add"
),
d9
,
mb1
);
...
...
@@ -603,6 +898,7 @@ TEST_CASE(mobilenet_snippet)
{
"padding"
,
{
0
,
0
,
0
,
0
}},
{
"stride"
,
{
1
,
1
}},
{
"lengths"
,
{
7
,
7
}},
{
"dilations"
,
{
1
,
1
}},
{
"ceil_mode"
,
0
}}),
d6
);
auto
q3
=
add_quantize_op
(
mm
,
"quantizelinear"
,
ap
,
scale
,
zero
);
...
...
test/simplify_reshapes_test.cpp
View file @
664b2f7c
...
...
@@ -888,9 +888,8 @@ TEST_CASE(optimize_resize)
std
::
vector
<
int64_t
>
mb_dims
=
{
1
,
2
,
2
,
2
,
2
,
3
};
auto
mbx
=
m
.
add_instruction
(
migraphx
::
make_op
(
"multibroadcast"
,
{{
"out_lens"
,
mb_dims
}}),
rspx
);
auto
std_mb
=
m
.
add_instruction
(
migraphx
::
make_op
(
"contiguous"
),
mbx
);
std
::
vector
<
int64_t
>
orig_dims
=
{
1
,
2
,
4
,
6
};
auto
rmb
=
m
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
,
{{
"dims"
,
orig_dims
}}),
std_
mb
);
auto
rmb
=
m
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
,
{{
"dims"
,
orig_dims
}}),
mb
x
);
auto
r
=
m
.
add_instruction
(
migraphx
::
make_op
(
"softmax"
,
{{
"axis"
,
1
}}),
rmb
);
m
.
add_return
({
r
});
...
...
@@ -1300,10 +1299,9 @@ TEST_CASE(transpose_contiguous_reshape_unary)
m2
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
,
{{
"dims"
,
{
2
,
2
,
2
,
2
,
5
,
5
}}}),
x
);
auto
transpose_ins
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"transpose"
,
{{
"permutation"
,
{
0
,
3
,
4
,
1
,
5
,
2
}}}),
reshape_ins1
);
auto
relu
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"relu"
),
transpose_ins
);
auto
cont_ins
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"contiguous"
),
relu
);
auto
relu
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"relu"
),
transpose_ins
);
auto
reshape_ins2
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
,
{{
"dims"
,
{
2
,
2
,
10
,
10
}}}),
cont_ins
);
m2
.
add_instruction
(
migraphx
::
make_op
(
"reshape"
,
{{
"dims"
,
{
2
,
2
,
10
,
10
}}}),
relu
);
m2
.
add_instruction
(
pass_op
{},
reshape_ins2
);
}
EXPECT
(
m1
==
m2
);
...
...
@@ -1328,8 +1326,7 @@ TEST_CASE(transpose_contiguous_squeeze_unary)
auto
transpose_ins
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"transpose"
,
{{
"permutation"
,
{
0
,
2
,
3
,
1
}}}),
x
);
auto
rsqrt
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"rsqrt"
),
transpose_ins
);
auto
cont_ins
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"contiguous"
),
rsqrt
);
auto
sq_ins
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"squeeze"
,
{{
"axes"
,
{
1
}}}),
cont_ins
);
auto
sq_ins
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"squeeze"
,
{{
"axes"
,
{
1
}}}),
rsqrt
);
m2
.
add_instruction
(
pass_op
{},
sq_ins
);
}
EXPECT
(
m1
==
m2
);
...
...
@@ -1345,7 +1342,7 @@ TEST_CASE(transpose_contiguous_unsqueeze_unary)
auto
cont_ins
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"contiguous"
),
transpose_ins
);
auto
unsq_ins
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"unsqueeze"
,
{{
"axes"
,
{
2
}}}),
cont_ins
);
auto
round
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"
round
"
),
unsq_ins
);
auto
round
=
m1
.
add_instruction
(
migraphx
::
make_op
(
"
nearbyint
"
),
unsq_ins
);
m1
.
add_instruction
(
pass_op
{},
round
);
}
run_pass
(
m1
);
...
...
@@ -1354,10 +1351,8 @@ TEST_CASE(transpose_contiguous_unsqueeze_unary)
auto
x
=
m2
.
add_parameter
(
"x"
,
{
migraphx
::
shape
::
float_type
,
{
2
,
8
,
5
,
5
}});
auto
transpose_ins
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"transpose"
,
{{
"permutation"
,
{
0
,
2
,
3
,
1
}}}),
x
);
auto
round
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"round"
),
transpose_ins
);
auto
cont_ins
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"contiguous"
),
round
);
auto
unsq_ins
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"unsqueeze"
,
{{
"axes"
,
{
2
}}}),
cont_ins
);
auto
round
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"nearbyint"
),
transpose_ins
);
auto
unsq_ins
=
m2
.
add_instruction
(
migraphx
::
make_op
(
"unsqueeze"
,
{{
"axes"
,
{
2
}}}),
round
);
m2
.
add_instruction
(
pass_op
{},
unsq_ins
);
}
EXPECT
(
m1
==
m2
);
...
...
test/verify/
test_isnan_half
.cpp
→
test/verify/
gemm_2args_mm_8
.cpp
View file @
664b2f7c
...
...
@@ -21,23 +21,27 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <limits>
#include "verify_program.hpp"
#include <migraphx/program.hpp>
#include <migraphx/generate.hpp>
#include <migraphx/make_op.hpp>
#include <migraphx/half.hpp>
struct
test_isnan_half
:
verify_program
<
test_isnan_half
>
struct
gemm_2args_mm_8
:
verify_program
<
gemm_2args_mm_8
>
{
migraphx
::
program
create_program
()
const
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
auto
x
=
mm
->
add_parameter
(
"x"
,
migraphx
::
shape
{
migraphx
::
shape
::
half_type
,
{
2
}});
auto
l0
=
mm
->
add_literal
(
std
::
numeric_limits
<
migraphx
::
half
>::
quiet_NaN
());
x
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"concat"
,
{{
"axis"
,
0
}}),
x
,
l0
);
mm
->
add_instruction
(
migraphx
::
make_op
(
"isnan"
),
x
);
migraphx
::
shape
a_shape
{
migraphx
::
shape
::
float_type
,
{
2
,
128
,
32
},
{
4096
,
1
,
128
}};
migraphx
::
shape
b_shape
{
migraphx
::
shape
::
float_type
,
{
32
,
32
}};
auto
a
=
mm
->
add_parameter
(
"a"
,
a_shape
);
auto
b
=
mm
->
add_parameter
(
"b"
,
b_shape
);
auto
bb
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"multibroadcast"
,
{{
"out_lens"
,
{
2
,
32
,
32
}}}),
b
);
mm
->
add_instruction
(
migraphx
::
make_op
(
"dot"
),
a
,
bb
);
return
p
;
}
};
test/verify/gemm_softmax_gemm_relu.cpp
0 → 100644
View file @
664b2f7c
/*
* The MIT License (MIT)
*
* Copyright (c) 2015-2022 Advanced Micro Devices, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "verify_program.hpp"
#include <migraphx/program.hpp>
#include <migraphx/generate.hpp>
#include <migraphx/make_op.hpp>
struct
gemm_softmax_gemm_relu
:
verify_program
<
gemm_softmax_gemm_relu
>
{
migraphx
::
program
create_program
()
const
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
migraphx
::
shape
m1_shape
{
migraphx
::
shape
::
half_type
,
{
1
,
12
,
256
,
256
}};
migraphx
::
shape
m2_shape
{
migraphx
::
shape
::
half_type
,
{
1
,
12
,
256
,
256
}};
auto
m2_elements
=
m2_shape
.
elements
();
auto
a
=
mm
->
add_parameter
(
"1"
,
m1_shape
);
auto
b
=
mm
->
add_parameter
(
"2"
,
m1_shape
);
auto
b1
=
mm
->
add_parameter
(
"3"
,
m1_shape
);
std
::
vector
<
float
>
eights
(
m2_elements
,
0.125
);
auto
eight
=
mm
->
add_literal
(
migraphx
::
literal
{
m2_shape
,
eights
});
std
::
vector
<
float
>
zeros
(
m2_elements
,
0
);
auto
zero
=
mm
->
add_literal
(
migraphx
::
literal
{
m2_shape
,
zeros
});
b
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"transpose"
,
{{
"permutation"
,
{
0
,
1
,
3
,
2
}}}),
b
);
auto
gemm1
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"dot"
),
a
,
b
);
auto
scale
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"mul"
),
gemm1
,
eight
);
auto
bias
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"add"
),
scale
,
zero
);
auto
softmax
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"softmax"
,
{{
"axis"
,
3
}}),
bias
);
auto
gemm2
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"dot"
),
softmax
,
b1
);
mm
->
add_instruction
(
migraphx
::
make_op
(
"relu"
),
gemm2
);
return
p
;
}
};
test/verify/test_abs.cpp
View file @
664b2f7c
...
...
@@ -27,14 +27,19 @@
#include <migraphx/generate.hpp>
#include <migraphx/make_op.hpp>
struct
test_abs
:
verify_program
<
test_abs
>
template
<
migraphx
::
shape
::
type_t
DType
>
struct
test_abs
:
verify_program
<
test_abs
<
DType
>>
{
migraphx
::
program
create_program
()
const
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
auto
x
=
mm
->
add_parameter
(
"x"
,
migraphx
::
shape
{
migraphx
::
shape
::
float_t
ype
,
{
4
,
3
,
3
,
3
}});
auto
x
=
mm
->
add_parameter
(
"x"
,
migraphx
::
shape
{
DT
ype
,
{
4
,
3
,
3
,
3
}});
mm
->
add_instruction
(
migraphx
::
make_op
(
"abs"
),
x
);
return
p
;
}
};
template
struct
test_abs
<
migraphx
::
shape
::
fp8e4m3fnuz_type
>;
template
struct
test_abs
<
migraphx
::
shape
::
half_type
>;
template
struct
test_abs
<
migraphx
::
shape
::
float_type
>;
test/verify/test_acos.cpp
View file @
664b2f7c
...
...
@@ -27,15 +27,20 @@
#include <migraphx/generate.hpp>
#include <migraphx/make_op.hpp>
struct
test_acos
:
verify_program
<
test_acos
>
template
<
migraphx
::
shape
::
type_t
DType
>
struct
test_acos
:
verify_program
<
test_acos
<
DType
>>
{
migraphx
::
program
create_program
()
const
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
migraphx
::
shape
s
{
migraphx
::
shape
::
float_t
ype
,
{
16
}};
migraphx
::
shape
s
{
DT
ype
,
{
16
}};
auto
x
=
mm
->
add_parameter
(
"x"
,
s
);
mm
->
add_instruction
(
migraphx
::
make_op
(
"acos"
),
x
);
return
p
;
}
};
template
struct
test_acos
<
migraphx
::
shape
::
fp8e4m3fnuz_type
>;
template
struct
test_acos
<
migraphx
::
shape
::
half_type
>;
template
struct
test_acos
<
migraphx
::
shape
::
float_type
>;
test/verify/test_acosh.cpp
View file @
664b2f7c
...
...
@@ -23,20 +23,23 @@
*/
#include "verify_program.hpp"
#include <migraphx/literal.hpp>
#include <migraphx/program.hpp>
#include <migraphx/generate.hpp>
#include <migraphx/make_op.hpp>
struct
test_acosh
:
verify_program
<
test_acosh
>
template
<
typename
CType
>
struct
test_acosh
:
verify_program
<
test_acosh
<
CType
>>
{
migraphx
::
program
create_program
()
const
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
16
}};
auto
*
mm
=
p
.
get_main_module
();
migraphx
::
shape
::
type_t
dtype
=
migraphx
::
shape
::
get_type
<
CType
>
();
migraphx
::
shape
s
{
dtype
,
{
16
}};
auto
x
=
mm
->
add_parameter
(
"x"
,
s
);
auto
min_val
=
mm
->
add_literal
(
1.1
f
);
auto
max_val
=
mm
->
add_literal
(
100.0
f
);
auto
min_val
=
mm
->
add_literal
(
migraphx
::
literal
{
migraphx
::
shape
{
dtype
},
{
1.1
f
}}
);
auto
max_val
=
mm
->
add_literal
(
migraphx
::
literal
{
migraphx
::
shape
{
dtype
},
{
100.0
f
}}
);
min_val
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"multibroadcast"
,
{{
"out_lens"
,
{
16
}}}),
min_val
);
max_val
=
...
...
@@ -46,3 +49,7 @@ struct test_acosh : verify_program<test_acosh>
return
p
;
}
};
template
struct
test_acosh
<
float
>;
template
struct
test_acosh
<
migraphx
::
half
>;
template
struct
test_acosh
<
migraphx
::
fp8
::
fp8e4m3fnuz
>;
test/verify/test_add.cpp
View file @
664b2f7c
...
...
@@ -27,16 +27,21 @@
#include <migraphx/generate.hpp>
#include <migraphx/make_op.hpp>
struct
test_add
:
verify_program
<
test_add
>
template
<
migraphx
::
shape
::
type_t
DType
>
struct
test_add
:
verify_program
<
test_add
<
DType
>>
{
migraphx
::
program
create_program
()
const
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
migraphx
::
shape
s
{
migraphx
::
shape
::
float_t
ype
,
{
3
}};
migraphx
::
shape
s
{
DT
ype
,
{
8
}};
auto
x
=
mm
->
add_parameter
(
"x"
,
s
);
auto
y
=
mm
->
add_parameter
(
"y"
,
s
);
mm
->
add_instruction
(
migraphx
::
make_op
(
"add"
),
x
,
y
);
return
p
;
}
};
template
struct
test_add
<
migraphx
::
shape
::
fp8e4m3fnuz_type
>;
template
struct
test_add
<
migraphx
::
shape
::
half_type
>;
template
struct
test_add
<
migraphx
::
shape
::
float_type
>;
test/verify/test_asin.cpp
View file @
664b2f7c
...
...
@@ -27,15 +27,20 @@
#include <migraphx/generate.hpp>
#include <migraphx/make_op.hpp>
struct
test_asin
:
verify_program
<
test_asin
>
template
<
migraphx
::
shape
::
type_t
DType
>
struct
test_asin
:
verify_program
<
test_asin
<
DType
>>
{
migraphx
::
program
create_program
()
const
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
migraphx
::
shape
s
{
migraphx
::
shape
::
float_t
ype
,
{
16
}};
migraphx
::
shape
s
{
DT
ype
,
{
16
}};
auto
x
=
mm
->
add_parameter
(
"x"
,
s
);
mm
->
add_instruction
(
migraphx
::
make_op
(
"asin"
),
x
);
return
p
;
}
};
template
struct
test_asin
<
migraphx
::
shape
::
float_type
>;
template
struct
test_asin
<
migraphx
::
shape
::
half_type
>;
template
struct
test_asin
<
migraphx
::
shape
::
fp8e4m3fnuz_type
>;
test/verify/test_asinh.cpp
View file @
664b2f7c
...
...
@@ -27,15 +27,20 @@
#include <migraphx/generate.hpp>
#include <migraphx/make_op.hpp>
struct
test_asinh
:
verify_program
<
test_asinh
>
template
<
migraphx
::
shape
::
type_t
DType
>
struct
test_asinh
:
verify_program
<
test_asinh
<
DType
>>
{
migraphx
::
program
create_program
()
const
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
migraphx
::
shape
s
{
migraphx
::
shape
::
float_t
ype
,
{
16
}};
migraphx
::
shape
s
{
DT
ype
,
{
16
}};
auto
x
=
mm
->
add_parameter
(
"x"
,
s
);
mm
->
add_instruction
(
migraphx
::
make_op
(
"asinh"
),
x
);
return
p
;
}
};
template
struct
test_asinh
<
migraphx
::
shape
::
float_type
>;
template
struct
test_asinh
<
migraphx
::
shape
::
half_type
>;
template
struct
test_asinh
<
migraphx
::
shape
::
fp8e4m3fnuz_type
>;
test/verify/test_atan.cpp
View file @
664b2f7c
...
...
@@ -27,15 +27,20 @@
#include <migraphx/generate.hpp>
#include <migraphx/make_op.hpp>
struct
test_atan
:
verify_program
<
test_atan
>
template
<
migraphx
::
shape
::
type_t
DType
>
struct
test_atan
:
verify_program
<
test_atan
<
DType
>>
{
migraphx
::
program
create_program
()
const
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
migraphx
::
shape
s
{
migraphx
::
shape
::
float_t
ype
,
{
16
}};
migraphx
::
shape
s
{
DT
ype
,
{
16
}};
auto
x
=
mm
->
add_parameter
(
"x"
,
s
);
mm
->
add_instruction
(
migraphx
::
make_op
(
"atan"
),
x
);
return
p
;
}
};
template
struct
test_atan
<
migraphx
::
shape
::
float_type
>;
template
struct
test_atan
<
migraphx
::
shape
::
half_type
>;
template
struct
test_atan
<
migraphx
::
shape
::
fp8e4m3fnuz_type
>;
test/verify/test_atanh.cpp
View file @
664b2f7c
...
...
@@ -23,20 +23,24 @@
*/
#include "verify_program.hpp"
#include <migraphx/float8.hpp>
#include <migraphx/half.hpp>
#include <migraphx/program.hpp>
#include <migraphx/generate.hpp>
#include <migraphx/make_op.hpp>
struct
test_atanh
:
verify_program
<
test_atanh
>
template
<
typename
CType
>
struct
test_atanh
:
verify_program
<
test_atanh
<
CType
>>
{
migraphx
::
program
create_program
()
const
{
migraphx
::
program
p
;
auto
*
mm
=
p
.
get_main_module
();
migraphx
::
shape
s
{
migraphx
::
shape
::
float_type
,
{
16
}};
auto
*
mm
=
p
.
get_main_module
();
migraphx
::
shape
::
type_t
dtype
=
migraphx
::
shape
::
get_type
<
CType
>
();
migraphx
::
shape
s
{
dtype
,
{
16
}};
auto
x
=
mm
->
add_parameter
(
"x"
,
s
);
auto
min_val
=
mm
->
add_literal
(
-
0.95
f
);
auto
max_val
=
mm
->
add_literal
(
0.95
f
);
auto
min_val
=
mm
->
add_literal
(
migraphx
::
literal
{
migraphx
::
shape
{
dtype
},
{
-
0.95
f
}}
);
auto
max_val
=
mm
->
add_literal
(
migraphx
::
literal
{
migraphx
::
shape
{
dtype
},
{
0.95
f
}}
);
min_val
=
mm
->
add_instruction
(
migraphx
::
make_op
(
"multibroadcast"
,
{{
"out_lens"
,
{
16
}}}),
min_val
);
max_val
=
...
...
@@ -46,3 +50,7 @@ struct test_atanh : verify_program<test_atanh>
return
p
;
}
};
template
struct
test_atanh
<
float
>;
template
struct
test_atanh
<
migraphx
::
half
>;
template
struct
test_atanh
<
migraphx
::
fp8
::
fp8e4m3fnuz
>;
test/verify/test_avg_pooling_1d.cpp
View file @
664b2f7c
...
...
@@ -35,7 +35,7 @@ struct test_avg_pooling_1d : verify_program<test_avg_pooling_1d>
auto
*
mm
=
p
.
get_main_module
();
auto
input
=
mm
->
add_parameter
(
"x"
,
migraphx
::
shape
{
migraphx
::
shape
::
float_type
,
{
1
,
3
,
5
}});
auto
op
=
migraphx
::
op
::
pooling
{
migraphx
::
op
::
pooling_mode
::
average
,
{
0
},
{
1
},
{
3
}};
auto
op
=
migraphx
::
op
::
pooling
{
migraphx
::
op
::
pooling_mode
::
average
,
{
0
},
{
1
},
{
3
}
,
{
1
}
};
mm
->
add_instruction
(
op
,
input
);
return
p
;
}
...
...
test/verify/test_avg_pooling_3d.cpp
View file @
664b2f7c
...
...
@@ -36,7 +36,7 @@ struct test_avg_pooling_3d : verify_program<test_avg_pooling_3d>
auto
input
=
mm
->
add_parameter
(
"x"
,
migraphx
::
shape
{
migraphx
::
shape
::
float_type
,
{
1
,
3
,
5
,
5
,
5
}});
auto
op
=
migraphx
::
op
::
pooling
{
migraphx
::
op
::
pooling_mode
::
average
,
{
1
,
1
,
1
},
{
3
,
3
,
3
},
{
3
,
3
,
3
}};
migraphx
::
op
::
pooling_mode
::
average
,
{
1
,
1
,
1
},
{
3
,
3
,
3
},
{
3
,
3
,
3
}
,
{
1
,
1
,
1
}
};
mm
->
add_instruction
(
op
,
input
);
return
p
;
}
...
...
Prev
1
…
7
8
9
10
11
12
13
14
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