mlir.cpp 6.89 KB
Newer Older
Paul's avatar
Paul committed
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
#include <migraphx/gpu/mlir.hpp>
Paul's avatar
Paul committed
25
#include <migraphx/gpu/target.hpp>
Paul's avatar
Paul committed
26
27
#include <migraphx/gpu/context.hpp>
#include <migraphx/gpu/write_literals.hpp>
Paul's avatar
Paul committed
28
#include <migraphx/ref/target.hpp>
29
#include <migraphx/module.hpp>
Paul's avatar
Paul committed
30
#include <migraphx/program.hpp>
31
32
33
#include <migraphx/make_op.hpp>
#include <migraphx/ranges.hpp>
#include <migraphx/stringutils.hpp>
Paul's avatar
Paul committed
34
35
#include <migraphx/generate.hpp>
#include <migraphx/verify_args.hpp>
Paul's avatar
Paul committed
36
37
#include <migraphx/instruction.hpp>
#include <migraphx/functional.hpp>
38
39
40
41
#include <test.hpp>

using migraphx::trim;

Paul's avatar
Paul committed
42
43
// m test_gpu_mlir && ./bin/test_gpu_mlir

Paul's avatar
Paul committed
44
45
46
struct mlir_gpu_target : migraphx::gpu::target
{
    std::string name() const { return "mlir"; }
Paul's avatar
Format  
Paul committed
47
48
    std::vector<migraphx::pass> get_passes(migraphx::context& gctx,
                                           const migraphx::compile_options&) const
Paul's avatar
Paul committed
49
50
    {
        auto& ctx = migraphx::any_cast<migraphx::gpu::context>(gctx);
Paul's avatar
Format  
Paul committed
51
        return {migraphx::gpu::write_literals{&ctx}};
Paul's avatar
Paul committed
52
53
54
    }
};

Paul's avatar
Paul committed
55
std::string encode(const std::string& s)
56
57
58
{
    std::stringstream ss;
    bool prespace = false;
Paul's avatar
Paul committed
59
    for(auto c : s)
60
    {
Paul's avatar
Paul committed
61
        if(std::isspace(c) != 0)
62
        {
Paul's avatar
Paul committed
63
            if(not prespace)
64
65
66
                ss << "  ";
            prespace = true;
        }
Paul's avatar
Paul committed
67
        else if(std::isprint(c) != 0)
68
69
70
71
72
73
74
75
        {
            ss << c;
            prespace = false;
        }
    }
    return migraphx::trim(ss.str());
}

Paul's avatar
Paul committed
76
77
78
migraphx::program create_program_from_mlir(const migraphx::module& mmlir)
{
    migraphx::program p;
Paul's avatar
Paul committed
79
    auto* mm   = p.get_main_module();
Paul's avatar
Paul committed
80
81
82
83
84
    auto names = mmlir.get_parameter_names();
    std::vector<migraphx::instruction_ref> inputs;
    std::transform(names.begin(), names.end(), std::back_inserter(inputs), [&](const auto& name) {
        return mm->add_parameter(name, mmlir.get_parameter_shape(name));
    });
Paul's avatar
Format  
Paul committed
85
86
87
    std::sort(inputs.begin(), inputs.end(), migraphx::by(std::less<>{}, [](auto ins) {
                  return to_string(ins->get_operator());
              }));
Paul's avatar
Paul committed
88
    inputs.push_back(mm->add_parameter("output", mmlir.get_output_shapes().front()));
Paul's avatar
Paul committed
89

Paul's avatar
Paul committed
90
91
    migraphx::gpu::context ctx;
    migraphx::gpu::insert_mlir(*mm, mm->end(), compile_mlir(ctx, mmlir), inputs);
Paul's avatar
Paul committed
92
93
94
95
96
97
98
99
100
    return p;
}

migraphx::parameter_map generate_params(const migraphx::program& p)
{
    migraphx::parameter_map m;
    std::size_t i = 0;
    for(auto&& x : p.get_parameter_shapes())
    {
Paul's avatar
Updates  
Paul committed
101
        // m[x.first] = migraphx::fill_argument(x.second, 1);
Paul's avatar
Paul committed
102
103
104
105
106
107
108
        m[x.first] = migraphx::generate_argument(x.second, i++);
    }
    return m;
}

migraphx::argument run_gpu(migraphx::program p, const migraphx::parameter_map& inputs)
{
Paul's avatar
Paul committed
109
    mlir_gpu_target t;
Paul's avatar
Paul committed
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
    p.compile(t);
    migraphx::parameter_map m;
    for(auto&& input : inputs)
    {
        m[input.first] = t.copy_to(input.second);
    }
    for(auto&& x : p.get_parameter_shapes())
    {
        if(m.count(x.first) == 0)
        {
            m[x.first] = t.allocate(x.second);
        }
    }
    return t.copy_from(p.eval(m).front());
}

migraphx::argument run_ref(migraphx::program p, const migraphx::parameter_map& inputs)
{
    p.compile(migraphx::ref::target{});
    return p.eval(inputs).front();
}

bool verify_mlir(const migraphx::module& mmlir)
{
    migraphx::program ref;
    ref.get_main_module()->insert_module_instructions(ref.get_main_module()->end(), &mmlir);

    auto inputs = generate_params(ref);

    auto mlir = create_program_from_mlir(mmlir);
    return migraphx::verify_args("mlir", run_ref(ref, inputs), run_gpu(mlir, inputs));
}

143
144
145
TEST_CASE(conv)
{
    const std::string mlir_output = R"__migraphx__(
Paul's avatar
Paul committed
146
147
148
module {
  func @main(%arg0: tensor<2x8x3x3xf32>, %arg1: tensor<1x8x4x4xf32>) -> tensor<1x2x2x2xf32> attributes {kernel = "mixr"} {
    %0 = migraphx.convolution(%arg1, %arg0) {dilation = [1, 1], group = 1 : i64, padding = [0, 0, 0, 0], padding_mode = 0 : i64, stride = [1, 1]} : (tensor<1x8x4x4xf32>, tensor<2x8x3x3xf32>) -> tensor<1x2x2x2xf32>
149
    return %0 : tensor<1x2x2x2xf32>
150
151
152
153
  }
}
)__migraphx__";
    migraphx::module m;
Paul's avatar
Format  
Paul committed
154
155
    auto x    = m.add_parameter("x", {migraphx::shape::float_type, {1, 8, 4, 4}});
    auto w    = m.add_parameter("w", {migraphx::shape::float_type, {2, 8, 3, 3}});
Paul's avatar
Paul committed
156
    auto conv = m.add_instruction(migraphx::make_op("convolution"), x, w);
Paul's avatar
Paul committed
157
    m.add_return({conv});
158
    auto s = migraphx::gpu::dump_mlir(m);
Paul's avatar
Paul committed
159
    // Skip test if MLIR is not enabled
Paul's avatar
Format  
Paul committed
160
    if(s.empty())
Paul's avatar
Paul committed
161
        return;
Paul's avatar
Paul committed
162
    CHECK(encode(s) == encode(mlir_output));
Paul's avatar
Paul committed
163
    EXPECT(verify_mlir(m));
Paul's avatar
Paul committed
164
165
166
167
168
}

TEST_CASE(conv_add_relu)
{
    const std::string mlir_output = R"__migraphx__(
Paul's avatar
Paul committed
169
170
171
172
module {
  func @main(%arg0: tensor<1x2x2x2xf32>, %arg1: tensor<2x8x3x3xf32>, %arg2: tensor<1x8x4x4xf32>) -> tensor<1x2x2x2xf32> attributes {kernel = "mixr"} {
    %0 = migraphx.convolution(%arg2, %arg1) {dilation = [1, 1], group = 1 : i64, padding = [0, 0, 0, 0], padding_mode = 0 : i64, stride = [1, 1]} : (tensor<1x8x4x4xf32>, tensor<2x8x3x3xf32>) -> tensor<1x2x2x2xf32>
    %1 = migraphx.add(%0, %arg0) : (tensor<1x2x2x2xf32>, tensor<1x2x2x2xf32>) -> tensor<1x2x2x2xf32>
Paul's avatar
Paul committed
173
    %2 = migraphx.relu(%1) : (tensor<1x2x2x2xf32>) -> tensor<1x2x2x2xf32>
174
    return %2 : tensor<1x2x2x2xf32>
Paul's avatar
Paul committed
175
176
177
178
  }
}
)__migraphx__";
    migraphx::module m;
Paul's avatar
Format  
Paul committed
179
180
181
    auto x    = m.add_parameter("x", {migraphx::shape::float_type, {1, 8, 4, 4}});
    auto w    = m.add_parameter("w", {migraphx::shape::float_type, {2, 8, 3, 3}});
    auto b    = m.add_parameter("b", {migraphx::shape::float_type, {1, 2, 2, 2}});
Paul's avatar
Paul committed
182
    auto conv = m.add_instruction(migraphx::make_op("convolution"), x, w);
Paul's avatar
Format  
Paul committed
183
    auto add  = m.add_instruction(migraphx::make_op("add"), conv, b);
Paul's avatar
Paul committed
184
185
    auto relu = m.add_instruction(migraphx::make_op("relu"), add);
    m.add_return({relu});
Paul's avatar
Paul committed
186
187
    auto s = migraphx::gpu::dump_mlir(m);
    // Skip test if MLIR is not enabled
Paul's avatar
Format  
Paul committed
188
    if(s.empty())
Paul's avatar
Paul committed
189
        return;
Paul's avatar
Paul committed
190
    CHECK(encode(s) == encode(mlir_output));
Paul's avatar
Paul committed
191
    EXPECT(verify_mlir(m));
192
193
194
}

int main(int argc, const char* argv[]) { test::run(argc, argv); }