target.hpp 15.9 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
25
#ifndef MIGRAPHX_GUARD_MIGRAPHLIB_TARGET_HPP
#define MIGRAPHX_GUARD_MIGRAPHLIB_TARGET_HPP
Paul's avatar
Paul committed
26

Paul's avatar
Paul committed
27
#include <cassert>
Paul's avatar
Paul committed
28
29
30
31
32
#include <string>
#include <functional>
#include <memory>
#include <type_traits>
#include <utility>
Paul's avatar
Paul committed
33
#include <vector>
Paul's avatar
Paul committed
34
35
36
#include <migraphx/context.hpp>
#include <migraphx/pass.hpp>
#include <migraphx/config.hpp>
37
#include <migraphx/compile_options.hpp>
Shucai Xiao's avatar
Shucai Xiao committed
38
39
#include <migraphx/argument.hpp>
#include <migraphx/rank.hpp>
varunsh's avatar
varunsh committed
40
#include <migraphx/module_ref.hpp>
41
42
#include <migraphx/support_metric.hpp>
#include <migraphx/instruction_ref.hpp>
varunsh's avatar
varunsh committed
43
#include <migraphx/supported_segments.hpp>
Paul's avatar
Paul committed
44

Paul's avatar
Paul committed
45
namespace migraphx {
Paul's avatar
Paul committed
46
inline namespace MIGRAPHX_INLINE_NS {
Paul's avatar
Paul committed
47

Paul's avatar
Paul committed
48
#ifdef DOXYGEN
Paul's avatar
Paul committed
49

Paul's avatar
Paul committed
50
/// An interface for a compilation target
Paul's avatar
Paul committed
51
52
53
54
55
56
57
58
struct target
{
    /// A unique name used to identify the target
    std::string name() const;
    /**
     * @brief The transformation pass to be run during compilation.
     *
     * @param ctx This is the target-dependent context that is created by `get_context`
59
     * @param options Compiling options passed in by the user
Paul's avatar
Paul committed
60
61
     * @return The passes to be ran
     */
62
    std::vector<pass> get_passes(context& ctx, const compile_options& options) const;
Paul's avatar
Paul committed
63
64
65
66
67
    /**
     * @brief Construct a context for the target.
     * @return The context to be used during compilation and execution.
     */
    context get_context() const;
68
    /**
varunsh's avatar
varunsh committed
69
70
71
72
     * @brief Get the ranges of instructions that are supported on a target
     * @param module Module to check for supported instructions
     * @param metric Used to define how the quality of the support should be measured
     * @return the supported segments of the graph
73
     */
varunsh's avatar
varunsh committed
74
    supported_segments target_is_supported(T&, const_module_ref mod, support_metric metric) const;
Shucai Xiao's avatar
Shucai Xiao committed
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
    /**
     * @brief copy an argument to the current target.
     *
     * @param arg Input argument to be copied to the target
     * @return Argument in the target.
     */
    argument copy_to(const argument& arg) const;
    /**
     * @brief copy an argument from the current target.
     *
     * @param arg Input argument to be copied from the target
     * @return Argument in the host.
     */
    argument copy_from(const argument& arg) const;
    /**
     * @brief Allocate an argument based on the input shape
     *
     * @param s Shape of the argument to be allocated in the target
     * @return Allocated argument in the target.
     */
    argument allocate(const shape& s) const;
Paul's avatar
Paul committed
96
97
98
};

#else
Paul's avatar
Paul committed
99

Shucai Xiao's avatar
Shucai Xiao committed
100
template <class T>
Paul's avatar
Paul committed
101
argument target_allocate(T& x, const shape&)
Shucai Xiao's avatar
Shucai Xiao committed
102
103
104
105
106
107
{
    std::string name = x.name();
    MIGRAPHX_THROW("Not computable: " + name);
}

template <class T>
Paul's avatar
Paul committed
108
argument copy_to_target(T&, const argument& arg)
Shucai Xiao's avatar
Shucai Xiao committed
109
{
Shucai Xiao's avatar
Shucai Xiao committed
110
    return arg;
Shucai Xiao's avatar
Shucai Xiao committed
111
112
113
}

template <class T>
Paul's avatar
Paul committed
114
argument copy_from_target(T&, const argument& arg)
Shucai Xiao's avatar
Shucai Xiao committed
115
{
Shucai Xiao's avatar
Shucai Xiao committed
116
    return arg;
Shucai Xiao's avatar
Shucai Xiao committed
117
118
}

119
template <class T>
varunsh's avatar
varunsh committed
120
supported_segments target_find_supported(T&, const_module_ref, support_metric)
121
{
varunsh's avatar
varunsh committed
122
    return {};
123
124
}

125
126
127
128
129
130
131
132
133
134
135
136
#ifdef TYPE_ERASED_DECLARATION

// Type-erased interface for:
struct target
{
    //
    std::string name() const;
    //
    std::vector<pass> get_passes(context& ctx, const compile_options& options) const;
    //
    context get_context() const;
    // (optional)
varunsh's avatar
varunsh committed
137
    supported_segments find_supported(const_module_ref mod, support_metric m) const;
138
    // (optional)
139
140
141
142
143
144
145
146
    argument copy_to(const argument& input) const;
    // (optional)
    argument copy_from(const argument& input) const;
    // (optional)
    argument allocate(const shape& s) const;
};

#else
Paul's avatar
Paul committed
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

struct target
{
    // Constructors
    target() = default;

    template <typename PrivateDetailTypeErasedT>
    target(PrivateDetailTypeErasedT value)
        : private_detail_te_handle_mem_var(
              std::make_shared<private_detail_te_handle_type<
                  typename std::remove_reference<PrivateDetailTypeErasedT>::type>>(
                  std::forward<PrivateDetailTypeErasedT>(value)))
    {
    }

    // Assignment
    template <typename PrivateDetailTypeErasedT>
    target& operator=(PrivateDetailTypeErasedT value)
    {
Paul Fultz II's avatar
Paul Fultz II committed
166
167
168
169
170
171
172
173
174
175
176
        using std::swap;
        auto* derived = this->any_cast<PrivateDetailTypeErasedT>();
        if(derived and private_detail_te_handle_mem_var.unique())
        {
            *derived = std::forward<PrivateDetailTypeErasedT>(value);
        }
        else
        {
            target rhs(value);
            swap(private_detail_te_handle_mem_var, rhs.private_detail_te_handle_mem_var);
        }
Paul's avatar
Paul committed
177
178
179
180
181
182
183
        return *this;
    }

    // Cast
    template <typename PrivateDetailTypeErasedT>
    PrivateDetailTypeErasedT* any_cast()
    {
Paul Fultz II's avatar
Paul Fultz II committed
184
        return this->type_id() == typeid(PrivateDetailTypeErasedT)
Paul's avatar
Paul committed
185
186
187
188
189
190
191
192
193
194
                   ? std::addressof(static_cast<private_detail_te_handle_type<
                                        typename std::remove_cv<PrivateDetailTypeErasedT>::type>&>(
                                        private_detail_te_get_handle())
                                        .private_detail_te_value)
                   : nullptr;
    }

    template <typename PrivateDetailTypeErasedT>
    const typename std::remove_cv<PrivateDetailTypeErasedT>::type* any_cast() const
    {
Paul Fultz II's avatar
Paul Fultz II committed
195
        return this->type_id() == typeid(PrivateDetailTypeErasedT)
Paul's avatar
Paul committed
196
197
198
199
200
201
202
                   ? std::addressof(static_cast<const private_detail_te_handle_type<
                                        typename std::remove_cv<PrivateDetailTypeErasedT>::type>&>(
                                        private_detail_te_get_handle())
                                        .private_detail_te_value)
                   : nullptr;
    }

Paul's avatar
Paul committed
203
204
205
206
207
208
209
210
    const std::type_info& type_id() const
    {
        if(private_detail_te_handle_empty())
            return typeid(std::nullptr_t);
        else
            return private_detail_te_get_handle().type();
    }

Paul's avatar
Paul committed
211
212
    std::string name() const
    {
Paul's avatar
Paul committed
213
214
        assert((*this).private_detail_te_handle_mem_var);
        return (*this).private_detail_te_get_handle().name();
Paul's avatar
Paul committed
215
216
    }

217
    std::vector<pass> get_passes(context& ctx, const compile_options& options) const
Paul's avatar
Paul committed
218
    {
Paul's avatar
Paul committed
219
        assert((*this).private_detail_te_handle_mem_var);
220
        return (*this).private_detail_te_get_handle().get_passes(ctx, options);
Paul's avatar
Paul committed
221
222
    }

Paul's avatar
Paul committed
223
224
225
226
227
228
    context get_context() const
    {
        assert((*this).private_detail_te_handle_mem_var);
        return (*this).private_detail_te_get_handle().get_context();
    }

varunsh's avatar
varunsh committed
229
    supported_segments find_supported(const_module_ref mod, support_metric m) const
230
231
    {
        assert((*this).private_detail_te_handle_mem_var);
varunsh's avatar
varunsh committed
232
        return (*this).private_detail_te_get_handle().find_supported(mod, m);
233
234
    }

Shucai Xiao's avatar
Shucai Xiao committed
235
    argument copy_to(const argument& input) const
236
237
    {
        assert((*this).private_detail_te_handle_mem_var);
Shucai Xiao's avatar
Shucai Xiao committed
238
        return (*this).private_detail_te_get_handle().copy_to(input);
239
240
    }

Shucai Xiao's avatar
Shucai Xiao committed
241
    argument copy_from(const argument& input) const
242
243
    {
        assert((*this).private_detail_te_handle_mem_var);
Shucai Xiao's avatar
Shucai Xiao committed
244
        return (*this).private_detail_te_get_handle().copy_from(input);
245
246
247
248
249
250
251
252
    }

    argument allocate(const shape& s) const
    {
        assert((*this).private_detail_te_handle_mem_var);
        return (*this).private_detail_te_get_handle().allocate(s);
    }

Paul's avatar
Paul committed
253
254
255
256
257
258
    friend bool is_shared(const target& private_detail_x, const target& private_detail_y)
    {
        return private_detail_x.private_detail_te_handle_mem_var ==
               private_detail_y.private_detail_te_handle_mem_var;
    }

Paul's avatar
Paul committed
259
260
261
262
263
264
265
    private:
    struct private_detail_te_handle_base_type
    {
        virtual ~private_detail_te_handle_base_type() {}
        virtual std::shared_ptr<private_detail_te_handle_base_type> clone() const = 0;
        virtual const std::type_info& type() const                                = 0;

varunsh's avatar
varunsh committed
266
        virtual std::string name() const                                                        = 0;
267
        virtual std::vector<pass> get_passes(context& ctx,
varunsh's avatar
varunsh committed
268
269
270
271
272
273
                                             const compile_options& options) const              = 0;
        virtual context get_context() const                                                     = 0;
        virtual supported_segments find_supported(const_module_ref mod, support_metric m) const = 0;
        virtual argument copy_to(const argument& input) const                                   = 0;
        virtual argument copy_from(const argument& input) const                                 = 0;
        virtual argument allocate(const shape& s) const                                         = 0;
Paul's avatar
Paul committed
274
275
    };

276
    template <class T>
varunsh's avatar
varunsh committed
277
278
279
280
281
    static auto private_detail_te_default_find_supported(char,
                                                         T&& private_detail_te_self,
                                                         const_module_ref mod,
                                                         support_metric m)
        -> decltype(private_detail_te_self.find_supported(mod, m))
282
    {
varunsh's avatar
varunsh committed
283
        return private_detail_te_self.find_supported(mod, m);
284
285
286
    }

    template <class T>
varunsh's avatar
varunsh committed
287
288
289
290
    static supported_segments private_detail_te_default_find_supported(float,
                                                                       T&& private_detail_te_self,
                                                                       const_module_ref mod,
                                                                       support_metric m)
291
    {
varunsh's avatar
varunsh committed
292
        return target_find_supported(private_detail_te_self, mod, m);
293
294
    }

295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
    template <class T>
    static auto
    private_detail_te_default_copy_to(char, T&& private_detail_te_self, const argument& input)
        -> decltype(private_detail_te_self.copy_to(input))
    {
        return private_detail_te_self.copy_to(input);
    }

    template <class T>
    static argument
    private_detail_te_default_copy_to(float, T&& private_detail_te_self, const argument& input)
    {
        return copy_to_target(private_detail_te_self, input);
    }

    template <class T>
    static auto
    private_detail_te_default_copy_from(char, T&& private_detail_te_self, const argument& input)
        -> decltype(private_detail_te_self.copy_from(input))
    {
        return private_detail_te_self.copy_from(input);
    }

    template <class T>
    static argument
    private_detail_te_default_copy_from(float, T&& private_detail_te_self, const argument& input)
    {
        return copy_from_target(private_detail_te_self, input);
    }

    template <class T>
    static auto private_detail_te_default_allocate(char, T&& private_detail_te_self, const shape& s)
        -> decltype(private_detail_te_self.allocate(s))
    {
        return private_detail_te_self.allocate(s);
    }

    template <class T>
    static argument
    private_detail_te_default_allocate(float, T&& private_detail_te_self, const shape& s)
    {
        return target_allocate(private_detail_te_self, s);
    }

Paul's avatar
Paul committed
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
    template <typename PrivateDetailTypeErasedT>
    struct private_detail_te_handle_type : private_detail_te_handle_base_type
    {
        template <typename PrivateDetailTypeErasedU = PrivateDetailTypeErasedT>
        private_detail_te_handle_type(
            PrivateDetailTypeErasedT value,
            typename std::enable_if<std::is_reference<PrivateDetailTypeErasedU>::value>::type* =
                nullptr)
            : private_detail_te_value(value)
        {
        }

        template <typename PrivateDetailTypeErasedU = PrivateDetailTypeErasedT>
        private_detail_te_handle_type(
            PrivateDetailTypeErasedT value,
354
            typename std::enable_if<not std::is_reference<PrivateDetailTypeErasedU>::value,
Paul's avatar
Paul committed
355
356
357
358
359
360
361
362
363
364
365
366
367
368
                                    int>::type* = nullptr) noexcept
            : private_detail_te_value(std::move(value))
        {
        }

        std::shared_ptr<private_detail_te_handle_base_type> clone() const override
        {
            return std::make_shared<private_detail_te_handle_type>(private_detail_te_value);
        }

        const std::type_info& type() const override { return typeid(private_detail_te_value); }

        std::string name() const override { return private_detail_te_value.name(); }

369
        std::vector<pass> get_passes(context& ctx, const compile_options& options) const override
Paul's avatar
Paul committed
370
371
        {

372
            return private_detail_te_value.get_passes(ctx, options);
Paul's avatar
Paul committed
373
        }
Paul's avatar
Paul committed
374

Paul's avatar
Paul committed
375
376
        context get_context() const override { return private_detail_te_value.get_context(); }

varunsh's avatar
varunsh committed
377
        supported_segments find_supported(const_module_ref mod, support_metric m) const override
378
379
        {

varunsh's avatar
varunsh committed
380
381
            return private_detail_te_default_find_supported(
                char(0), private_detail_te_value, mod, m);
382
383
        }

Shucai Xiao's avatar
Shucai Xiao committed
384
        argument copy_to(const argument& input) const override
Shucai Xiao's avatar
Shucai Xiao committed
385
        {
Shucai Xiao's avatar
Shucai Xiao committed
386

387
            return private_detail_te_default_copy_to(char(0), private_detail_te_value, input);
Shucai Xiao's avatar
Shucai Xiao committed
388
        }
389

Shucai Xiao's avatar
Shucai Xiao committed
390
        argument copy_from(const argument& input) const override
Shucai Xiao's avatar
Shucai Xiao committed
391
        {
Shucai Xiao's avatar
Shucai Xiao committed
392

393
            return private_detail_te_default_copy_from(char(0), private_detail_te_value, input);
Shucai Xiao's avatar
Shucai Xiao committed
394
        }
395

Shucai Xiao's avatar
Shucai Xiao committed
396
397
        argument allocate(const shape& s) const override
        {
Shucai Xiao's avatar
Shucai Xiao committed
398

399
            return private_detail_te_default_allocate(char(0), private_detail_te_value, s);
Shucai Xiao's avatar
Shucai Xiao committed
400
        }
401

Paul's avatar
Paul committed
402
403
404
405
406
407
408
409
410
411
412
413
414
        PrivateDetailTypeErasedT private_detail_te_value;
    };

    template <typename PrivateDetailTypeErasedT>
    struct private_detail_te_handle_type<std::reference_wrapper<PrivateDetailTypeErasedT>>
        : private_detail_te_handle_type<PrivateDetailTypeErasedT&>
    {
        private_detail_te_handle_type(std::reference_wrapper<PrivateDetailTypeErasedT> ref)
            : private_detail_te_handle_type<PrivateDetailTypeErasedT&>(ref.get())
        {
        }
    };

Paul's avatar
Paul committed
415
416
417
418
419
    bool private_detail_te_handle_empty() const
    {
        return private_detail_te_handle_mem_var == nullptr;
    }

Paul's avatar
Paul committed
420
421
    const private_detail_te_handle_base_type& private_detail_te_get_handle() const
    {
Paul's avatar
Paul committed
422
        assert(private_detail_te_handle_mem_var != nullptr);
Paul's avatar
Paul committed
423
424
425
426
427
        return *private_detail_te_handle_mem_var;
    }

    private_detail_te_handle_base_type& private_detail_te_get_handle()
    {
Paul's avatar
Paul committed
428
        assert(private_detail_te_handle_mem_var != nullptr);
429
        if(not private_detail_te_handle_mem_var.unique())
Paul's avatar
Paul committed
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
            private_detail_te_handle_mem_var = private_detail_te_handle_mem_var->clone();
        return *private_detail_te_handle_mem_var;
    }

    std::shared_ptr<private_detail_te_handle_base_type> private_detail_te_handle_mem_var;
};

template <typename ValueType>
inline const ValueType* any_cast(const target* x)
{
    return x->any_cast<ValueType>();
}

template <typename ValueType>
inline ValueType* any_cast(target* x)
{
    return x->any_cast<ValueType>();
}

template <typename ValueType>
inline ValueType& any_cast(target& x)
{
    auto* y = x.any_cast<typename std::remove_reference<ValueType>::type>();
    if(y == nullptr)
        throw std::bad_cast();
    return *y;
}

template <typename ValueType>
inline const ValueType& any_cast(const target& x)
{
    const auto* y = x.any_cast<typename std::remove_reference<ValueType>::type>();
    if(y == nullptr)
        throw std::bad_cast();
    return *y;
}
466
#endif
Paul's avatar
Paul committed
467

Paul's avatar
Paul committed
468
469
#endif

Paul's avatar
Paul committed
470
} // namespace MIGRAPHX_INLINE_NS
Paul's avatar
Paul committed
471
} // namespace migraphx
Paul's avatar
Paul committed
472
473

#endif