Commit b119ed8f authored by Alan Turner's avatar Alan Turner
Browse files

Merge branch 'develop' of https://github.com/ROCmSoftwarePlatform/AMDMIGraphX into develop

parents 26d1a969 6f1c947f
...@@ -96,7 +96,7 @@ struct parse_randomuniform_ops : op_parser<parse_randomuniform_ops> ...@@ -96,7 +96,7 @@ struct parse_randomuniform_ops : op_parser<parse_randomuniform_ops>
if(contains(info.attributes, "seed")) if(contains(info.attributes, "seed"))
gen.seed(info.attributes.at("seed").f()); gen.seed(info.attributes.at("seed").f());
std::uniform_real_distribution<> d(high, low); std::uniform_real_distribution<> d(low, high);
std::vector<double> rand_vals(out_shape.elements()); std::vector<double> rand_vals(out_shape.elements());
std::generate(rand_vals.begin(), rand_vals.end(), [&]() { return d(gen); }); std::generate(rand_vals.begin(), rand_vals.end(), [&]() { return d(gen); });
......
...@@ -34,16 +34,65 @@ namespace onnx { ...@@ -34,16 +34,65 @@ namespace onnx {
struct parse_slice : op_parser<parse_slice> struct parse_slice : op_parser<parse_slice>
{ {
std::vector<op_desc> operators() const { return {{"Slice"}}; } std::vector<op_desc> operators() const { return {{"Slice"}}; }
struct slice_desc
{
op::slice op;
std::vector<instruction_ref> op_args;
std::vector<int64_t> steps;
std::vector<int64_t> raxes;
void always_insert(instruction_ref arg) { op_args.insert(op_args.begin(), arg); }
std::vector<int64_t> insert(instruction_ref arg)
{
std::vector<int64_t> result;
migraphx::argument arg_value = arg->eval();
if(arg_value.empty())
{
op_args.insert(op_args.begin(), arg);
}
else
{
arg_value.visit([&](auto s) { result.assign(s.begin(), s.end()); });
}
return result;
}
};
instruction_ref parse(const op_desc& /*opd*/, instruction_ref parse(const op_desc& /*opd*/,
const onnx_parser& parser, const onnx_parser& parser,
onnx_parser::node_info info, const onnx_parser::node_info& info,
std::vector<instruction_ref> args) const const std::vector<instruction_ref>& args) const
{ {
op::slice op; auto sd = construct_slice_desc(parser, info, args);
auto ins = info.add_instruction(sd.op, sd.op_args);
if(not sd.raxes.empty())
{
ins = info.add_instruction(make_op("reverse", {{"axes", sd.raxes}}), ins);
}
// If any steps are other than default 1, add a "steps" op
if(std::any_of(sd.steps.begin(), sd.steps.end(), [](auto s) { return std::abs(s) != 1; }))
{
std::vector<int64_t> nsteps;
std::transform(sd.steps.begin(),
sd.steps.end(),
std::back_inserter(nsteps),
[](auto s) { return std::abs(s); });
return ins = info.add_instruction(
make_op("step", {{"axes", sd.op.axes}, {"steps", nsteps}}), ins);
}
else
return ins;
}
std::vector<int64_t> steps; slice_desc construct_slice_desc(const onnx_parser& parser,
onnx_parser::node_info info,
std::vector<instruction_ref> args) const
{
slice_desc sd;
// slice can have up to 5 inputs, we first check the 5th one // slice can have up to 5 inputs, we first check the 5th one
// to decide whether MIGRAPHX can handle this slice. // to decide whether MIGRAPHX can handle this slice.
...@@ -51,89 +100,73 @@ struct parse_slice : op_parser<parse_slice> ...@@ -51,89 +100,73 @@ struct parse_slice : op_parser<parse_slice>
{ {
migraphx::argument step_arg = args.back()->eval(); migraphx::argument step_arg = args.back()->eval();
check_arg_empty(step_arg, "PARSE_SLICE: cannot handle variable steps for slice"); check_arg_empty(step_arg, "PARSE_SLICE: cannot handle variable steps for slice");
step_arg.visit([&](auto s) { steps.assign(s.begin(), s.end()); }); step_arg.visit([&](auto s) { sd.steps.assign(s.begin(), s.end()); });
} }
if(args.size() >= 4) if(args.size() >= 4)
{ {
migraphx::argument axes_arg = args.at(3)->eval(); sd.op.axes = sd.insert(args.at(3));
check_arg_empty(axes_arg, "PARSE_SLICE: cannot handle variable axes for slice");
axes_arg.visit([&](auto s) { op.axes.assign(s.begin(), s.end()); });
} }
else if(contains(info.attributes, "axes")) else if(contains(info.attributes, "axes"))
{ {
literal s = parser.parse_value(info.attributes.at("axes")); literal s = parser.parse_value(info.attributes.at("axes"));
s.visit([&](auto v) { copy(v, std::back_inserter(op.axes)); }); s.visit([&](auto v) { copy(v, std::back_inserter(sd.op.axes)); });
} }
if(args.size() >= 3) if(args.size() >= 3)
{ {
migraphx::argument end_arg = args.at(2)->eval(); sd.op.ends = sd.insert(args.at(2));
check_arg_empty(end_arg, "PARSE_SLICE: cannot handle variable ends for slice");
end_arg.visit([&](auto s) { op.ends.assign(s.begin(), s.end()); });
} }
else if(contains(info.attributes, "ends")) else if(contains(info.attributes, "ends"))
{ {
literal s = parser.parse_value(info.attributes.at("ends")); literal s = parser.parse_value(info.attributes.at("ends"));
s.visit([&](auto v) { copy(v, std::back_inserter(op.ends)); }); s.visit([&](auto v) { copy(v, std::back_inserter(sd.op.ends)); });
} }
if(args.size() >= 2) if(args.size() >= 2)
{ {
migraphx::argument start_arg = args.at(1)->eval(); sd.op.starts = sd.insert(args.at(1));
check_arg_empty(start_arg, "PARSE_SLICE: cannot handle variable starts for slice");
start_arg.visit([&](auto s) { op.starts.assign(s.begin(), s.end()); });
} }
else if(contains(info.attributes, "starts")) else if(contains(info.attributes, "starts"))
{ {
literal s = parser.parse_value(info.attributes.at("starts")); literal s = parser.parse_value(info.attributes.at("starts"));
s.visit([&](auto v) { copy(v, std::back_inserter(op.starts)); }); s.visit([&](auto v) { copy(v, std::back_inserter(sd.op.starts)); });
} }
// data input argument
sd.always_insert(args.at(0));
// If axes arg is not given, the default is all of them. // If axes arg is not given, the default is all of them.
if(op.axes.empty()) if(sd.op.axes.empty() and sd.op_args.size() < 3)
{ {
std::vector<int64_t> axes(args[0]->get_shape().ndim()); std::vector<int64_t> axes(args[0]->get_shape().ndim());
std::iota(axes.begin(), axes.end(), int64_t{0}); std::iota(axes.begin(), axes.end(), int64_t{0});
op.axes = axes; sd.op.axes = axes;
} }
std::vector<int64_t> raxes; if(not sd.steps.empty())
{
if(sd.op.starts.empty() or sd.op.ends.empty())
MIGRAPHX_THROW("PARSE_SLICE: steps and variable starts and ends is not supported");
if(sd.op.axes.empty())
MIGRAPHX_THROW("PARSE_SLICE: steps and variable axes is not supported");
}
assert(steps.empty() or steps.size() == op.axes.size()); assert(sd.steps.empty() or sd.steps.size() == sd.op.axes.size());
assert(op.axes.size() == op.starts.size());
assert(op.axes.size() == op.ends.size());
// If any axes have negative step, prepare to add a "reverse" op // If any axes have negative step, prepare to add a "reverse" op
for(auto i : range(steps.size())) for(auto i : range(sd.steps.size()))
{ {
if(steps[i] >= 0) if(sd.steps[i] >= 0)
continue; continue;
op.starts[i] += 1; sd.op.starts[i] += 1;
if(op.starts[i] == 0) if(sd.op.starts[i] == 0)
op.starts[i] = INT_MAX; sd.op.starts[i] = INT_MAX;
op.ends[i] += 1; sd.op.ends[i] += 1;
raxes.push_back(op.axes[i]); sd.raxes.push_back(sd.op.axes[i]);
std::swap(op.starts[i], op.ends[i]); std::swap(sd.op.starts[i], sd.op.ends[i]);
}
auto ins = info.add_instruction(op, args[0]);
if(not raxes.empty())
{
ins = info.add_instruction(make_op("reverse", {{"axes", raxes}}), ins);
} }
// If any steps are other than default 1, add a "steps" op return sd;
if(std::any_of(steps.begin(), steps.end(), [](auto s) { return std::abs(s) != 1; }))
{
std::vector<int64_t> nsteps;
std::transform(steps.begin(), steps.end(), std::back_inserter(nsteps), [](auto s) {
return std::abs(s);
});
return ins = info.add_instruction(
make_op("step", {{"axes", op.axes}, {"steps", nsteps}}), ins);
}
else
return ins;
} }
}; };
......
...@@ -41,7 +41,7 @@ struct index ...@@ -41,7 +41,7 @@ struct index
__device__ index_int nglobal() const { return blockDim.x * gridDim.x; } // NOLINT __device__ index_int nglobal() const { return blockDim.x * gridDim.x; } // NOLINT
__device__ index_int nlocal() const { return blockDim.x; } // NOLINT __device__ index_int nlocal() const { return blockDim.x; } // NOLINT
template <class F> template <class F>
__device__ void global_stride(index_int n, F f) const __device__ void global_stride(index_int n, F f) const
...@@ -81,6 +81,12 @@ inline auto launch(hipStream_t stream, index_int global, index_int local) ...@@ -81,6 +81,12 @@ inline auto launch(hipStream_t stream, index_int global, index_int local)
dim3 nthreads(local); dim3 nthreads(local);
// cppcheck-suppress UseDeviceLaunch // cppcheck-suppress UseDeviceLaunch
hipLaunchKernelGGL((launcher<f_type>), nblocks, nthreads, 0, stream, f); hipLaunchKernelGGL((launcher<f_type>), nblocks, nthreads, 0, stream, f);
hipError_t kernel_launch_status = hipGetLastError();
if(kernel_launch_status != hipSuccess)
{
MIGRAPHX_THROW("MIGraphX device kernel failed to launch with error: " +
std::string(hipGetErrorString(kernel_launch_status)));
}
}; };
} }
......
...@@ -86,7 +86,7 @@ struct mlir_op ...@@ -86,7 +86,7 @@ struct mlir_op
size_t param_cnt = 0; size_t param_cnt = 0;
std::vector<std::string> names = mod->get_parameter_names(); std::vector<std::string> names = mod->get_parameter_names();
std::sort(names.begin(), names.end()); std::sort(names.begin(), names.end());
for(std::string param_name : names) for(const std::string& param_name : names)
{ {
ins_shapes[mod->get_parameter(param_name)] = inputs[param_cnt++]; ins_shapes[mod->get_parameter(param_name)] = inputs[param_cnt++];
} }
...@@ -210,32 +210,37 @@ struct find_mlir_op ...@@ -210,32 +210,37 @@ struct find_mlir_op
return false; return false;
} }
const std::initializer_list<std::string> any_type_ops = {"@literal", "@param", "@return"}; const std::initializer_list<std::string> any_type_ops = {"@literal", "@param", "@return"};
const std::initializer_list<std::string> no_bool_ops = {"convolution", const std::initializer_list<std::string> no_bool_ops = {
"quant_convolution", "convolution",
"dot", "quant_convolution",
"quant_dot", "dot",
"add", "quant_dot",
"clip", "add",
"relu", "clip",
"sub", "relu",
"mul", "sub",
"div", "mul",
"pow", "div",
"where", "pow",
"quantizelinear", "where",
"dequantizelinear", "quantizelinear",
"abs", "dequantizelinear",
"neg"}; "abs",
const std::initializer_list<std::string> fp_only_ops = {"ceil", "neg",
"erf", };
"exp", const std::initializer_list<std::string> fp_only_ops = {
"floor", "ceil",
"log", "erf",
"recip", "exp",
"rsqrt", "floor",
"sigmoid" "log",
"softmax", "recip",
"tanh"}; "rsqrt",
// There are bugs in MLIR right now for models using sigmoid so disable it for now
// "sigmoid",
"softmax",
"tanh",
};
bool is_float = contains({type_t::float_type, type_t::half_type}, result_type); bool is_float = contains({type_t::float_type, type_t::half_type}, result_type);
if(contains(any_type_ops, name)) if(contains(any_type_ops, name))
return true; return true;
......
...@@ -644,7 +644,7 @@ struct mlir_program ...@@ -644,7 +644,7 @@ struct mlir_program
void set_gpu_properties(const context& migraphx_ctx) void set_gpu_properties(const context& migraphx_ctx)
{ {
auto& device = migraphx_ctx.get_current_device(); const auto& device = migraphx_ctx.get_current_device();
target_arch = device.get_device_name(); target_arch = device.get_device_name();
num_cu = device.get_cu_count(); num_cu = device.get_cu_count();
} }
...@@ -669,10 +669,10 @@ struct mlir_program ...@@ -669,10 +669,10 @@ struct mlir_program
MIGRAPHX_THROW("Failed to compile mlir program"); MIGRAPHX_THROW("Failed to compile mlir program");
} }
void set_tuning(const value& v) void set_tuning(const value& v) MIGRAPHX_TIDY_CONST
{ {
auto* str = v.if_string(); const auto* str = v.if_string();
if(not str) if(str == nullptr)
MIGRAPHX_THROW("mlir tuning solutions must be strings"); MIGRAPHX_THROW("mlir tuning solutions must be strings");
if(not mlirRockTuningSetFromStr(mmodule.get(), make_mlir_string_ref(*str))) if(not mlirRockTuningSetFromStr(mmodule.get(), make_mlir_string_ref(*str)))
MIGRAPHX_THROW("Failed setting tuning key: " + *str); MIGRAPHX_THROW("Failed setting tuning key: " + *str);
...@@ -747,10 +747,10 @@ struct mlir_program ...@@ -747,10 +747,10 @@ struct mlir_program
{ {
std::vector<std::string> tokens = split_string(line, '\t'); std::vector<std::string> tokens = split_string(line, '\t');
std::string arch = tokens[0]; std::string arch = tokens[0];
std::string numCU = tokens[1]; std::string num_cu = tokens[1];
std::string prob = tokens[2]; std::string prob = tokens[2];
std::string perf = tokens[3]; std::string perf = tokens[3];
std::string key = arch.append("\t").append(numCU).append("\t").append(prob); std::string key = arch.append("\t").append(num_cu).append("\t").append(prob);
mlirRockTuningUpdateTable(tuning_table.get(), mlirRockTuningUpdateTable(tuning_table.get(),
make_mlir_string_ref(key), make_mlir_string_ref(key),
make_mlir_string_ref(perf), make_mlir_string_ref(perf),
......
...@@ -202,11 +202,16 @@ endif() ...@@ -202,11 +202,16 @@ endif()
function(test_header NAME HEADER) function(test_header NAME HEADER)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/header-main-include-${NAME}.cpp file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/header-main-include-${NAME}.cpp "
"#include <${HEADER}>\nint main() {}\n" #include <${HEADER}>
int main() {}\n"
) )
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/header-static-include-${NAME}.cpp file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/header-static-include-${NAME}.cpp "
"#include <${HEADER}>\n" #include <${HEADER}>
#if defined(min) || defined(max) || defined(near) || defined(far)
#error \"Do not include windows.h in header files\"
#endif
\n"
) )
add_test_executable(${NAME} add_test_executable(${NAME}
${CMAKE_CURRENT_BINARY_DIR}/header-main-include-${NAME}.cpp ${CMAKE_CURRENT_BINARY_DIR}/header-main-include-${NAME}.cpp
......
...@@ -145,15 +145,15 @@ TEST_CASE(zero_parameter) ...@@ -145,15 +145,15 @@ TEST_CASE(zero_parameter)
TEST_CASE(set_scalar_parameter) TEST_CASE(set_scalar_parameter)
{ {
auto p1 = migraphx::parse_onnx("add_bcast_test.onnx"); auto p1 = migraphx::parse_onnx("implicit_add_bcast_test.onnx");
migraphx::shape s1(migraphx_shape_float_type, {3, 4}); migraphx::shape s1(migraphx_shape_float_type, {3, 4, 1});
auto param_shapes = p1.get_parameter_shapes(); auto param_shapes = p1.get_parameter_shapes();
auto s1_orig = param_shapes["1"]; auto s1_orig = param_shapes["1"];
CHECK(bool{s1 == s1_orig}); CHECK(bool{s1 == s1_orig});
migraphx::onnx_options option; migraphx::onnx_options option;
option.set_input_parameter_shape("1", {}); option.set_input_parameter_shape("1", {});
auto p2 = migraphx::parse_onnx("add_bcast_test.onnx", option); auto p2 = migraphx::parse_onnx("implicit_add_bcast_test.onnx", option);
migraphx::shape s_scalar(migraphx_shape_float_type); migraphx::shape s_scalar(migraphx_shape_float_type);
auto param_shapes_1 = p2.get_parameter_shapes(); auto param_shapes_1 = p2.get_parameter_shapes();
auto s_scalar_after = param_shapes_1["1"]; auto s_scalar_after = param_shapes_1["1"];
......
...@@ -196,15 +196,47 @@ TEST_CASE(contiguous_pointwise) ...@@ -196,15 +196,47 @@ TEST_CASE(contiguous_pointwise)
migraphx::make_op("broadcast", {{"axis", 1}, {"out_lens", {2, 3, 8, 8}}}), y); migraphx::make_op("broadcast", {{"axis", 1}, {"out_lens", {2, 3, 8, 8}}}), y);
auto yc = mm->add_instruction(migraphx::make_op("contiguous"), yb); auto yc = mm->add_instruction(migraphx::make_op("contiguous"), yb);
auto add = add_pointwise(p, "main:pointwise0", {x, yc}, single_pointwise("add")); auto add = add_pointwise(p, "main:pointwise0", {x, yc}, single_pointwise("add"));
mm->add_instruction(pass_op{}, add); auto cadd = mm->add_instruction(migraphx::make_op("contiguous"), add);
mm->add_instruction(pass_op{}, cadd);
} }
auto count = std::distance(mm->begin(), mm->end()); auto count = std::distance(mm->begin(), mm->end());
run_pass(*mm); run_pass(*mm);
EXPECT(std::distance(mm->begin(), mm->end()) == (count - 1)); EXPECT(std::distance(mm->begin(), mm->end()) == (count - 2));
EXPECT(std::none_of( EXPECT(std::none_of(
mm->begin(), mm->end(), [](auto&& ins) { return ins.name() == "contiguous"; })); mm->begin(), mm->end(), [](auto&& ins) { return ins.name() == "contiguous"; }));
} }
TEST_CASE(contiguous_nhwc_pointwise)
{
auto s =
migraphx::shape::from_permutation(migraphx::shape::float_type, {2, 3, 8, 8}, {0, 2, 3, 1});
migraphx::program p1;
{
auto* mm = p1.get_main_module();
auto x = mm->add_parameter("x", s);
auto y = mm->add_parameter("y", migraphx::shape{migraphx::shape::float_type, {3}});
auto yb = mm->add_instruction(
migraphx::make_op("broadcast", {{"axis", 1}, {"out_lens", {2, 3, 8, 8}}}), y);
auto yc = mm->add_instruction(migraphx::make_op("contiguous"), yb);
auto add = add_pointwise(p1, "main:pointwise0", {x, yc}, single_pointwise("add"));
auto cadd = mm->add_instruction(migraphx::make_op("contiguous"), add);
mm->add_instruction(pass_op{}, cadd);
}
run_pass(*p1.get_main_module());
migraphx::program p2;
{
auto* mm = p2.get_main_module();
auto x = mm->add_parameter("x", s);
auto y = mm->add_parameter("y", migraphx::shape{migraphx::shape::float_type, {3}});
auto yb = mm->add_instruction(
migraphx::make_op("broadcast", {{"axis", 1}, {"out_lens", {2, 3, 8, 8}}}), y);
auto add = add_pointwise(p2, "main:pointwise0", {x, yb}, single_pointwise("add"));
auto cadd = mm->add_instruction(migraphx::make_op("contiguous"), add);
mm->add_instruction(pass_op{}, cadd);
}
EXPECT(p1 == p2);
}
TEST_CASE(slice_contiguous) TEST_CASE(slice_contiguous)
{ {
migraphx::module m; migraphx::module m;
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include <migraphx/pass_manager.hpp> #include <migraphx/pass_manager.hpp>
#include <migraphx/instruction.hpp> #include <migraphx/instruction.hpp>
#include <basic_ops.hpp> #include <basic_ops.hpp>
#include <migraphx/operators.hpp> #include <migraphx/op/common.hpp>
#include <migraphx/make_op.hpp> #include <migraphx/make_op.hpp>
#include <test.hpp> #include <test.hpp>
...@@ -58,9 +58,8 @@ create_conv(migraphx::instruction_ref& l_img, ...@@ -58,9 +58,8 @@ create_conv(migraphx::instruction_ref& l_img,
migraphx::shape s_weights{migraphx::shape::int32_type, {4, channels, 3, 3}}; migraphx::shape s_weights{migraphx::shape::int32_type, {4, channels, 3, 3}};
std::vector<int32_t> weights(4 * channels * 3 * 3); std::vector<int32_t> weights(4 * channels * 3 * 3);
auto l_weights = m.add_literal(migraphx::literal{s_weights, weights}); auto l_weights = m.add_literal(migraphx::literal{s_weights, weights});
migraphx::op::convolution op; return m.add_instruction(
op.padding_mode = padding_mode; migraphx::make_op("convolution", {{"padding_mode", padding_mode}}), l_img, l_weights);
return m.add_instruction(op, l_img, l_weights);
} }
TEST_CASE(rewrite_pad) TEST_CASE(rewrite_pad)
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <migraphx/gpu/fuse_mlir.hpp> #include <migraphx/gpu/fuse_mlir.hpp>
#include <migraphx/operators.hpp> #include <migraphx/make_op.hpp>
#include <migraphx/instruction.hpp> #include <migraphx/instruction.hpp>
#include <migraphx/quantization.hpp> #include <migraphx/quantization.hpp>
#include <migraphx/generate.hpp> #include <migraphx/generate.hpp>
...@@ -90,7 +90,7 @@ TEST_CASE(int8_quantization) ...@@ -90,7 +90,7 @@ TEST_CASE(int8_quantization)
migraphx::shape sc{migraphx::shape::float_type, {5, 8}}; migraphx::shape sc{migraphx::shape::float_type, {5, 8}};
auto pa = mm->add_parameter("a", sa); auto pa = mm->add_parameter("a", sa);
auto pb = mm->add_parameter("b", sb); auto pb = mm->add_parameter("b", sb);
mm->add_instruction(migraphx::op::dot{}, pa, pb); mm->add_instruction(migraphx::make_op("dot"), pa, pb);
return p; return p;
}; };
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include <atomic>
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <cstdio> #include <cstdio>
...@@ -342,11 +343,19 @@ inline std::ostream& operator<<(std::ostream& os, const color& c) ...@@ -342,11 +343,19 @@ inline std::ostream& operator<<(std::ostream& os, const color& c)
return os; return os;
} }
inline std::atomic<int>& failures()
{
// NOLINTNEXTLINE
static std::atomic<int> f = 0;
return f;
}
template <class T, class F> template <class T, class F>
void failed(T x, const char* msg, const char* func, const char* file, int line, F f) void failed(T x, const char* msg, const char* func, const char* file, int line, F f)
{ {
if(not bool(x.value())) if(not bool(x.value()))
{ {
failures()++;
std::cout << func << std::endl; std::cout << func << std::endl;
std::cout << file << ":" << line << ":" << std::endl; std::cout << file << ":" << line << ":" << std::endl;
std::cout << color::bold << color::fg_red << " FAILED: " << color::reset << msg << " " std::cout << color::bold << color::fg_red << " FAILED: " << color::reset << msg << " "
...@@ -586,13 +595,21 @@ struct driver ...@@ -586,13 +595,21 @@ struct driver
{ {
try try
{ {
failures() = 0;
f(); f();
} }
// cppcheck-suppress EmptyCatchStatement
catch(const failure_error&) catch(const failure_error&)
{ {
msg = "Test failure";
} }
} }
if(msg.empty() and failures() != 0)
{
if(failures() == 1)
msg = "Test failure";
else
msg = std::to_string(failures()) + " test failures";
}
if(msg.empty()) if(msg.empty())
{ {
out() << color::fg_green << "[ COMPLETE ] " << color::reset << color::bold << name out() << color::fg_green << "[ COMPLETE ] " << color::reset << color::bold << name
...@@ -683,10 +700,10 @@ inline void run(int argc, const char* argv[]) ...@@ -683,10 +700,10 @@ inline void run(int argc, const char* argv[])
#define TEST_CAPTURE(...) test::capture{}->*__VA_ARGS__ #define TEST_CAPTURE(...) test::capture{}->*__VA_ARGS__
// NOLINTNEXTLINE // NOLINTNEXTLINE
#define CHECK(...) \ #define CHECK(...) \
test::failed( \ test::failed( \
test::capture{}->*__VA_ARGS__, #__VA_ARGS__, __PRETTY_FUNCTION__, __FILE__, __LINE__, [] { \ TEST_CAPTURE(__VA_ARGS__), #__VA_ARGS__, __PRETTY_FUNCTION__, __FILE__, __LINE__, [] {})
})
// NOLINTNEXTLINE // NOLINTNEXTLINE
#define EXPECT(...) \ #define EXPECT(...) \
test::failed(TEST_CAPTURE(__VA_ARGS__), \ test::failed(TEST_CAPTURE(__VA_ARGS__), \
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include <migraphx/pass_manager.hpp> #include <migraphx/pass_manager.hpp>
#include <migraphx/instruction.hpp> #include <migraphx/instruction.hpp>
#include <basic_ops.hpp> #include <basic_ops.hpp>
#include <migraphx/operators.hpp>
#include <migraphx/make_op.hpp> #include <migraphx/make_op.hpp>
#include <test.hpp> #include <test.hpp>
......
...@@ -26,8 +26,8 @@ ...@@ -26,8 +26,8 @@
#include <migraphx/insert_pad.hpp> #include <migraphx/insert_pad.hpp>
#include <migraphx/pass_manager.hpp> #include <migraphx/pass_manager.hpp>
#include <migraphx/instruction.hpp> #include <migraphx/instruction.hpp>
#include <migraphx/op/common.hpp>
#include <basic_ops.hpp> #include <basic_ops.hpp>
#include <migraphx/operators.hpp>
#include <migraphx/make_op.hpp> #include <migraphx/make_op.hpp>
#include <test.hpp> #include <test.hpp>
...@@ -58,10 +58,11 @@ create_conv(migraphx::instruction_ref& l_img, ...@@ -58,10 +58,11 @@ create_conv(migraphx::instruction_ref& l_img,
migraphx::shape s_weights{migraphx::shape::int32_type, {4, channels, 3, 3}}; migraphx::shape s_weights{migraphx::shape::int32_type, {4, channels, 3, 3}};
std::vector<int32_t> weights(4 * channels * 3 * 3); std::vector<int32_t> weights(4 * channels * 3 * 3);
auto l_weights = m.add_literal(migraphx::literal{s_weights, weights}); auto l_weights = m.add_literal(migraphx::literal{s_weights, weights});
migraphx::op::convolution op; return m.add_instruction(
op.padding_mode = padding_mode; migraphx::make_op("convolution",
op.padding = {0, 0, 1, 1}; {{"padding_mode", padding_mode}, {"padding", {0, 0, 1, 1}}}),
return m.add_instruction(op, l_img, l_weights); l_img,
l_weights);
} }
TEST_CASE(rewrite_pad) TEST_CASE(rewrite_pad)
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include <migraphx/layout_nhwc.hpp> #include <migraphx/layout_nhwc.hpp>
#include <migraphx/dead_code_elimination.hpp> #include <migraphx/dead_code_elimination.hpp>
#include <migraphx/pass_manager.hpp> #include <migraphx/pass_manager.hpp>
#include <migraphx/operators.hpp>
#include <migraphx/generate.hpp> #include <migraphx/generate.hpp>
#include <migraphx/ranges.hpp> #include <migraphx/ranges.hpp>
#include <migraphx/instruction.hpp> #include <migraphx/instruction.hpp>
......
e5bb7aba502f5a8783de945258d226c092c14386 a476dbf430ac8315550474a78d47bf182f202d7c
...@@ -6414,6 +6414,30 @@ def slice_test(): ...@@ -6414,6 +6414,30 @@ def slice_test():
return ([node], [x], [y]) return ([node], [x], [y])
@onnx_test()
def slice_constant_test():
y = helper.make_tensor_value_info('1', TensorProto.FLOAT, [1, 2])
x_tensor = helper.make_tensor(name='x_tensor',
data_type=TensorProto.FLOAT,
dims=[3, 2],
vals=[0, 1, 2, 3, 4, 5])
x = onnx.helper.make_node('Constant',
inputs=[],
outputs=['x'],
value=x_tensor)
node = onnx.helper.make_node('Slice',
inputs=['x'],
axes=[0, 1],
starts=[1, 0],
ends=[2, 2],
outputs=['1'])
return ([x, node], [], [y])
@onnx_test() @onnx_test()
def slice_dyn_test(): def slice_dyn_test():
x = helper.make_tensor_value_info('0', TensorProto.FLOAT, [None, None, 2]) x = helper.make_tensor_value_info('0', TensorProto.FLOAT, [None, None, 2])
...@@ -6746,6 +6770,92 @@ def slice_max_end_test(): ...@@ -6746,6 +6770,92 @@ def slice_max_end_test():
return ([node], [x], [y]) return ([node], [x], [y])
@onnx_test()
def slice_var_input_static0():
data = helper.make_tensor_value_info('data', TensorProto.FLOAT, [3, 2])
starts = helper.make_tensor_value_info('starts', TensorProto.INT32, [2])
ends = helper.make_tensor_value_info('ends', TensorProto.INT32, [2])
output = helper.make_tensor_value_info('output', TensorProto.FLOAT, [1, 2])
node = onnx.helper.make_node('Slice',
inputs=['data', 'starts', 'ends'],
axes=[0, 1],
outputs=['output'])
return ([node], [data, starts, ends], [output])
@onnx_test()
def slice_var_input_static1():
data = helper.make_tensor_value_info('data', TensorProto.FLOAT, [3, 2])
starts = helper.make_tensor_value_info('starts', TensorProto.INT64, [2])
ends = helper.make_tensor_value_info('ends', TensorProto.INT64, [2])
axes = helper.make_tensor_value_info('axes', TensorProto.INT64, [2])
output = helper.make_tensor_value_info('output', TensorProto.FLOAT, [1, 2])
node = onnx.helper.make_node('Slice',
inputs=['data', 'starts', 'ends', 'axes'],
outputs=['output'])
return ([node], [data, starts, ends, axes], [output])
@onnx_test()
def slice_var_input_dyn0():
data = helper.make_tensor_value_info('data', TensorProto.FLOAT, [None, 2])
starts = helper.make_tensor_value_info('starts', TensorProto.INT32, [2])
ends = helper.make_tensor_value_info('ends', TensorProto.INT32, [2])
output = helper.make_tensor_value_info('output', TensorProto.FLOAT, [1, 2])
node = onnx.helper.make_node('Slice',
inputs=['data', 'starts', 'ends'],
axes=[0, 1],
outputs=['output'])
return ([node], [data, starts, ends], [output])
@onnx_test()
def slice_var_input_dyn1():
data = helper.make_tensor_value_info('data', TensorProto.FLOAT, [None, 2])
starts = helper.make_tensor_value_info('starts', TensorProto.INT32, [2])
ends = helper.make_tensor_value_info('ends', TensorProto.INT32, [2])
axes = helper.make_tensor_value_info('axes', TensorProto.INT32, [2])
output = helper.make_tensor_value_info('output', TensorProto.FLOAT, [1, 2])
node = onnx.helper.make_node('Slice',
inputs=['data', 'starts', 'ends', 'axes'],
outputs=['output'])
return ([node], [data, starts, ends, axes], [output])
@onnx_test()
def slice_var_input_steps_error():
step = np.array([2, 1])
step_tensor = helper.make_tensor(name="step",
data_type=TensorProto.INT32,
dims=step.shape,
vals=step.astype(int))
arg_step = helper.make_node("Constant",
inputs=[],
outputs=['arg_step'],
value=step_tensor)
data = helper.make_tensor_value_info('data', TensorProto.FLOAT, [3, 2])
starts = helper.make_tensor_value_info('starts', TensorProto.FLOAT, [2])
ends = helper.make_tensor_value_info('ends', TensorProto.FLOAT, [2])
axes = helper.make_tensor_value_info('axes', TensorProto.FLOAT, [2])
output = helper.make_tensor_value_info('output', TensorProto.FLOAT, [1, 2])
node = onnx.helper.make_node(
'Slice',
inputs=['data', 'starts', 'ends', 'axes', 'arg_step'],
outputs=['output'])
return ([arg_step, node], [data, starts, ends, axes], [output])
@onnx_test() @onnx_test()
def softmax_test(): def softmax_test():
x = helper.make_tensor_value_info('0', TensorProto.FLOAT, [1, 3]) x = helper.make_tensor_value_info('0', TensorProto.FLOAT, [1, 3])
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <migraphx/literal.hpp> #include <migraphx/literal.hpp>
#include <migraphx/operators.hpp> #include <migraphx/op/common.hpp>
#include <migraphx/program.hpp> #include <migraphx/program.hpp>
#include <migraphx/instruction.hpp> #include <migraphx/instruction.hpp>
#include <migraphx/pass_manager.hpp> #include <migraphx/pass_manager.hpp>
......
...@@ -6294,6 +6294,19 @@ TEST_CASE(slice_test) ...@@ -6294,6 +6294,19 @@ TEST_CASE(slice_test)
EXPECT(p == prog); EXPECT(p == prog);
} }
TEST_CASE(slice_constant_test)
{
migraphx::program p;
auto* mm = p.get_main_module();
auto l0 = mm->add_literal(migraphx::literal{
migraphx::shape{migraphx::shape::float_type, {3, 2}}, {0, 1, 2, 3, 4, 5}});
mm->add_instruction(
migraphx::make_op("slice", {{"axes", {0, 1}}, {"starts", {1, 0}}, {"ends", {2, 2}}}), l0);
auto prog = optimize_onnx("slice_constant_test.onnx");
EXPECT(p == prog);
}
TEST_CASE(slice_dyn_test) TEST_CASE(slice_dyn_test)
{ {
migraphx::program p; migraphx::program p;
...@@ -6426,6 +6439,74 @@ TEST_CASE(slice_max_end_test) ...@@ -6426,6 +6439,74 @@ TEST_CASE(slice_max_end_test)
EXPECT(p == prog); EXPECT(p == prog);
} }
TEST_CASE(slice_var_input_static0)
{
migraphx::program p;
auto* mm = p.get_main_module();
auto data = mm->add_parameter("data", migraphx::shape{migraphx::shape::float_type, {3, 2}});
auto starts = mm->add_parameter("starts", migraphx::shape{migraphx::shape::int32_type, {2}});
auto ends = mm->add_parameter("ends", migraphx::shape{migraphx::shape::int32_type, {2}});
mm->add_instruction(migraphx::make_op("slice", {{"axes", {0, 1}}}), data, starts, ends);
auto prog = optimize_onnx("slice_var_input_static0.onnx");
EXPECT(p == prog);
}
TEST_CASE(slice_var_input_static1)
{
migraphx::program p;
auto* mm = p.get_main_module();
auto data = mm->add_parameter("data", migraphx::shape{migraphx::shape::float_type, {3, 2}});
auto starts = mm->add_parameter("starts", migraphx::shape{migraphx::shape::int64_type, {2}});
auto ends = mm->add_parameter("ends", migraphx::shape{migraphx::shape::int64_type, {2}});
auto axes = mm->add_parameter("axes", migraphx::shape{migraphx::shape::int64_type, {2}});
mm->add_instruction(migraphx::make_op("slice"), data, starts, ends, axes);
auto prog = optimize_onnx("slice_var_input_static1.onnx");
EXPECT(p == prog);
}
TEST_CASE(slice_var_input_dyn0)
{
migraphx::program p;
auto* mm = p.get_main_module();
auto data =
mm->add_parameter("data", migraphx::shape{migraphx::shape::float_type, {{3, 8}, {2, 2}}});
auto starts = mm->add_parameter("starts", migraphx::shape{migraphx::shape::int32_type, {2}});
auto ends = mm->add_parameter("ends", migraphx::shape{migraphx::shape::int32_type, {2}});
auto ret =
mm->add_instruction(migraphx::make_op("slice", {{"axes", {0, 1}}}), data, starts, ends);
mm->add_return({ret});
migraphx::onnx_options options;
options.default_dyn_dim_value = {3, 8};
auto prog = parse_onnx("slice_var_input_dyn0.onnx", options);
EXPECT(p == prog);
}
TEST_CASE(slice_var_input_dyn1)
{
migraphx::program p;
auto* mm = p.get_main_module();
auto data =
mm->add_parameter("data", migraphx::shape{migraphx::shape::float_type, {{3, 8}, {2, 2}}});
auto starts = mm->add_parameter("starts", migraphx::shape{migraphx::shape::int32_type, {2}});
auto ends = mm->add_parameter("ends", migraphx::shape{migraphx::shape::int32_type, {2}});
auto axes = mm->add_parameter("axes", migraphx::shape{migraphx::shape::int32_type, {2}});
auto ret = mm->add_instruction(migraphx::make_op("slice"), data, starts, ends, axes);
mm->add_return({ret});
migraphx::onnx_options options;
options.default_dyn_dim_value = {3, 8};
auto prog = parse_onnx("slice_var_input_dyn1.onnx", options);
EXPECT(p == prog);
}
TEST_CASE(slice_var_input_steps_error)
{
EXPECT(test::throws([&] { migraphx::parse_onnx("slice_var_input_steps_error.onnx"); }));
}
TEST_CASE(softmax_test) TEST_CASE(softmax_test)
{ {
migraphx::program p; migraphx::program p;
......
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