Commit a0ea12f6 authored by Khalique's avatar Khalique
Browse files

add imagescaler op

parent 945e89e0
......@@ -256,7 +256,6 @@ struct operation
shape compute_shape(const std::vector<shape>& input) const override
{
return private_detail_te_value.compute_shape(input);
}
......
......@@ -306,10 +306,10 @@ struct contiguous
check_shapes{inputs, *this}.has(1);
auto lens = inputs.at(0).lens();
auto t = inputs.at(0).type();
if(lens.size() < 2)
{
MIGRAPH_THROW("Number of dimensions should exceed 1");
}
// if(lens.size() < 2)
// {
// MIGRAPH_THROW("Number of dimensions should exceed 1");
// }
return {t, lens};
}
};
......@@ -710,6 +710,27 @@ struct broadcast
}
};
struct scalar
{
shape scalar_bcast;
std::string name() const { return "scalar"; }
shape compute_shape(std::vector<shape> inputs) const
{
assert(check_shapes{inputs}.has(1).only_dims(1).size() == 1);
auto t = inputs.at(0).type();
auto input = inputs.at(0);
std::vector<std::size_t> strides(scalar_bcast.lens().size(), 0);
return {t, scalar_bcast.lens(), strides};
}
argument compute(context&, shape output_shape, std::vector<argument> args) const
{
return {std::move(output_shape), std::move(args.at(0).data)};
}
};
struct binary
{
shape compute_shape(std::vector<shape> inputs) const
......
......@@ -92,6 +92,8 @@ struct shape
/// Returns true if the shape is in its standard format. That is, the shape is both packed and
/// not transposed.
bool standard() const;
/// Returns true if all strides are equal to 0 (scalar tensor)
bool scalar() const;
friend bool operator==(const shape& x, const shape& y);
friend bool operator!=(const shape& x, const shape& y);
......
......@@ -56,6 +56,7 @@ struct onnx_parser
add_generic_op("Sub", op::sub{});
add_generic_op("Sum", op::add{});
// add_mem_op("ImageScaler", &onnx_parser::parse_imagescaler);
add_mem_op("LeakyRelu", &onnx_parser::parse_leaky_relu);
add_mem_op("Constant", &onnx_parser::parse_constant);
add_mem_op("Conv", &onnx_parser::parse_conv);
......@@ -265,7 +266,7 @@ struct onnx_parser
attribute_map attributes,
std::vector<instruction_ref> args)
{
float alpha = 0.01;
float alpha = 0.01; // default alpha val for leaky relu
if(contains(attributes, "alpha"))
{
alpha = parse_value(attributes.at("alpha")).at<float>();
......@@ -274,6 +275,11 @@ struct onnx_parser
return prog.add_instruction(op, args.front());
}
// instruction_ref parse_imagescaler(const std::string&, attribute_map attributes, std::vector<instruction_ref> args)
// {
// }
void parse_from(std::istream& is)
{
onnx::ModelProto model;
......
......@@ -195,6 +195,7 @@ void memory_coloring_impl::register_operand_alias()
operand_alias["broadcast"] = 0;
operand_alias["reshape"] = 0;
operand_alias["pass"] = 0;
operand_alias["scalar"] = 0;
}
void memory_coloring_impl::rewrite()
......
......@@ -29,8 +29,8 @@ struct shape_impl
: m_type(t), m_lens(std::move(l)), m_strides(std::move(s))
{
assert(m_lens.size() == m_strides.size());
assert(std::any_of(m_strides.begin(), m_strides.end(), [](auto x) { return x > 0; }) and
"At least one stride must be non-zero");
// assert(std::any_of(m_strides.begin(), m_strides.end(), [](auto x) { return x > 0; }) and
// "At least one stride must be non-zero");
m_standard = this->elements() == this->element_space() and
std::is_sorted(m_strides.rbegin(), m_strides.rend());
}
......@@ -153,6 +153,15 @@ bool shape::broadcasted() const
std::multiplies<std::size_t>()) == 0;
}
bool shape::scalar() const
{
assert(this->lens().size() == this->strides().size());
// if any stride > 0, then accumulate will return false
return std::accumulate(this->strides().begin(),
this->strides().end(),
std::size_t(0)) == 0;
}
bool shape::standard() const { return impl->m_standard; }
std::size_t shape::element_space() const { return impl->element_space(); }
......
......@@ -581,6 +581,7 @@ struct cpu_apply
apply_map["add"] = simple_op<cpu_binary<add_op>>();
apply_map["sub"] = simple_op<cpu_binary<sub_op>>();
apply_map["mul"] = simple_op<cpu_binary<mul_op>>();
// apply_map["scalar"] = simple_op<cpu_binary<mul_op>>();
apply_map["div"] = simple_op<cpu_binary<div_op>>();
apply_map["softmax"] = simple_op<softmax2d>();
......
# This is the CMakeCache file.
# For build in directory: /home/khalique/MIGraph/src/targets/gpu
# It was generated by CMake: /usr/bin/cmake
# You can edit this file to change values found and used by cmake.
# If you do not want to change any of the values, simply exit the editor.
# If you do want to change a value, simply edit, save, and exit the editor.
# The syntax for the file is as follows:
# KEY:TYPE=VALUE
# KEY is the name of a variable in the cache.
# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!.
# VALUE is the current value for the KEY.
########################
# EXTERNAL cache entries
########################
########################
# INTERNAL cache entries
########################
//This is the directory where this CMakeCache.txt was created
CMAKE_CACHEFILE_DIR:INTERNAL=/home/khalique/MIGraph/src/targets/gpu
//Major version of cmake used to create the current loaded cache
CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3
//Minor version of cmake used to create the current loaded cache
CMAKE_CACHE_MINOR_VERSION:INTERNAL=5
//Patch version of cmake used to create the current loaded cache
CMAKE_CACHE_PATCH_VERSION:INTERNAL=1
//Path to CMake executable.
CMAKE_COMMAND:INTERNAL=/usr/bin/cmake
//Path to cpack program executable.
CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack
//Path to ctest program executable.
CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest
//Path to CMake installation.
CMAKE_ROOT:INTERNAL=/usr/share/cmake-3.5
# This file is generated by cmake for dependency checking of the CMakeCache.txt file
......@@ -10,10 +10,11 @@ if(NOT TARGET MIOpen)
message(SEND_ERROR "Cant find miopen")
endif()
add_library(migraph_device
add_library(migraph_device
device/add.cpp
device/add_relu.cpp
device/contiguous.cpp
device/mul.cpp
)
rocm_clang_tidy_check(migraph_device)
target_link_libraries(migraph_device migraph hip::device)
......@@ -34,6 +35,7 @@ add_library(migraph_gpu
relu.cpp
leaky_relu.cpp
add.cpp
mul.cpp
batchnorm.cpp
write_literals.cpp
rocblas.cpp
......
......@@ -325,7 +325,7 @@ inline auto nary(const argument& result, const argument& arg1, const argument& a
{
return [=](auto f) {
// TODO: Check result and arg1 shape is the same
if(arg1.get_shape().standard() and arg2.get_shape().broadcasted())
if(arg1.get_shape().standard() and arg2.get_shape().broadcasted() and not arg2.get_shape().scalar())
{
auto not_zero = [](auto x) { return x != 0; };
const auto& strides = arg2.get_shape().strides();
......
#include <migraph/gpu/device/mul.hpp>
#include <migraph/gpu/device/nary.hpp>
namespace migraph {
namespace gpu {
namespace device {
void mul(const argument& result, const argument& arg1, const argument& arg2)
{
nary(result, arg1, arg2)([](auto x, auto y) { return x * y; });
}
} // namespace device
} // namespace gpu
} // namespace migraph
#ifndef MIGRAPH_GUARD_RTGLIB_DEVICE_MUL_HPP
#define MIGRAPH_GUARD_RTGLIB_DEVICE_MUL_HPP
#include <migraph/argument.hpp>
namespace migraph {
namespace gpu {
namespace device {
void mul(const argument& result, const argument& arg1, const argument& arg2);
} // namespace device
} // namespace gpu
} // namespace migraph
#endif
#ifndef MIGRAPH_GUARD_RTGLIB_MUL_HPP
#define MIGRAPH_GUARD_RTGLIB_MUL_HPP
#include <migraph/gpu/lowering.hpp>
#include <migraph/manage_ptr.hpp>
#include <migraph/instruction.hpp>
#include <migraph/operators.hpp>
#include <migraph/generate.hpp>
#include <migraph/shape_for_each.hpp>
#include <migraph/gpu/miopen.hpp>
#include <migraph/gpu/hip.hpp>
#include <migraph/dfor.hpp>
#include <migraph/gpu/device/contiguous.hpp>
#include <migraph/gpu/device/mul.hpp>
#include <migraph/iterator_for.hpp>
#include <migraph/gpu/rocblas.hpp>
#include <migraph/gpu/context.hpp>
#include <utility>
namespace migraph {
namespace gpu {
struct hip_mul
{
std::string name() const { return "gpu::mul"; }
shape compute_shape(const std::vector<shape>& inputs) const;
argument compute(context&, const shape&, const std::vector<argument>& args) const;
};
} // namespace gpu
} // namespace migraph
#endif
......@@ -19,6 +19,7 @@
#include <migraph/gpu/leaky_relu.hpp>
#include <migraph/gpu/softmax.hpp>
#include <migraph/gpu/add.hpp>
#include <migraph/gpu/mul.hpp>
#include <migraph/gpu/batchnorm.hpp>
#include <migraph/gpu/pooling.hpp>
#include <migraph/gpu/gemm.hpp>
......@@ -64,6 +65,10 @@ struct miopen_apply
{
check_shape(s, apply_add(it));
}
else if(it->name() == "mul")
{
check_shape(s, apply_mul(it));
}
else if(it->name() == "gemm")
{
check_shape(s, apply_gemm(it));
......@@ -158,6 +163,13 @@ struct miopen_apply
ins, hip_add{}, ins->inputs().at(0), ins->inputs().at(1), output);
}
instruction_ref apply_mul(instruction_ref ins)
{
auto output = insert_allocation(ins, ins->get_shape());
return prog->replace_instruction(
ins, hip_mul{}, ins->inputs().at(0), ins->inputs().at(1), output);
}
instruction_ref apply_gemm(instruction_ref ins)
{
auto&& op = any_cast<op::gemm>(ins->get_operator());
......
#include <migraph/gpu/mul.hpp>
#include <migraph/operators.hpp>
#include <migraph/manage_ptr.hpp>
#include <migraph/gpu/miopen.hpp>
#include <utility>
namespace migraph {
namespace gpu {
shape hip_mul::compute_shape(const std::vector<shape>& inputs) const
{
// check_shapes{inputs, *this}.has(3).standard();
check_shapes{inputs, *this}.has(3);
return inputs.at(0);
}
argument hip_mul::compute(context&, const shape&, const std::vector<argument>& args) const
{
device::mul(args[2], args[0], args[1]);
return args[2];
}
} // namespace gpu
} // namespace migraph
......@@ -489,6 +489,43 @@ void leaky_relu_test()
EXPECT(migraph::verify_range(results_vector, gold));
}
void imagescaler_test()
{
migraph::program p;
migraph::shape s{migraph::shape::float_type, {1, 3, 2, 2}};
auto img = p.add_literal(migraph::literal{s, {
0.2, 0.3,
0.5, 0.4,
0.7, 0.8,
0.1, 0.9,
0.15, 0.25,
0.35, 0.45
}});
auto scale_val = p.add_literal(2.f);
auto scaled_tensor = p.add_instruction(migraph::op::scalar{s}, scale_val);
auto img_scaled = p.add_instruction(migraph::op::mul{}, img, scaled_tensor);
auto bias_vals = p.add_literal(migraph::literal{migraph::shape{migraph::shape::float_type, {3}}, {0.01, 0.02, 0.03}});
auto bias_bcast = p.add_instruction(migraph::op::broadcast{1, s}, bias_vals);
p.add_instruction(migraph::op::add{}, img_scaled, bias_bcast);
p.compile(migraph::cpu::cpu_target{});
auto result = p.eval({});
std::vector<float> results_vector(12);
result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); });
std::vector<float> gold = {
0.41, 0.61,
1.01, 0.81,
1.42, 1.62,
0.22, 1.82,
0.33, 0.53,
0.73, 0.93
};
EXPECT(migraph::verify_range(results_vector, gold));
}
void reshape_test()
{
migraph::shape a_shape{migraph::shape::float_type, {24, 1, 1, 1}};
......@@ -943,6 +980,7 @@ int main()
add_test();
broadcast_test();
add_broadcast_test();
imagescaler_test();
sub_test();
mul_test();
div_test();
......
......@@ -174,6 +174,33 @@ struct test_add
}
};
struct test_mul
{
migraph::program create_program() const
{
migraph::program p;
migraph::shape s{migraph::shape::float_type, {3}};
auto x = p.add_parameter("x", s);
auto y = p.add_parameter("y", s);
p.add_instruction(migraph::op::mul{}, x, y);
return p;
}
};
struct test_scale
{
migraph::program create_program() const
{
migraph::program p;
migraph::shape s{migraph::shape::float_type, {3}};
auto x = p.add_parameter("x", s);
auto y = p.add_parameter("y", migraph::shape::float_type);
auto scale = p.add_instruction(migraph::op::scalar{s}, y);
p.add_instruction(migraph::op::mul{}, x, scale);
return p;
}
};
struct test_triadd
{
migraph::program create_program() const
......@@ -616,6 +643,8 @@ struct test_conv_bn_relu_pooling2
int main()
{
verify_program<test_add>();
verify_program<test_mul>();
verify_program<test_scale>();
verify_program<test_triadd>();
verify_program<test_triadd2>();
verify_program<test_add_broadcast>();
......
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