Commit 8f568801 authored by Paul's avatar Paul
Browse files

Merge branch 'develop' into layout-nhwc

parents 7393cf1e f7d987ba
batchnorm_1d_test:
M
0
1
2
3
45"BatchNormalization*
epsilon75*
momentumfff?batchnorm_1d_testZ
0



Z
1

Z
2

Z
3

Z
4

b
5



B
\ No newline at end of file
batchnorm_3d_test:
M
0
1
2
3
45"BatchNormalization*
epsilon75*
momentumfff?batchnorm_3d_testZ
0





Z
1

Z
2

Z
3

Z
4

b
5





B
\ No newline at end of file
......@@ -314,38 +314,107 @@ def averagepool_same_upper_test():
@onnx_test
def batchnorm_1d_test():
x = helper.make_tensor_value_info('0', TensorProto.FLOAT, [1, 3, 5])
scale = helper.make_tensor_value_info('1', TensorProto.FLOAT, [3])
bias = helper.make_tensor_value_info('2', TensorProto.FLOAT, [3])
mean = helper.make_tensor_value_info('3', TensorProto.FLOAT, [3])
var = helper.make_tensor_value_info('4', TensorProto.FLOAT, [3])
out = helper.make_tensor_value_info('5', TensorProto.FLOAT, [1, 3, 5])
node = onnx.helper.make_node('BatchNormalization',
inputs=['0', '1', '2', '3', '4'],
outputs=['5'],
epsilon=1e-6,
momentum=0.9)
def batch_norm_flat_test():
x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [10])
scale = helper.make_tensor_value_info('scale', TensorProto.FLOAT, [1])
bias = helper.make_tensor_value_info('bias', TensorProto.FLOAT, [1])
mean = helper.make_tensor_value_info('mean', TensorProto.FLOAT, [1])
var = helper.make_tensor_value_info('variance', TensorProto.FLOAT, [1])
out = helper.make_tensor_value_info('y', TensorProto.FLOAT, [10])
node = onnx.helper.make_node(
'BatchNormalization',
inputs=['x', 'scale', 'bias', 'mean', 'variance'],
outputs=['y'],
epsilon=1e-6)
return ([node], [x, scale, bias, mean, var], [out])
@onnx_test
def batchnorm_3d_test():
x = helper.make_tensor_value_info('0', TensorProto.FLOAT, [1, 3, 5, 5, 5])
scale = helper.make_tensor_value_info('1', TensorProto.FLOAT, [3])
bias = helper.make_tensor_value_info('2', TensorProto.FLOAT, [3])
mean = helper.make_tensor_value_info('3', TensorProto.FLOAT, [3])
var = helper.make_tensor_value_info('4', TensorProto.FLOAT, [3])
out = helper.make_tensor_value_info('5', TensorProto.FLOAT,
[1, 3, 5, 5, 5])
node = onnx.helper.make_node('BatchNormalization',
inputs=['0', '1', '2', '3', '4'],
outputs=['5'],
epsilon=1e-6,
momentum=0.9)
def batch_norm_1d_test():
x = helper.make_tensor_value_info('x', TensorProto.FLOAT16, [2, 3, 4])
scale = helper.make_tensor_value_info('scale', TensorProto.FLOAT, [3])
bias = helper.make_tensor_value_info('bias', TensorProto.FLOAT, [3])
mean = helper.make_tensor_value_info('mean', TensorProto.FLOAT, [3])
var = helper.make_tensor_value_info('variance', TensorProto.FLOAT, [3])
out = helper.make_tensor_value_info('y', TensorProto.FLOAT16, [2, 3, 4])
node = onnx.helper.make_node(
'BatchNormalization',
inputs=['x', 'scale', 'bias', 'mean', 'variance'],
outputs=['y'])
return ([node], [x, scale, bias, mean, var], [out])
@onnx_test
def batch_norm_2d_test():
x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [2, 3, 4, 4])
scale = helper.make_tensor_value_info('scale', TensorProto.FLOAT, [3])
bias = helper.make_tensor_value_info('bias', TensorProto.FLOAT, [3])
mean = helper.make_tensor_value_info('mean', TensorProto.FLOAT, [3])
var = helper.make_tensor_value_info('variance', TensorProto.FLOAT, [3])
out = helper.make_tensor_value_info('y', TensorProto.FLOAT, [2, 3, 4, 4])
node = onnx.helper.make_node(
'BatchNormalization',
inputs=['x', 'scale', 'bias', 'mean', 'variance'],
outputs=['y'])
return ([node], [x, scale, bias, mean, var], [out])
@onnx_test
def batch_norm_3d_test():
x = helper.make_tensor_value_info('x', TensorProto.FLOAT16,
[2, 2, 2, 2, 2])
scale = helper.make_tensor_value_info('scale', TensorProto.FLOAT16, [2])
bias = helper.make_tensor_value_info('bias', TensorProto.FLOAT16, [2])
mean = helper.make_tensor_value_info('mean', TensorProto.FLOAT16, [2])
var = helper.make_tensor_value_info('variance', TensorProto.FLOAT16, [2])
out = helper.make_tensor_value_info('y', TensorProto.FLOAT16,
[2, 2, 2, 2, 2])
node = onnx.helper.make_node(
'BatchNormalization',
inputs=['x', 'scale', 'bias', 'mean', 'variance'],
outputs=['y'],
epsilon=1e-6)
return ([node], [x, scale, bias, mean, var], [out])
@onnx_test
def batch_norm_invalid_rank_test():
x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [8, 8])
scale = helper.make_tensor_value_info('scale', TensorProto.FLOAT, [8])
bias = helper.make_tensor_value_info('bias', TensorProto.FLOAT, [8])
mean = helper.make_tensor_value_info('mean', TensorProto.FLOAT, [8])
var = helper.make_tensor_value_info('variance', TensorProto.FLOAT, [8])
out = helper.make_tensor_value_info('y', TensorProto.FLOAT, [8, 8])
node = onnx.helper.make_node(
'BatchNormalization',
inputs=['x', 'scale', 'bias', 'mean', 'variance'],
outputs=['y'])
return ([node], [x, scale, bias, mean, var], [out])
@onnx_test
def batch_norm_invalid_bias_rank_test():
x = helper.make_tensor_value_info('x', TensorProto.FLOAT, [2, 3, 4, 4])
scale = helper.make_tensor_value_info('scale', TensorProto.FLOAT, [3])
bias = helper.make_tensor_value_info('bias', TensorProto.FLOAT, [3, 1])
mean = helper.make_tensor_value_info('mean', TensorProto.FLOAT, [3])
var = helper.make_tensor_value_info('variance', TensorProto.FLOAT, [3])
out = helper.make_tensor_value_info('y', TensorProto.FLOAT, [2, 3, 4, 4])
node = onnx.helper.make_node(
'BatchNormalization',
inputs=['x', 'scale', 'bias', 'mean', 'variance'],
outputs=['y'])
return ([node], [x, scale, bias, mean, var], [out])
......
......@@ -369,36 +369,134 @@ TEST_CASE(averagepool_same_upper_test)
EXPECT(p == prog);
}
TEST_CASE(batchnorm_1d_test)
TEST_CASE(batch_norm_flat_test)
{
migraphx::program p;
auto* mm = p.get_main_module();
auto l0 = mm->add_parameter("0", {migraphx::shape::float_type, {1, 3, 5}});
auto l1 = mm->add_parameter("1", {migraphx::shape::float_type, {3}});
auto l2 = mm->add_parameter("2", {migraphx::shape::float_type, {3}});
auto l3 = mm->add_parameter("3", {migraphx::shape::float_type, {3}});
auto l4 = mm->add_parameter("4", {migraphx::shape::float_type, {3}});
mm->add_instruction(migraphx::make_op("batch_norm_inference"), l0, l1, l2, l3, l4);
auto prog = optimize_onnx("batchnorm_1d_test.onnx");
auto x = mm->add_parameter("x", {migraphx::shape::float_type, {10}});
auto scale = mm->add_parameter("scale", {migraphx::shape::float_type, {1}});
auto bias = mm->add_parameter("bias", {migraphx::shape::float_type, {1}});
auto mean = mm->add_parameter("mean", {migraphx::shape::float_type, {1}});
auto var = mm->add_parameter("variance", {migraphx::shape::float_type, {1}});
auto rt = mm->add_literal(migraphx::literal{migraphx::shape::float_type, {0.5}});
auto eps = mm->add_literal(migraphx::literal{migraphx::shape::float_type, {1e-6f}});
auto numer = add_common_op(*mm, migraphx::make_op("sub"), {x, mean});
auto var_eps = add_common_op(*mm, migraphx::make_op("add"), {var, eps});
auto denom = add_common_op(*mm, migraphx::make_op("pow"), {var_eps, rt});
auto div0 = add_common_op(*mm, migraphx::make_op("div"), {numer, denom});
auto r0 = add_common_op(*mm, migraphx::make_op("mul"), {div0, scale});
add_common_op(*mm, migraphx::make_op("add"), {r0, bias});
auto prog = optimize_onnx("batch_norm_flat_test.onnx");
EXPECT(p == prog);
}
TEST_CASE(batchnorm_3d_test)
TEST_CASE(batch_norm_1d_test)
{
migraphx::program p;
auto* mm = p.get_main_module();
auto l0 = mm->add_parameter("0", {migraphx::shape::float_type, {1, 3, 5, 5, 5}});
auto l1 = mm->add_parameter("1", {migraphx::shape::float_type, {3}});
auto l2 = mm->add_parameter("2", {migraphx::shape::float_type, {3}});
auto l3 = mm->add_parameter("3", {migraphx::shape::float_type, {3}});
auto l4 = mm->add_parameter("4", {migraphx::shape::float_type, {3}});
mm->add_instruction(migraphx::make_op("batch_norm_inference"), l0, l1, l2, l3, l4);
auto prog = optimize_onnx("batchnorm_3d_test.onnx");
auto x = mm->add_parameter("x", {migraphx::shape::half_type, {2, 3, 4}});
auto scale = mm->add_parameter("scale", {migraphx::shape::float_type, {3}});
auto bias = mm->add_parameter("bias", {migraphx::shape::float_type, {3}});
auto mean = mm->add_parameter("mean", {migraphx::shape::float_type, {3}});
auto var = mm->add_parameter("variance", {migraphx::shape::float_type, {3}});
auto rt = mm->add_literal(migraphx::literal{migraphx::shape::half_type, {0.5}});
auto eps = mm->add_literal(migraphx::literal{migraphx::shape::half_type, {1e-5f}});
auto usq_scale = mm->add_instruction(migraphx::make_op("unsqueeze", {{"axes", {1}}}), scale);
auto usq_bias = mm->add_instruction(migraphx::make_op("unsqueeze", {{"axes", {1}}}), bias);
auto usq_mean = mm->add_instruction(migraphx::make_op("unsqueeze", {{"axes", {1}}}), mean);
auto usq_var = mm->add_instruction(migraphx::make_op("unsqueeze", {{"axes", {1}}}), var);
auto numer = add_common_op(*mm, migraphx::make_op("sub"), {x, usq_mean});
auto var_eps = add_common_op(*mm, migraphx::make_op("add"), {usq_var, eps});
auto denom = add_common_op(*mm, migraphx::make_op("pow"), {var_eps, rt});
auto div0 = add_common_op(*mm, migraphx::make_op("div"), {numer, denom});
auto r0 = add_common_op(*mm, migraphx::make_op("mul"), {div0, usq_scale});
add_common_op(*mm, migraphx::make_op("add"), {r0, usq_bias});
auto prog = optimize_onnx("batch_norm_1d_test.onnx");
EXPECT(p == prog);
}
TEST_CASE(batch_norm_2d_test)
{
migraphx::program p;
auto* mm = p.get_main_module();
auto x = mm->add_parameter("x", {migraphx::shape::float_type, {2, 3, 4, 4}});
auto scale = mm->add_parameter("scale", {migraphx::shape::float_type, {3}});
auto bias = mm->add_parameter("bias", {migraphx::shape::float_type, {3}});
auto mean = mm->add_parameter("mean", {migraphx::shape::float_type, {3}});
auto var = mm->add_parameter("variance", {migraphx::shape::float_type, {3}});
auto rt = mm->add_literal(migraphx::literal{migraphx::shape::float_type, {0.5}});
auto eps = mm->add_literal(migraphx::literal{migraphx::shape::float_type, {1e-5f}});
auto usq_scale = mm->add_instruction(migraphx::make_op("unsqueeze", {{"axes", {1, 2}}}), scale);
auto usq_bias = mm->add_instruction(migraphx::make_op("unsqueeze", {{"axes", {1, 2}}}), bias);
auto usq_mean = mm->add_instruction(migraphx::make_op("unsqueeze", {{"axes", {1, 2}}}), mean);
auto usq_var = mm->add_instruction(migraphx::make_op("unsqueeze", {{"axes", {1, 2}}}), var);
auto numer = add_common_op(*mm, migraphx::make_op("sub"), {x, usq_mean});
auto var_eps = add_common_op(*mm, migraphx::make_op("add"), {usq_var, eps});
auto denom = add_common_op(*mm, migraphx::make_op("pow"), {var_eps, rt});
auto div0 = add_common_op(*mm, migraphx::make_op("div"), {numer, denom});
auto r0 = add_common_op(*mm, migraphx::make_op("mul"), {div0, usq_scale});
add_common_op(*mm, migraphx::make_op("add"), {r0, usq_bias});
auto prog = optimize_onnx("batch_norm_2d_test.onnx");
EXPECT(p == prog);
}
TEST_CASE(batch_norm_3d_test)
{
migraphx::program p;
auto* mm = p.get_main_module();
auto x = mm->add_parameter("x", {migraphx::shape::half_type, {2, 2, 2, 2, 2}});
auto scale = mm->add_parameter("scale", {migraphx::shape::half_type, {2}});
auto bias = mm->add_parameter("bias", {migraphx::shape::half_type, {2}});
auto mean = mm->add_parameter("mean", {migraphx::shape::half_type, {2}});
auto var = mm->add_parameter("variance", {migraphx::shape::half_type, {2}});
auto rt = mm->add_literal(migraphx::literal{migraphx::shape::half_type, {0.5}});
auto eps = mm->add_literal(migraphx::literal{migraphx::shape::half_type, {1e-6f}});
auto usq_scale =
mm->add_instruction(migraphx::make_op("unsqueeze", {{"axes", {1, 2, 3}}}), scale);
auto usq_bias =
mm->add_instruction(migraphx::make_op("unsqueeze", {{"axes", {1, 2, 3}}}), bias);
auto usq_mean =
mm->add_instruction(migraphx::make_op("unsqueeze", {{"axes", {1, 2, 3}}}), mean);
auto usq_var = mm->add_instruction(migraphx::make_op("unsqueeze", {{"axes", {1, 2, 3}}}), var);
auto numer = add_common_op(*mm, migraphx::make_op("sub"), {x, usq_mean});
auto var_eps = add_common_op(*mm, migraphx::make_op("add"), {usq_var, eps});
auto denom = add_common_op(*mm, migraphx::make_op("pow"), {var_eps, rt});
auto div0 = add_common_op(*mm, migraphx::make_op("div"), {numer, denom});
auto r0 = add_common_op(*mm, migraphx::make_op("mul"), {div0, usq_scale});
add_common_op(*mm, migraphx::make_op("add"), {r0, usq_bias});
auto prog = optimize_onnx("batch_norm_3d_test.onnx");
EXPECT(p == prog);
}
TEST_CASE(batch_norm_invalid_rank)
{
EXPECT(test::throws([&] { migraphx::parse_onnx("batch_norm_invalid_rank.onnx"); }));
}
TEST_CASE(batch_norm_invalid_bias_rank)
{
EXPECT(test::throws([&] { migraphx::parse_onnx("batch_norm_invalid_bias_rank.onnx"); }));
}
TEST_CASE(cast_test)
{
migraphx::program p;
......@@ -795,14 +893,42 @@ TEST_CASE(conv_bn_relu_maxpool_test)
auto p4 = mm->add_parameter("4", {migraphx::shape::float_type, {1}});
auto p5 = mm->add_parameter("5", {migraphx::shape::float_type, {1}});
auto p6 = mm->add_parameter("6", {migraphx::shape::float_type, {1}});
auto rt = mm->add_literal(migraphx::literal{migraphx::shape::float_type, {0.5}});
auto eps = mm->add_literal(migraphx::literal{migraphx::shape::float_type, {1e-5f}});
uint64_t axis = 1;
auto l3 =
mm->add_instruction(migraphx::make_op("convolution", {{"padding", {0, 0, 0, 0}}}), l0, l1);
auto l4 = mm->add_instruction(
migraphx::make_op("broadcast", {{"axis", axis}, {"out_lens", l3->get_shape().lens()}}), l2);
auto l5 = mm->add_instruction(migraphx::make_op("add"), l3, l4);
auto l6 = mm->add_instruction(
migraphx::make_op("batch_norm_inference", {{"epsilon", 1.0e-5f}}), l5, p3, p4, p5, p6);
auto usq_scale = mm->add_instruction(migraphx::make_op("unsqueeze", {{"axes", {1, 2}}}), p3);
auto usq_bias = mm->add_instruction(migraphx::make_op("unsqueeze", {{"axes", {1, 2}}}), p4);
auto usq_mean = mm->add_instruction(migraphx::make_op("unsqueeze", {{"axes", {1, 2}}}), p5);
auto usq_var = mm->add_instruction(migraphx::make_op("unsqueeze", {{"axes", {1, 2}}}), p6);
auto mb_mean = mm->add_instruction(
migraphx::make_op("multibroadcast", {{"out_lens", {1, 1, 28, 28}}}), usq_mean);
auto numer = mm->add_instruction(migraphx::make_op("sub"), l5, mb_mean);
auto mb_eps =
mm->add_instruction(migraphx::make_op("multibroadcast", {{"out_lens", {1, 1, 1}}}), eps);
auto var_eps = mm->add_instruction(migraphx::make_op("add"), usq_var, mb_eps);
auto mb_rt =
mm->add_instruction(migraphx::make_op("multibroadcast", {{"out_lens", {1, 1, 1}}}), rt);
auto denom = mm->add_instruction(migraphx::make_op("pow"), var_eps, mb_rt);
auto mb_denom = mm->add_instruction(
migraphx::make_op("multibroadcast", {{"out_lens", {1, 1, 28, 28}}}), denom);
auto div0 = mm->add_instruction(migraphx::make_op("div"), numer, mb_denom);
auto mb_scale = mm->add_instruction(
migraphx::make_op("multibroadcast", {{"out_lens", {1, 1, 28, 28}}}), usq_scale);
auto r0 = mm->add_instruction(migraphx::make_op("mul"), div0, mb_scale);
auto mb_bias = mm->add_instruction(
migraphx::make_op("multibroadcast", {{"out_lens", {1, 1, 28, 28}}}), usq_bias);
auto l6 = mm->add_instruction(migraphx::make_op("add"), r0, mb_bias);
auto l7 = mm->add_instruction(migraphx::make_op("relu"), l6);
mm->add_instruction(migraphx::make_op("pooling",
{{"mode", migraphx::op::pooling_mode::max},
......
......@@ -30,6 +30,7 @@
#include <migraphx/pass_manager.hpp>
#include <migraphx/verify.hpp>
#include <migraphx/onnx.hpp>
#include <migraphx/half.hpp>
#include "test.hpp"
TEST_CASE(averagepool_notset_test)
......@@ -68,6 +69,196 @@ TEST_CASE(averagepool_nt_cip_test)
EXPECT(migraphx::verify_range(result_vector, gold));
}
TEST_CASE(batch_norm_flat_test)
{
migraphx::program p = migraphx::parse_onnx("batch_norm_flat_test.onnx");
p.compile(migraphx::ref::target{});
migraphx::shape x_shape{migraphx::shape::float_type, {10}};
migraphx::shape c_shape(migraphx::shape::float_type, {1});
std::vector<float> x_data = {1.6524342,
-0.51048076,
0.32543048,
2.4410043,
2.0833702,
0.44981122,
1.0044622,
-0.24006313,
-0.43065986,
0.07626268};
std::vector<float> scale_data = {-0.02927135};
std::vector<float> bias_data = {0.42347777};
std::vector<float> mean_data = {-0.00449735};
std::vector<float> variance_data = {0.5184545};
migraphx::parameter_map params;
params["x"] = migraphx::argument(x_shape, x_data.data());
params["scale"] = migraphx::argument(c_shape, scale_data.data());
params["bias"] = migraphx::argument(c_shape, bias_data.data());
params["mean"] = migraphx::argument(c_shape, mean_data.data());
params["variance"] = migraphx::argument(c_shape, variance_data.data());
auto result = p.eval(params).back();
std::vector<float> result_vector;
result.visit([&](auto output) { result_vector.assign(output.begin(), output.end()); });
std::vector<float> gold = {0.35612,
0.44404706,
0.4100655,
0.32406294,
0.33860153,
0.40500915,
0.38246143,
0.43305403,
0.4408022,
0.42019472};
EXPECT(migraphx::verify_range(result_vector, gold));
}
TEST_CASE(batch_norm_1d_test)
{
migraphx::program p = migraphx::parse_onnx("batch_norm_1d_test.onnx");
p.compile(migraphx::ref::target{});
migraphx::shape x_shape{migraphx::shape::half_type, {2, 3, 4}};
migraphx::shape c_shape(migraphx::shape::float_type, {3});
std::vector<float> tmp = {1.652, -0.5103, 0.3254, 2.441, 2.084, 0.4497,
1.005, -0.2401, -0.4307, 0.07623, -0.02927, 0.4236,
-0.004498, -0.4282, -0.5527, 0.02205, -1.472, -1.7295,
0.796, 0.9507, 0.2312, 0.664, -0.06964, 1.035};
std::vector<migraphx::half> x_data{tmp.cbegin(), tmp.cend()};
std::vector<float> scale_data = {-1.336926, -1.0679098, 0.10368501};
std::vector<float> bias_data = {0.20240043, -0.70175606, -0.8859727};
std::vector<float> mean_data = {0.30854642, -0.36574763, -0.9463552};
std::vector<float> variance_data = {0.43428132, 0.97773486, 0.30332062};
migraphx::parameter_map params;
params["x"] = migraphx::argument(x_shape, x_data.data());
params["scale"] = migraphx::argument(c_shape, scale_data.data());
params["bias"] = migraphx::argument(c_shape, bias_data.data());
params["mean"] = migraphx::argument(c_shape, mean_data.data());
params["variance"] = migraphx::argument(c_shape, variance_data.data());
auto result = p.eval(params).back();
std::vector<migraphx::half> result_vector;
result.visit([&](auto output) { result_vector.assign(output.begin(), output.end()); });
tmp = {-2.523, 1.863, 0.1681, -4.125, -3.348, -1.582, -2.182, -0.8374,
-0.789, -0.6934, -0.7134, -0.628, 0.8374, 1.697, 1.949, 0.7837,
0.4927, 0.771, -1.956, -2.123, -0.664, -0.583, -0.7207, -0.5127};
std::vector<migraphx::half> gold{tmp.cbegin(), tmp.cend()};
EXPECT(migraphx::verify_range(result_vector, gold));
}
TEST_CASE(batch_norm_2d_test)
{
migraphx::program p = migraphx::parse_onnx("batch_norm_2d_test.onnx");
p.compile(migraphx::ref::target{});
migraphx::shape x_shape{migraphx::shape::float_type, {2, 3, 4, 4}};
migraphx::shape c_shape(migraphx::shape::float_type, {3});
std::vector<float> x_data = {
1.6524342, -0.51048076, 0.32543048, 2.4410043, 2.0833702, 0.44981122, 1.0044622,
-0.24006313, -0.43065986, 0.07626268, -0.02927135, 0.42347777, -0.00449735, -0.4281568,
-0.5527635, 0.02204161, -1.4719028, -1.7298799, 0.79596406, 0.9505461, 0.23115851,
0.6639593, -0.06963254, 1.0348768, -1.336926, -1.0679098, 0.10368501, 0.20240043,
-0.70175606, -0.8859727, 0.30854642, -0.36574763, -0.9463552, 0.9476916, 0.37686515,
-0.05184272, -0.7151244, -0.37341377, 0.59440356, 0.10051094, -0.20755945, 0.9098465,
1.1664004, 1.4075205, -1.1522529, -0.34607422, 0.32027543, -0.6885485, 0.5404544,
0.10012514, 0.8767704, 1.0032021, -1.2755303, 0.23577735, 0.74239916, 1.0146079,
0.60875916, -0.29163074, 1.4872868, 0.20466477, -0.26367408, -0.56394804, -0.56043875,
0.7763664, -0.9626441, 0.29653943, -3.2231965, 0.03322164, 0.03402911, 0.77308357,
-0.0654009, -0.30463725, 0.22182712, -0.22594836, -0.5807543, -0.22390617, -0.24484141,
-2.0761833, 1.8459716, 0.2455878, 0.99913245, -0.9266217, -0.1938893, 0.6417983,
-1.0880078, 0.49565446, 2.1584804, 1.2276239, 3.3091128, 0.14217089, 0.9425477,
0.07578196, 0.4067431, 0.71984154, -0.20796849, 0.90003085};
std::vector<float> scale_data = {0.658487, 0.03700604, 2.463201};
std::vector<float> bias_data = {0.03497279, 0.17080553, 0.5636415};
std::vector<float> mean_data = {0.1954783, 0.6203974, 0.8116831};
std::vector<float> variance_data = {0.30558077, 0.04536599, 0.05461315};
migraphx::parameter_map params;
params["x"] = migraphx::argument(x_shape, x_data.data());
params["scale"] = migraphx::argument(c_shape, scale_data.data());
params["bias"] = migraphx::argument(c_shape, bias_data.data());
params["mean"] = migraphx::argument(c_shape, mean_data.data());
params["variance"] = migraphx::argument(c_shape, variance_data.data());
auto result = p.eval(params).back();
std::vector<float> result_vector;
result.visit([&](auto output) { result_vector.assign(output.begin(), output.end()); });
std::vector<float> gold = {
1.77046824e+00, -8.05950999e-01, 1.89769119e-01, 2.70979643e+00, 2.28379035e+00,
3.37928861e-01, 9.98617530e-01, -4.83835101e-01, -7.10869908e-01, -1.07034385e-01,
-2.32744321e-01, 3.06560963e-01, -2.03234047e-01, -7.07888365e-01, -8.56317282e-01,
-1.71621382e-01, -1.92677066e-01, -2.37493858e-01, 2.01305658e-01, 2.28160262e-01,
1.03185430e-01, 1.78373277e-01, 5.09308279e-02, 2.42810518e-01, -1.69228360e-01,
-1.22493818e-01, 8.10402334e-02, 9.81894583e-02, -5.88841513e-02, -9.08869803e-02,
1.16629556e-01, -5.11445105e-04, -1.79648399e+01, 1.99707508e+00, -4.01903248e+00,
-8.53731060e+00, -1.55278311e+01, -1.19264421e+01, -1.72633123e+00, -6.93161058e+00,
-1.01784554e+01, 1.59821415e+00, 4.30211163e+00, 6.84334660e+00, -2.01348572e+01,
-1.16383028e+01, -4.61544800e+00, -1.52477398e+01, 4.45901126e-01, -7.86099210e-02,
8.46513629e-01, 9.97116446e-01, -1.71726203e+00, 8.29761624e-02, 6.86453462e-01,
1.01070285e+00, 5.27264357e-01, -5.45261383e-01, 1.57374811e+00, 4.59154993e-02,
-5.11959970e-01, -8.69639993e-01, -8.65459919e-01, 7.26914644e-01, -1.04206637e-01,
1.14543661e-01, -4.96918678e-01, 6.87990561e-02, 6.89393356e-02, 1.97330773e-01,
5.16659655e-02, 1.01048872e-02, 1.01564340e-01, 2.37750299e-02, -3.78632471e-02,
2.41298079e-02, 2.04928555e-02, -2.97655046e-01, 3.83717060e-01, 1.05692141e-01,
2.53922558e+00, -1.77568626e+01, -1.00343809e+01, -1.22682428e+00, -1.94577579e+01,
-2.76707697e+00, 1.47579327e+01, 4.94736385e+00, 2.68847847e+01, -6.49254417e+00,
1.94286156e+00, -7.19223642e+00, -3.70413971e+00, -4.04303551e-01, -1.01827660e+01,
1.49476433e+00};
EXPECT(migraphx::verify_range(result_vector, gold));
}
TEST_CASE(batch_norm_3d_test)
{
migraphx::program p = migraphx::parse_onnx("batch_norm_3d_test.onnx");
p.compile(migraphx::ref::target{});
migraphx::shape x_shape{migraphx::shape::half_type, {2, 2, 2, 2, 2}};
migraphx::shape c_shape(migraphx::shape::half_type, {2});
// using migraphx::half copy conversion since it doesn't have initializer_list constructor
std::vector<float> tmp = {5., 5., 8., 7., 3., 4., 1., 7., 5., 5., 9., 4., 7., 2., 2., 2.,
6., 1., 4., 9., 2., 8., 0., 2., 1., 4., 8., 8., 3., 3., 0., 8.};
std::vector<migraphx::half> x_data{tmp.cbegin(), tmp.cend()};
tmp = {1., 1.};
std::vector<migraphx::half> scale_data{tmp.cbegin(), tmp.cend()};
tmp = {
0.,
0.,
};
std::vector<migraphx::half> bias_data{tmp.cbegin(), tmp.cend()};
tmp = {-0.75, 0.29};
std::vector<migraphx::half> mean_data{tmp.cbegin(), tmp.cend()};
tmp = {0.31, 0.37};
std::vector<migraphx::half> variance_data{tmp.cbegin(), tmp.cend()};
migraphx::parameter_map params;
params["x"] = migraphx::argument(x_shape, x_data.data());
params["scale"] = migraphx::argument(c_shape, scale_data.data());
params["bias"] = migraphx::argument(c_shape, bias_data.data());
params["mean"] = migraphx::argument(c_shape, mean_data.data());
params["variance"] = migraphx::argument(c_shape, variance_data.data());
auto result = p.eval(params).back();
std::vector<migraphx::half> result_vector;
result.visit([&](auto output) { result_vector.assign(output.begin(), output.end()); });
tmp = {10.33, 10.33, 15.71, 13.914, 6.734, 8.53, 3.143, 13.914, 7.742, 7.742, 14.32,
6.098, 11.03, 2.81, 2.81, 2.81, 12.125, 3.143, 8.53, 17.52, 4.938, 15.71,
1.347, 4.938, 1.167, 6.098, 12.67, 12.67, 4.453, 4.453, -0.4768, 12.67};
std::vector<migraphx::half> gold{tmp.cbegin(), tmp.cend()};
EXPECT(migraphx::verify_range(result_vector, gold));
}
TEST_CASE(celu_verify_test)
{
migraphx::program p = migraphx::parse_onnx("celu_verify_test.onnx");
......
......@@ -56,4 +56,5 @@ add_py_test(gpu_offload test_gpu_offload.py WORKING_DIRECTORY ${TEST_ONNX_DIR})
add_py_test(gpu test_gpu.py WORKING_DIRECTORY ${TEST_ONNX_DIR})
add_py_test(array test_array.py WORKING_DIRECTORY ${TEST_ONNX_DIR})
add_py_test(backend onnx_backend_test.py WORKING_DIRECTORY ${TEST_ONNX_DIR})
add_py_test(gpu_async test_gpu_async.py WORKING_DIRECTORY ${TEST_ONNX_DIR})
endif()
......@@ -138,6 +138,7 @@ def create_backend_test(testname=None, target_device=None):
backend_test.include(r'.*test_eyelike.*')
backend_test.include(r'.*test_flatten.*')
backend_test.include(r'.*test_floor.*')
backend_test.include(r'.*test_fmod.*')
backend_test.include(r'.*test_gather.*')
backend_test.include(r'.*test_gemm.*')
backend_test.include(r'.*test_globalaveragepool.*')
......@@ -162,6 +163,7 @@ def create_backend_test(testname=None, target_device=None):
backend_test.include(r'.*test_MaxPool[1-9]d.*')
backend_test.include(r'.*test_mean.*')
backend_test.include(r'.*test_min.*')
backend_test.include(r' .*test_mod.*')
backend_test.include(r'.*test_mul.*')
backend_test.include(r'.*test_multinomial.*')
backend_test.include(r'.*test_Multinomial.*')
......@@ -179,6 +181,7 @@ def create_backend_test(testname=None, target_device=None):
backend_test.include(r'.*test_operator_max_.*')
backend_test.include(r'.*test_operator_maxpool.*')
backend_test.include(r'.*test_operator_min.*')
backend_test.include(r'.*test_operator_mod.*')
backend_test.include(r'.*test_operator_mm.*')
backend_test.include(r'.*test_operator_non_float_params.*')
backend_test.include(r'.*test_operator_params.*')
......
#####################################################################################
# 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.
#####################################################################################
import migraphx
import ctypes
def test_conv_relu():
hip = ctypes.cdll.LoadLibrary("libamdhip64.so")
p = migraphx.parse_onnx("conv_relu_maxpool_test.onnx")
print(p)
print("Compiling ...")
# Need to have offload_copy = False to avoid syncs() back to the host device
p.compile(migraphx.get_target("gpu"), offload_copy=False)
print(p)
params = {}
# Using default value in api for hipSuccess which is always 0
hipSuccess = ctypes.c_long(0)
# Alloc a stream
stream = ctypes.c_void_p()
err = ctypes.c_long(
hip.hipStreamCreateWithFlags(ctypes.byref(stream), ctypes.c_uint(0)))
if err.value != hipSuccess.value:
print("FAILED hipStreamCreate")
return err
# Use to_gpu to push generated argument to the GPU before we perform a run
for key, value in p.get_parameter_shapes().items():
params[key] = migraphx.to_gpu(migraphx.generate_argument(value))
result = migraphx.from_gpu(
p.run_async(params, stream.value, "ihipStream_t")[-1])
# Wait for all commands in stream to complete
err = ctypes.c_long(hip.hipStreamSynchronize(stream))
if err.value != hipSuccess.value:
print("FAILED: hipStreamSyncronize")
return err
# Cleanup Stream
err = ctypes.c_long(hip.hipStreamDestroy(stream))
if err.value != hipSuccess.value:
print("FAILED: hipStreamDestroy")
return err
print(result)
test_conv_relu()
......@@ -3591,7 +3591,7 @@ TEST_CASE(multinomial_test)
result.visit([&](auto output) { result_vec.assign(output.begin(), output.end()); });
std::vector<int> res_dist(5, 0);
for(auto& r : result_vec)
for(const auto& r : result_vec)
res_dist[r]++;
auto dist_sum = std::accumulate(dist.begin(), dist.end(), 0);
auto res_dist_sum = std::accumulate(res_dist.begin(), res_dist.end(), 0);
......
......@@ -236,6 +236,105 @@ TEST_CASE(simplify_mul_conv1)
EXPECT(new_conv->outputs().front()->name() != "mul");
}
TEST_CASE(simplify_mul_conv2)
{
migraphx::module m;
auto x = m.add_parameter("x", {migraphx::shape::int32_type, {1, 128, 28, 28}});
auto w =
m.add_literal(migraphx::generate_literal({migraphx::shape::int32_type, {256, 128, 3, 3}}));
auto conv = m.add_instruction(
migraphx::make_op("convolution",
{{"padding", {1, 1}}, {"stride", {2, 2}}, {"dilation", {1, 1}}}),
x,
w);
auto a = m.add_literal(migraphx::generate_literal({migraphx::shape::int32_type, {256}}));
auto unsq_a = m.add_instruction(migraphx::make_op("unsqueeze", {{"axes", {1, 2}}}), a);
auto b = m.add_instruction(
migraphx::make_op("multibroadcast", {{"out_lens", {1, 256, 14, 14}}}), unsq_a);
auto mul = m.add_instruction(migraphx::make_op("mul"), conv, b);
m.add_instruction(pass_op{}, mul);
EXPECT(conv->outputs().front()->name() == "mul");
run_pass(m);
auto new_conv =
std::find_if(m.begin(), m.end(), [](auto&& ins) { return ins.name() == "convolution"; });
EXPECT(new_conv->outputs().front()->name() != "mul");
}
// len = 1 case
TEST_CASE(simplify_mul_conv3)
{
migraphx::module m;
auto x = m.add_parameter("x", {migraphx::shape::int32_type, {1, 128, 28, 28}});
auto w =
m.add_literal(migraphx::generate_literal({migraphx::shape::int32_type, {256, 128, 3, 3}}));
auto conv = m.add_instruction(
migraphx::make_op("convolution",
{{"padding", {1, 1}}, {"stride", {2, 2}}, {"dilation", {1, 1}}}),
x,
w);
auto a = m.add_literal(
migraphx::generate_literal({migraphx::shape::int32_type, {256, 1, 1}, {1, 18, 1}}));
auto b =
m.add_instruction(migraphx::make_op("multibroadcast", {{"out_lens", {1, 256, 14, 14}}}), a);
auto mul = m.add_instruction(migraphx::make_op("mul"), conv, b);
m.add_instruction(pass_op{}, mul);
EXPECT(conv->outputs().front()->name() == "mul");
run_pass(m);
auto new_conv =
std::find_if(m.begin(), m.end(), [](auto&& ins) { return ins.name() == "convolution"; });
EXPECT(new_conv->outputs().front()->name() != "mul");
}
// Previously broadcasted literal case, should skip
TEST_CASE(simplify_mul_conv_skip1)
{
migraphx::module m;
auto x = m.add_parameter("x", {migraphx::shape::int32_type, {1, 128, 28, 28}});
auto w =
m.add_literal(migraphx::generate_literal({migraphx::shape::int32_type, {256, 128, 3, 3}}));
auto conv = m.add_instruction(
migraphx::make_op("convolution",
{{"padding", {1, 1}}, {"stride", {2, 2}}, {"dilation", {1, 1}}}),
x,
w);
auto a = m.add_literal(
migraphx::generate_literal({migraphx::shape::int32_type, {256, 14, 14}, {1, 0, 0}}));
auto b = m.add_instruction(
migraphx::make_op("broadcast", {{"axis", 1}, {"out_lens", {1, 256, 14, 14}}}), a);
auto mul = m.add_instruction(migraphx::make_op("mul"), conv, b);
m.add_instruction(pass_op{}, mul);
EXPECT(conv->outputs().front()->name() == "mul");
run_pass(m);
auto new_conv =
std::find_if(m.begin(), m.end(), [](auto&& ins) { return ins.name() == "convolution"; });
EXPECT(new_conv->outputs().front()->name() == "mul");
}
// Another previously broadcasted literal case, should skip
TEST_CASE(simplify_mul_conv_skip2)
{
migraphx::module m;
auto x = m.add_parameter("x", {migraphx::shape::int32_type, {1, 128, 28, 28}});
auto w =
m.add_literal(migraphx::generate_literal({migraphx::shape::int32_type, {256, 128, 3, 3}}));
auto conv = m.add_instruction(
migraphx::make_op("convolution",
{{"padding", {1, 1}}, {"stride", {2, 2}}, {"dilation", {1, 1}}}),
x,
w);
auto a = m.add_literal(
migraphx::generate_literal({migraphx::shape::int32_type, {256, 14, 14}, {1, 0, 0}}));
auto b =
m.add_instruction(migraphx::make_op("multibroadcast", {{"out_lens", {1, 256, 14, 14}}}), a);
auto mul = m.add_instruction(migraphx::make_op("mul"), conv, b);
m.add_instruction(pass_op{}, mul);
EXPECT(conv->outputs().front()->name() == "mul");
run_pass(m);
auto new_conv =
std::find_if(m.begin(), m.end(), [](auto&& ins) { return ins.name() == "convolution"; });
EXPECT(new_conv->outputs().front()->name() == "mul");
}
TEST_CASE(simplify_mul_slice_conv1)
{
migraphx::module m1;
......
......@@ -21,41 +21,26 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MIGRAPHX_GUARD_RTGLIB_CLIP_HPP
#define MIGRAPHX_GUARD_RTGLIB_CLIP_HPP
#include <migraphx/argument.hpp>
#include <migraphx/reflect.hpp>
#include <migraphx/op/clip.hpp>
#include "verify_program.hpp"
#include <migraphx/program.hpp>
#include <migraphx/generate.hpp>
#include <migraphx/make_op.hpp>
namespace migraphx {
inline namespace MIGRAPHX_INLINE_NS {
namespace gpu {
struct context;
struct hip_clip
struct test_conv_group_add : verify_program<test_conv_group_add>
{
op::clip op;
template <class Self, class F>
static auto reflect(Self& self, F f)
{
return migraphx::reflect(self.op, f);
}
std::string name() const { return "gpu::clip"; }
shape compute_shape(std::vector<shape> inputs) const;
argument
compute(context& ctx, const shape& output_shape, const std::vector<argument>& args) const;
std::ptrdiff_t output_alias(const std::vector<shape>& shapes) const
migraphx::program create_program() const
{
return shapes.size() - 1;
migraphx::program p;
auto* mm = p.get_main_module();
migraphx::shape s{migraphx::shape::float_type, {1, 68, 28, 28}};
auto x = mm->add_parameter("x", s);
auto w = mm->add_parameter("w", {migraphx::shape::float_type, {68, 17, 1, 1}});
auto b = mm->add_parameter("b", {migraphx::shape::float_type, {68}});
auto conv = mm->add_instruction(migraphx::make_op("convolution", {{"group", 4}}), x, w);
auto bb = mm->add_instruction(
migraphx::make_op("broadcast", {{"axis", 1}, {"out_lens", {1, 68, 28, 28}}}), b);
mm->add_instruction(migraphx::make_op("add"), conv, bb);
return p;
}
};
} // namespace gpu
} // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx
#endif
......@@ -21,43 +21,53 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MIGRAPHX_GUARD_RTGLIB_CONVERT_HPP
#define MIGRAPHX_GUARD_RTGLIB_CONVERT_HPP
#include <migraphx/argument.hpp>
#include <migraphx/reflect.hpp>
#include <migraphx/op/convert.hpp>
#include "verify_program.hpp"
#include <migraphx/program.hpp>
#include <migraphx/generate.hpp>
#include <migraphx/make_op.hpp>
#include <migraphx/common.hpp>
namespace migraphx {
inline namespace MIGRAPHX_INLINE_NS {
namespace gpu {
struct context;
/*
Checking for y == 0 ? eps : y
struct hip_convert
Adding this because HIP fmod sign changes when y = 0 resulting in nan and -nan not beign
consistent between ref and gpu implementations.
*/
migraphx::instruction_ref add_epsilon(migraphx::module& m, migraphx::instruction_ref y)
{
op::convert op;
auto zero = m.add_literal(0.0f);
auto eps = m.add_literal(1e-3f);
auto op_y = add_common_op(m, migraphx::make_op("equal"), {y, zero});
return add_common_op(m, migraphx::make_op("where"), {op_y, eps, y});
}
template <class Self, class F>
static auto reflect(Self& self, F f)
struct test_fmod : verify_program<test_fmod>
{
migraphx::program create_program() const
{
return migraphx::reflect(self.op, f);
migraphx::program p;
auto* mm = p.get_main_module();
migraphx::shape s{migraphx::shape::float_type, {64}};
auto x = mm->add_parameter("x", s);
auto y = mm->add_parameter("y", s);
auto op_where = add_epsilon(*mm, y);
mm->add_instruction(migraphx::make_op("fmod"), x, op_where);
return p;
}
};
std::string name() const { return "gpu::convert"; }
shape compute_shape(std::vector<shape> inputs) const;
argument compute(context& ctx, const shape&, const std::vector<argument>& args) const;
std::ptrdiff_t output_alias(const std::vector<shape>& shapes) const
struct test_mod : verify_program<test_mod>
{
migraphx::program create_program() const
{
return shapes.size() - 1;
migraphx::program p;
auto* mm = p.get_main_module();
migraphx::shape s{migraphx::shape::float_type, {64}};
auto x = mm->add_parameter("x", s);
auto y = mm->add_parameter("y", s);
auto op_where = add_epsilon(*mm, y);
mm->add_instruction(migraphx::make_op("mod"), x, op_where);
return p;
}
};
} // namespace gpu
} // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx
#endif
......@@ -29,14 +29,16 @@
#include <migraphx/op/reduce_mean.hpp>
migraphx::instruction_ref
add_layernorm(migraphx::module& m, migraphx::instruction_ref x, std::vector<size_t> dims)
migraphx::instruction_ref add_layernorm(migraphx::module& m,
migraphx::instruction_ref x,
std::vector<size_t> dims,
float eps = 1e-12f)
{
auto scale =
m.add_parameter("scale", migraphx::shape{migraphx::shape::float_type, {dims.back()}});
auto bias =
m.add_parameter("bias", migraphx::shape{migraphx::shape::float_type, {dims.back()}});
auto epsilon = m.add_literal(1e-12f);
auto epsilon = m.add_literal(eps);
auto exponent = m.add_literal(2.0f);
auto mean = m.add_instruction(migraphx::op::reduce_mean({2}), x);
......@@ -88,6 +90,19 @@ struct test_layernorm2 : verify_program<test_layernorm2>
}
};
struct test_layernorm_eps : verify_program<test_layernorm_eps>
{
migraphx::program create_program() const
{
migraphx::program p;
auto* mm = p.get_main_module();
std::vector<size_t> dims = {1, 2, 5};
auto x = mm->add_parameter("x", migraphx::shape{migraphx::shape::float_type, dims});
add_layernorm(*mm, x, dims, 1e-5f);
return p;
}
};
struct test_layernorm_triadd : verify_program<test_layernorm_triadd>
{
migraphx::program create_program() const
......
......@@ -21,23 +21,23 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MIGRAPHX_GUARD_RTGLIB_DEVICE_SOFTMAX_HPP
#define MIGRAPHX_GUARD_RTGLIB_DEVICE_SOFTMAX_HPP
#include <migraphx/argument.hpp>
#include <migraphx/config.hpp>
#include <hip/hip_runtime_api.h>
#include "verify_program.hpp"
#include <migraphx/program.hpp>
#include <migraphx/generate.hpp>
#include <migraphx/make_op.hpp>
#include <migraphx/common.hpp>
namespace migraphx {
inline namespace MIGRAPHX_INLINE_NS {
namespace gpu {
namespace device {
void softmax(hipStream_t stream, const argument& result, const argument& arg, int64_t axis);
} // namespace device
} // namespace gpu
} // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx
#endif
struct test_softmax_large3 : verify_program<test_softmax_large3>
{
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_type, {2, 4}});
auto large = mm->add_literal({migraphx::shape{migraphx::shape::float_type}, {100}});
auto add = migraphx::add_common_op(*mm, migraphx::make_op("mul"), {x, large});
mm->add_instruction(migraphx::make_op("softmax", {{"axis", -1}}), add);
return p;
}
};
......@@ -116,6 +116,9 @@ def main():
model = migraphx.parse_onnx(model_name, default_dim_value=batch)
if args.verbose:
print(model)
model.compile(migraphx.get_target('gpu'), offload_copy=False)
params = {}
......
......@@ -21,7 +21,10 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#####################################################################################
import string, sys, re, runpy
import string
import sys
import re
import runpy
from functools import wraps
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
......@@ -308,18 +311,39 @@ class Parameter:
return self.substitute('${type} ${name}', prefix=prefix)
def virtual_output_args(self, prefix: Optional[str] = None) -> List[str]:
return [
'&{prefix}{n}'.format(prefix=prefix or '', n=n)
for t, n in self.cparams
]
container_type = self.type.remove_generic().basic().str()
decl_list: List[str] = []
container = (container_type == "std::vector"
or container_type == "vector")
for t, n, in self.cparams:
if not decl_list and container:
decl_list.append('{prefix}{n}.data()'.format(prefix=prefix
or '',
n=n))
else:
decl_list.append('&{prefix}{n}'.format(prefix=prefix or '',
n=n))
return decl_list
def virtual_output_declarations(self,
prefix: Optional[str] = None) -> List[str]:
return [
'std::remove_pointer_t<{type}> {prefix}{n};'.format(
type=Type(t).str(), prefix=prefix or '', n=n)
for t, n in self.cparams
]
container_type = self.type.remove_generic().basic().str()
container = (container_type == "std::vector"
or container_type == "vector")
decl_list: List[str] = []
for t, n, in self.cparams:
if not decl_list and container:
inner_t = self.type.inner_type()
if inner_t:
decl_list.append(
'std::array<{inner_t}, 1024> {prefix}{n};'.format(
inner_t=inner_t.str(), prefix=prefix or '', n=n))
else:
decl_list.append(
'std::remove_pointer_t<{type}> {prefix}{n}'.format(
type=Type(t).str(), prefix=prefix or '', n=n))
decl_list[-1] += '=1024;' if container else ';'
return decl_list
def virtual_output(self, prefix: Optional[str] = None) -> str:
write = self.virtual_write
......@@ -694,9 +718,14 @@ def generate_cpp_header() -> str:
[c.generate() for c in cpp_classes])
def cwrap(name: str) -> Callable:
c_type_map: Dict[str, Type] = {}
def cwrap(name: str, c_type: Optional[str] = None) -> Callable:
def with_cwrap(f):
type_map[name] = f
if c_type:
c_type_map[name] = Type(c_type)
@wraps(f)
def decorated(*args, **kwargs):
......@@ -917,6 +946,9 @@ def vector_c_wrap(p: Parameter) -> None:
# Not a generic type
if not inner:
return
if inner.str() in c_type_map:
inner = c_type_map[inner.str()]
t = inner.add_pointer()
if p.type.is_reference():
if p.type.is_const():
......@@ -927,6 +959,12 @@ def vector_c_wrap(p: Parameter) -> None:
p.add_size_param()
p.bad_param('${name} == nullptr or ${size} == nullptr',
'Null pointer')
elif p.virtual:
p.add_param(t)
p.add_size_param()
p.bad_param('${name} == nullptr or ${size} == nullptr',
'Null pointer')
p.virtual_write = '{${name}.begin(), ${name}.begin()+${size}}; // cppcheck-suppress returnDanglingLifetime'
else:
p.add_param(t)
p.bad_param('${name} == nullptr', 'Null pointer')
......@@ -946,7 +984,7 @@ def vector_c_wrap(p: Parameter) -> None:
p.write = ['std::copy(${result}.begin(), ${result}.end(), ${name})']
@cwrap('std::string')
@cwrap('std::string', 'char*')
def string_c_wrap(p: Parameter) -> None:
t = Type('char*')
if p.returns:
......@@ -1061,9 +1099,9 @@ struct ${ctype} {
c_api_virtual_impl = Template('''
${return_type} ${name}(${params}) const
{
${output_decls}
if (${fname} == nullptr)
throw std::runtime_error("${name} function is missing.");
${output_decls}
std::array<char, 256> exception_msg;
exception_msg.front() = '\\0';
auto api_error_result = ${fname}(${args});
......
......@@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <migraphx/execution_environment.hpp>
#include <migraphx/migraphx.h>
#include <migraphx/rank.hpp>
#include <migraphx/shape.hpp>
......@@ -166,6 +167,13 @@ void set_output_names(tf_options& options, std::vector<const char*> names)
options.output_node_names = std::vector<std::string>(names.begin(), names.end());
}
std::vector<argument>
run_async(program& p, const parameter_map& params, void* s, std::string_view name)
{
execution_environment exec_env{any_ptr(s, name), true};
return p.eval(params, exec_env);
}
template <class Value>
std::vector<const char*> get_names(const std::unordered_map<std::string, Value>& m)
{
......@@ -265,11 +273,18 @@ struct experimental_custom_op
template <class CustomOp>
struct custom_operation
{
template <class Self, class F>
static auto reflect(Self&, F)
{
return pack();
}
value attributes() const
{
return {{"custom_op", true}, {"target", op.runs_on_offload_target() ? "gpu" : "cpu"}};
}
CustomOp op;
std::string name() const { return op.xobject.name; }
......@@ -284,6 +299,23 @@ struct custom_operation
{
return op.compute(std::move(ctx), std::move(output_shape), std::move(inputs));
}
std::ptrdiff_t output_alias(std::vector<shape> inputs) const
{
auto alias_vec = op.output_alias(std::move(inputs));
// TODO: For now, only support one output alias
if(alias_vec.empty())
{
return -1;
}
if(alias_vec.size() > 1)
{
MIGRAPHX_THROW("Currently, CustomOps in MIGraphX only supports one output_alias");
}
return alias_vec.front();
}
bool runs_on_offload_target() const { return op.runs_on_offload_target(); }
};
template <class CustomOp>
......
......@@ -26,7 +26,6 @@
#include <stdlib.h>
#include <stdbool.h>
// Add new types here
// clang-format off
#define MIGRAPHX_SHAPE_VISIT_TYPES(m) \
......
......@@ -66,12 +66,21 @@ any_ptr get_queue_context(T&)
{
return {};
}
template <class T>
void wait_for_context(T&, any_ptr)
{
}
template <class T>
void finish_on_context(T&, any_ptr){}
<%
interface('context',
virtual('to_value', returns = 'value', const = True, default = 'to_value_context'),
virtual('from_value', v = 'const value&', default = 'from_value_context'),
virtual('get_queue', returns = 'any_ptr', default = 'get_queue_context'),
virtual('wait_for', queue = 'any_ptr', returns = 'void', default = 'wait_for_context'),
virtual('finish_on', queue = 'any_ptr', returns = 'void', default = 'finish_on_context'),
virtual('finish', returns = 'void', const = True)) %>
inline void migraphx_to_value(value& v, const context& ctx)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment