mlir.cpp 6.9 KB
Newer Older
Paul's avatar
Paul committed
1
/*
Paul's avatar
Format  
Paul committed
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
    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;
Paul's avatar
Paul committed
135
    ref.get_main_module()->insert_instructions(ref.get_main_module()->end(), &mmlir);
Paul's avatar
Paul committed
136
137
138
139
140
141
142

    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); }