Commit 9154cbbe authored by Brian Pickrell's avatar Brian Pickrell
Browse files

initial creation of Resize op. and test file. Non functional

parent 5756ebd4
#ifndef MIGRAPHX_GUARD_OPERATORS_RESIZE_HPP
#define MIGRAPHX_GUARD_OPERATORS_RESIZE_HPP
#include <array>
// #include <migraphx/op/common.hpp>
#include <migraphx/check_shapes.hpp>
#include <migraphx/stringutils.hpp>
#include <migraphx/streamutils.hpp>
#include <migraphx/literal.hpp>
#include <migraphx/shape_for_each.hpp>
#include <migraphx/config.hpp>
#include <cmath>
#include <utility>
namespace migraphx {
inline namespace MIGRAPHX_INLINE_NS {
namespace op {
struct resize
{
// TODO: indicators. The real scales and sizes are inputs, not attributes.
std::vector<float> scales;
std::vector<int64_t> sizes;
int mode = 0; // 1: nereast 2: bilinear/linear 3: cubic
std::string coordinate_transformation_mode;
std::string name() const { return "resize"; }
template <class Self, class F>
static auto reflect(Self& self, F f)
{
return pack(f(self.scales, "scales"),
f(self.sizes, "sizes"),
f(self.mode,"mode"),
f(self.coordinate_transformation_mode,"coordinate_transformation_mode"));
}
shape compute_shape(std::vector<shape> inputs) const
{
// check_shapes{{inputs[0]}, *this, true}.has(2);
check_shapes{inputs, *this, true}.has(2);
// I get to DECIDE what the inputs are. inputs are X, sizes or scale, ROI not supported
if((sizes.empty()) == (scales.empty()))
MIGRAPHX_THROW("RESIZE: One and only one of max_size or scales attributes must be given");
if(inputs.back().ndim() != 1)
MIGRAPHX_THROW("RESIZE: size/scale input must have rank 1");
if(inputs.back().dynamic() and not inputs.back().dyn_dims()[0].is_fixed())
MIGRAPHX_THROW("RESIZE: size/scale input must be fixed size");
if(inputs.front().ndim() != inputs.back().to_static(1).lens()[0])
MIGRAPHX_THROW("RESIZE: size/scale input's size must match rank of input X");
if(not sizes.empty())
{
// the second shape is sizes
}
else
{
// the second shape is scales
}
// if(std::any_of(
// inputs.cbegin(), inputs.cend(), [](auto input) { return input->get_shape().dynamic(); }))
// {
// }
// No matter what the inputs, the output shape is dynamic, with an unlimited size range.
// TODO: How can we tell if the input shape is a literal? If it is, and input X is static,
// we can output a static shape.
std::size_t max_val = std::numeric_limits<std::size_t>::max();
std::vector<shape::dynamic_dimension> dyn_dims(inputs.back().lens().at(0),
shape::dynamic_dimension{0, max_val});
return {inputs.front().type(), dyn_dims};
// static input.
// if(!scales.empty())
// {
// // 计算输出blob大小
// auto in_s = inputs[0];
// auto in_lens = in_s.lens();
// if(in_lens.size() != scales.size())
// {
// MIGRAPHX_THROW("PARSE_UPSAMPLE: ranks of input and scale are different!");
// }
// std::vector<std::size_t> out_lens(in_lens.size());
// std::transform(in_lens.begin(),
// in_lens.end(),
// scales.begin(),
// out_lens.begin(),
// [&](auto idx, auto scale) { return static_cast<std::size_t>(idx * scale); });
// return shape{in_s.type(), out_lens};
// }
// else if(!sizes.empty())
// {
// return shape{inputs[0].type(), sizes};
// }
}
argument compute(const dyn_output& dyn_out, std::vector<argument> args) const
{
// See scatter.hpp or gather.hpp for how to do a similar iteration with reduction
// iterate through items in shape
argument result{dyn_out.computed_shape};
// negative axis means counting dimensions from back
auto lens = args[0].get_shape().lens();
//Everything that follows is placeholder logic
auto axis = 2;
std::size_t axis_dim_size = lens[axis];
// max dimension in axis
visit_all(result, args[0])([&](auto output, auto data) {
// the size input
args[1].visit([&](auto indices) {
for(auto aa : indices ) std::cout << aa << " indices \n";
if(dyn_out.computed_shape.scalar())
{
std::cout << " scalar output\n";
}
else
{
// for each element in output, calculate index in input
for(auto bb : data) std::cout << bb << " zzz data \n";
// auto out_lens = data.get_shape().lens();
// out_lens[axis] = indices.get_shape().elements();
migraphx::shape out_comp_shape{data.get_shape().type(), indices};
shape_for_each(out_comp_shape, [&](const auto& out_idx_v, size_t out_idx) {
auto data_idx = out_idx_v;
auto in_index = indices[data_idx[axis]];
in_index = (in_index < 0) ? in_index + axis_dim_size : in_index;
data_idx[axis] = in_index;
output[out_idx] = data(data_idx.begin(), data_idx.end());
std::cout << " !!!!! did something\n";
});
}
});
});
return result;
}
};
} // namespace op
} // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx
#endif
/*
* 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(resize_test_1)
{
// batch size 1, 1 color channel, resize 3x3 to 5x8
migraphx::program p;
auto* mm = p.get_main_module();
std::vector<float> data(3 * 3);
std::iota(data.begin(), data.end(), 0.5);
migraphx::shape s{migraphx::shape::float_type, {1, 1, 3, 3}};
auto a0 = mm->add_literal(migraphx::literal{s, data});
migraphx::shape size_input{migraphx::shape::int32_type, {4}};
std::vector<int> size_values = {1, 1, 5, 8};
auto a1 = mm->add_literal(migraphx::literal{size_input, size_values});
mm->add_instruction(migraphx::make_op("resize", {{"sizes", {1}}, {"scales", {}}}), a0, a1);
p.compile(migraphx::make_target("ref"));
auto result = p.eval({}).back();
std::vector<float> res_data(4 * 5);
std::vector<float> golden = {0.5f, 1.5f, 2.5f, 6.5f, 7.5f, 8.5f};
result.visit([&](auto output) { res_data.assign(output.begin(), output.end()); });
for(auto aa : res_data) std::cout << aa << ", "; std::cout << " result \n";
EXPECT(migraphx::verify::verify_rms_range(res_data, golden));
}
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