concat.hpp 4.57 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*
 * 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.
 */
24
25
26
27
28
29
30
31
32
33
#ifndef MIGRAPHX_GUARD_OPERATORS_CONCAT_HPP
#define MIGRAPHX_GUARD_OPERATORS_CONCAT_HPP

#include <array>
#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>
Shucai Xiao's avatar
Shucai Xiao committed
34
#include <migraphx/value.hpp>
35
#include <migraphx/permutation.hpp>
Shucai Xiao's avatar
Shucai Xiao committed
36
#include <migraphx/op/normalize_attribute.hpp>
37
38
39
40
41
42
43
44
45
#include <cmath>
#include <utility>

namespace migraphx {
inline namespace MIGRAPHX_INLINE_NS {
namespace op {

struct concat
{
Shucai Xiao's avatar
Shucai Xiao committed
46
    int64_t axis = 0;
47
48
49
50
51
52

    template <class Self, class F>
    static auto reflect(Self& self, F f)
    {
        return pack(f(self.axis, "axis"));
    }
Paul's avatar
Paul committed
53

Shucai Xiao's avatar
Shucai Xiao committed
54
55
56
57
58
59
60
    value attributes() const
    {
        value normalize;
        normalize["axis"] = value::array{normalize_attribute::include_min};
        return {{"normalize_axes", normalize}};
    }

61
62
63
64
    std::string name() const { return "concat"; }
    std::vector<std::size_t> compute_offsets(const shape& output_shape,
                                             const std::vector<argument>& args) const
    {
65
        auto n_dims = args[0].get_shape().lens().size();
66
        std::vector<std::size_t> offsets;
Shucai Xiao's avatar
Shucai Xiao committed
67
        std::vector<std::size_t> offset(n_dims, 0);
68
        offset[axis] = 0;
69
70
71
        for(const auto& arg : args)
        {
            offsets.push_back(output_shape.index(offset));
72
            offset[axis] += arg.get_shape().lens()[axis];
73
74
75
        }
        return offsets;
    }
Shucai Xiao's avatar
Shucai Xiao committed
76
    shape normalize_compute_shape(std::vector<shape> inputs) const
77
78
79
    {
        if(inputs.empty())
        {
Shucai Xiao's avatar
Shucai Xiao committed
80
            MIGRAPHX_THROW("CONCAT: Number of input tensors should exceed 0");
81
82
83
84
85
86
        }

        const auto& first_shape_lens = inputs.front().lens();
        const auto& type             = inputs.front().type();
        for(std::size_t l = 0; l < first_shape_lens.size(); l++)
        {
Shucai Xiao's avatar
Shucai Xiao committed
87
            if(l != axis)
88
            {
89
                if(not std::all_of(inputs.begin(), inputs.end(), [&](auto s) {
90
91
92
                       return s.lens()[l] == first_shape_lens[l];
                   }))
                {
Shucai Xiao's avatar
Shucai Xiao committed
93
                    MIGRAPHX_THROW("CONCAT: Non-axis dimensions should match");
94
95
96
97
98
99
100
                }
            }
        }
        std::size_t new_dim_axis = 0;
        for(const auto& input : inputs)
        {
            const auto& lens = input.lens();
Shucai Xiao's avatar
Shucai Xiao committed
101
            new_dim_axis += lens[axis];
102
103
104
        }
        std::vector<std::size_t> new_lens;
        std::copy(first_shape_lens.begin(), first_shape_lens.end(), std::back_inserter(new_lens));
Shucai Xiao's avatar
Shucai Xiao committed
105
        new_lens[axis] = new_dim_axis;
106
        return shape::from_permutation(type, new_lens, find_permutation(inputs));
107
108
109
110
111
112
113
    }
    argument compute(const shape& output_shape, std::vector<argument> args) const
    {
        argument result{output_shape};
        std::vector<std::size_t> coffsets = compute_offsets(output_shape, args);
        for(std::size_t l = 0; l < args.size(); l++)
        {
114
            auto argl = args[l];
115
116
117
118
            visit_all(result, argl)([&](auto output, auto input) {
                auto slice_shape =
                    shape{output_shape.type(), input.get_shape().lens(), output_shape.strides()};
                auto slice = make_view(slice_shape, output.data() + coffsets[l]);
119
                std::copy(input.begin(), input.end(), slice.begin());
120
121
122
123
124
125
126
127
128
129
130
            });
        }
        return result;
    }
};

} // namespace op
} // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx

#endif