operation.cpp 7.37 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.
 */
Paul's avatar
Paul committed
24

Paul's avatar
Paul committed
25
#include <migraphx/operation.hpp>
Paul's avatar
Paul committed
26
#include <migraphx/context.hpp>
Paul's avatar
Paul committed
27
28
29
30
31
32
#include <sstream>
#include <string>
#include "test.hpp"

struct simple_operation
{
Paul's avatar
Paul committed
33
    template <class T, class F>
Paul's avatar
Paul committed
34
35
    static auto reflect(T& x, F f)
    {
Paul's avatar
Paul committed
36
        return migraphx::pack(f(x.data, "data"));
Paul's avatar
Paul committed
37
    }
Paul's avatar
Paul committed
38
    int data = 1;
Paul's avatar
Paul committed
39
    std::string name() const { return "simple"; }
Paul's avatar
Paul committed
40
    migraphx::shape compute_shape(const std::vector<migraphx::shape>&) const
Paul's avatar
Paul committed
41
    {
Paul's avatar
Paul committed
42
        MIGRAPHX_THROW("not computable");
Paul's avatar
Paul committed
43
    }
Paul's avatar
Paul committed
44
45
46
    migraphx::argument compute(migraphx::context&,
                               const migraphx::shape&,
                               const std::vector<migraphx::argument>&) const
Paul's avatar
Paul committed
47
    {
Paul's avatar
Paul committed
48
        MIGRAPHX_THROW("not computable");
Paul's avatar
Paul committed
49
    }
Paul's avatar
Paul committed
50
    friend std::ostream& operator<<(std::ostream& os, const simple_operation& op)
Paul's avatar
Paul committed
51
    {
Paul's avatar
Paul committed
52
        os << op.name() << "[" << op.data << "]";
Paul's avatar
Paul committed
53
54
        return os;
    }
Paul's avatar
Paul committed
55
56
};

Paul's avatar
Paul committed
57
58
59
struct simple_operation_no_print
{
    std::string name() const { return "simple"; }
Paul's avatar
Paul committed
60
    migraphx::shape compute_shape(const std::vector<migraphx::shape>&) const
Paul's avatar
Paul committed
61
    {
Paul's avatar
Paul committed
62
        MIGRAPHX_THROW("not computable");
Paul's avatar
Paul committed
63
    }
Paul's avatar
Paul committed
64
65
66
    migraphx::argument compute(migraphx::context&,
                               const migraphx::shape&,
                               const std::vector<migraphx::argument>&) const
Paul's avatar
Paul committed
67
    {
Paul's avatar
Paul committed
68
        MIGRAPHX_THROW("not computable");
Paul's avatar
Paul committed
69
    }
Paul's avatar
Paul committed
70
71
};

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
struct compilable_op
{
    std::string name() const { return "compilable"; }
    migraphx::argument
    compute(migraphx::context&, const migraphx::shape&, std::vector<migraphx::argument> args) const
    {
        if(args.empty())
            return {};
        return args.front();
    }

    migraphx::shape compute_shape(std::vector<migraphx::shape> inputs) const
    {
        if(inputs.empty())
            return {};
        return inputs.front();
    }

    int output_alias(const std::vector<migraphx::shape>&) const { return 0; }

    migraphx::value
    compile(migraphx::context&, const migraphx::shape&, const std::vector<migraphx::shape>&)
    {
        return {{"compiled", true}};
    }
};

Paul's avatar
Paul committed
99
TEST_CASE(operation_copy_test)
Paul's avatar
Paul committed
100
101
{
    simple_operation s{};
Paul's avatar
Paul committed
102
103
    migraphx::operation op1 = s;   // NOLINT
    migraphx::operation op2 = op1; // NOLINT
Paul's avatar
Paul committed
104
    // cppcheck-suppress duplicateExpression
Paul's avatar
Paul committed
105
    EXPECT(s == op1);
Paul's avatar
Paul committed
106
    // cppcheck-suppress duplicateExpression
Paul's avatar
Paul committed
107
108
109
    EXPECT(op2 == op1);
}

Paul Fultz II's avatar
Paul Fultz II committed
110
111
112
113
114
115
116
117
118
TEST_CASE(operation_copy_assign_test)
{
    simple_operation s{};
    migraphx::operation op;
    op = s;
    // cppcheck-suppress duplicateExpression
    EXPECT(s == op);
}

Paul's avatar
Paul committed
119
TEST_CASE(operation_equal_test)
Paul's avatar
Paul committed
120
121
{
    simple_operation s{};
Paul's avatar
Paul committed
122
    migraphx::operation op1 = s;
Paul's avatar
Paul committed
123
    s.data                  = 2;
Paul's avatar
Paul committed
124
125
    migraphx::operation op2 = op1; // NOLINT
    migraphx::operation op3 = s;   // NOLINT
Paul's avatar
Paul committed
126
127
128
129
130

    EXPECT(s != op1);
    EXPECT(op2 == op1);
    EXPECT(op3 != op2);
    EXPECT(op3 != op1);
Paul's avatar
Paul committed
131
132
}

Paul's avatar
Paul committed
133
134
135
struct not_operation
{
};
Paul's avatar
Paul committed
136

Paul's avatar
Paul committed
137
TEST_CASE(operation_any_cast)
Paul's avatar
Paul committed
138
{
Paul's avatar
Paul committed
139
140
141
142
143
144
145
    migraphx::operation op1 = simple_operation{};
    EXPECT(migraphx::any_cast<simple_operation>(op1).data == 1);
    EXPECT(migraphx::any_cast<not_operation*>(&op1) == nullptr);
    EXPECT(test::throws([&] { migraphx::any_cast<not_operation&>(op1); }));
    migraphx::operation op2 = simple_operation{2};
    EXPECT(migraphx::any_cast<simple_operation>(op2).data == 2);
    EXPECT(migraphx::any_cast<not_operation*>(&op2) == nullptr);
Paul's avatar
Paul committed
146
147
}

Paul's avatar
Paul committed
148
TEST_CASE(operation_print)
Paul's avatar
Paul committed
149
{
Paul's avatar
Paul committed
150
    migraphx::operation op = simple_operation{};
Paul's avatar
Paul committed
151
152
153
    std::stringstream ss;
    ss << op;
    std::string s = ss.str();
Paul's avatar
Paul committed
154
    EXPECT(s == "simple[1]");
Paul's avatar
Paul committed
155
156
}

Paul's avatar
Paul committed
157
TEST_CASE(operation_default_print)
Paul's avatar
Paul committed
158
{
Paul's avatar
Paul committed
159
    migraphx::operation op = simple_operation_no_print{};
Paul's avatar
Paul committed
160
161
162
163
164
165
    std::stringstream ss;
    ss << op;
    std::string s = ss.str();
    EXPECT(s == "simple");
}

Paul's avatar
Paul committed
166
167
168
169
170
171
172
struct final_operation
{
    std::string name() const { return "final"; }
    migraphx::shape compute_shape(const std::vector<migraphx::shape>&) const
    {
        MIGRAPHX_THROW("not computable");
    }
Paul's avatar
Paul committed
173
174
175
176
    void
    finalize(migraphx::context&, const migraphx::shape&, const std::vector<migraphx::shape>&) const
    {
    }
Paul's avatar
Paul committed
177
178
179
180
181
182
183
184
185
};

struct final_operation_throw
{
    std::string name() const { return "final"; }
    migraphx::shape compute_shape(const std::vector<migraphx::shape>&) const
    {
        MIGRAPHX_THROW("not computable");
    }
Paul's avatar
Paul committed
186
187
    [[gnu::noreturn]] void
    finalize(migraphx::context&, const migraphx::shape&, const std::vector<migraphx::shape>&) const
Paul's avatar
Paul committed
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
    {
        MIGRAPHX_THROW("finalize");
    }
};

TEST_CASE(check_has_finalize_simple)
{
    migraphx::operation op = simple_operation{};
    EXPECT(not migraphx::has_finalize(op));
}

TEST_CASE(check_has_finalize)
{
    migraphx::operation op = final_operation{};
    EXPECT(migraphx::has_finalize(op));
}

TEST_CASE(check_run_finalize)
{
    migraphx::operation op = final_operation{};
    migraphx::context ctx{};
    op.finalize(ctx, {}, {});
}

TEST_CASE(check_run_finalize_simple)
{
    migraphx::operation op = simple_operation{};
    migraphx::context ctx{};
    op.finalize(ctx, {}, {});
}

TEST_CASE(check_run_finalize_throw)
{
    migraphx::operation op = final_operation_throw{};
    migraphx::context ctx{};
Paul's avatar
Paul committed
223
    EXPECT(test::throws([&] { op.finalize(ctx, {}, {}); }));
Paul's avatar
Paul committed
224
225
}

226
227
228
229
230
231
232
233
234
235
236
TEST_CASE(check_to_value1)
{
    migraphx::operation op = simple_operation{};
    auto v                 = op.to_value();
    EXPECT(v == migraphx::value{{"data", 1}});
}

TEST_CASE(check_to_value2)
{
    migraphx::operation op = simple_operation{};
    auto v                 = migraphx::to_value(op);
237
    EXPECT(v == migraphx::value{{"name", "simple"}, {"operator", {{"data", 1}}}});
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
}

TEST_CASE(check_from_value1)
{
    migraphx::operation op1 = simple_operation{};
    migraphx::operation op2 = simple_operation{3};

    op1.from_value({{"data", 3}});
    EXPECT(op1 == op2);
}

TEST_CASE(check_from_value2)
{
    migraphx::operation op1 = migraphx::from_value<simple_operation>({{"data", 3}});
    migraphx::operation op2 = simple_operation{3};

    EXPECT(op1 == op2);
}

257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
TEST_CASE(compile)
{
    migraphx::operation op = compilable_op{};
    migraphx::context ctx{};
    auto v = op.compile(ctx, {}, {});
    EXPECT(v.at("compiled").to<bool>() == true);
}

TEST_CASE(compile_non_compilable)
{
    migraphx::operation op = simple_operation{};
    migraphx::context ctx{};
    auto v = op.compile(ctx, {}, {});
    EXPECT(v.empty());
}

Paul's avatar
Paul committed
273
int main(int argc, const char* argv[]) { test::run(argc, argv); }