jit.cpp 7.26 KB
Newer Older
Paul Fultz II's avatar
Paul Fultz II committed
1
2
#include <test.hpp>
#include <migraphx/ranges.hpp>
3
4
5
#include <migraphx/make_op.hpp>
#include <migraphx/generate.hpp>
#include <migraphx/program.hpp>
Paul Fultz II's avatar
Paul Fultz II committed
6
#include <migraphx/gpu/kernel.hpp>
7
#include <migraphx/gpu/target.hpp>
Paul Fultz II's avatar
Paul Fultz II committed
8
#include <migraphx/gpu/hip.hpp>
9
#include <migraphx/gpu/context.hpp>
10
#include <migraphx/gpu/device_name.hpp>
Paul Fultz II's avatar
Paul Fultz II committed
11
#include <migraphx/gpu/compile_hip.hpp>
12
#include <migraphx/gpu/compile_hip_code_object.hpp>
13
#include <migraphx/gpu/compile_pointwise.hpp>
Paul Fultz II's avatar
Paul Fultz II committed
14
15

// NOLINTNEXTLINE
16
const std::string write_2s = R"__migraphx__(
Paul Fultz II's avatar
Paul Fultz II committed
17
18
19
#include <hip/hip_runtime.h>

extern "C" {
20
__global__ void write(int8_t* data) 
Paul Fultz II's avatar
Paul Fultz II committed
21
22
23
24
25
26
27
28
29
{
    int num = threadIdx.x + blockDim.x * blockIdx.x;
    data[num] = 2;
}
    
}

int main() {}

30
)__migraphx__";
Paul Fultz II's avatar
Paul Fultz II committed
31

32
// NOLINTNEXTLINE
33
const std::string add_2s_binary = R"__migraphx__(
34
35
36
#include <hip/hip_runtime.h>

extern "C" {
37
__global__ void add_2(std::int8_t* x, std::int8_t* y) 
38
39
40
41
42
43
44
45
46
{
    int num = threadIdx.x + blockDim.x * blockIdx.x;
    y[num] = x[num] + 2;
}
    
}

int main() {}

47
48
49
50
51
52
53
54
55
56
57
58
)__migraphx__";

// NOLINTNEXTLINE
const std::string simple_pointwise_increment = R"__migraphx__(
#include <migraphx/kernels/index.hpp>
#include <args.hpp>

using namespace migraphx;

extern "C" {
__global__ void kernel(void* x, void* y) 
{
59
    make_tensors()(x, y)([](auto xt, auto yt) __device__ {
60
61
62
63
64
65
66
67
68
69
70
71
72
73
        auto idx = make_index();
        const auto stride = idx.nglobal();
        for(index_int i = idx.global; i < xt.get_shape().elements(); i += stride)
        {
            yt[i] = xt[i] + 1;
        }
    });
}
    
}

int main() {}

)__migraphx__";
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
99
100
101
102
103
104
105
106
107
108
109
110
111
// NOLINTNEXTLINE
const std::string check_define = R"__migraphx__(

#ifndef __DEFINE__
#error __DEFINE__ was not defined
#endif

int main() {}

)__migraphx__";

// NOLINTNEXTLINE
const std::string unused_param = R"__migraphx__(

extern "C" {
__global__ void kernel(void* x, void* y) 
{}
}

int main() {}

)__migraphx__";

// NOLINTNEXTLINE
const std::string incorrect_program = R"__migraphx__(

extern "C" {
__global__ void kernel(void* x) 
{
    x += y;
}
}

int main() {}

)__migraphx__";

112
migraphx::src_file make_src_file(const std::string& name, const std::string& content)
Paul Fultz II's avatar
Paul Fultz II committed
113
114
115
116
117
118
119
{
    return {name, std::make_pair(content.data(), content.data() + content.size())};
}

TEST_CASE(simple_compile_hip)
{
    auto binaries = migraphx::gpu::compile_hip_src(
120
        {make_src_file("main.cpp", write_2s)}, "", migraphx::gpu::get_device_name());
Paul Fultz II's avatar
Paul Fultz II committed
121
122
    EXPECT(binaries.size() == 1);

123
    migraphx::argument input{{migraphx::shape::int8_type, {5}}};
Paul Fultz II's avatar
Paul Fultz II committed
124
125
    auto ginput = migraphx::gpu::to_gpu(input);
    migraphx::gpu::kernel k{binaries.front(), "write"};
126
    k.launch(nullptr, input.get_shape().elements(), 1024)(ginput.cast<std::int8_t>());
Paul Fultz II's avatar
Paul Fultz II committed
127
128
129
    auto output = migraphx::gpu::from_gpu(ginput);

    EXPECT(output != input);
130
    auto data = output.get<std::int8_t>();
Paul Fultz II's avatar
Paul Fultz II committed
131
132
133
    EXPECT(migraphx::all_of(data, [](auto x) { return x == 2; }));
}

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
auto check_target(const std::string& arch)
{
    auto define  = "__" + arch + "__";
    auto content = migraphx::replace_string(check_define, "__DEFINE__", define);
    return migraphx::gpu::compile_hip_src({make_src_file("main.cpp", content)}, "", arch);
}

TEST_CASE(compile_target)
{
    EXPECT(not check_target("gfx900").empty());
    EXPECT(not check_target("gfx906").empty());
}

TEST_CASE(compile_errors)
{
    EXPECT(test::throws([&] {
        migraphx::gpu::compile_hip_src(
            {make_src_file("main.cpp", incorrect_program)}, "", migraphx::gpu::get_device_name());
    }));
}

TEST_CASE(compile_warnings)
{
    auto compile = [](const std::string& params) {
        return migraphx::gpu::compile_hip_src(
            {make_src_file("main.cpp", unused_param)}, params, migraphx::gpu::get_device_name());
    };

    EXPECT(not compile("").empty());
    EXPECT(not compile("-Wunused-parameter -Wno-error").empty());
    EXPECT(not compile("-Wno-unused-parameter -Werror").empty());
    EXPECT(test::throws([&] { compile("-Werror=unused-parameter"); }));
    EXPECT(test::throws([&] { compile("-Wunused-parameter -Werror"); }));
}

169
170
171
TEST_CASE(code_object_hip)
{
    auto binaries = migraphx::gpu::compile_hip_src(
172
        {make_src_file("main.cpp", add_2s_binary)}, "", migraphx::gpu::get_device_name());
173
174
    EXPECT(binaries.size() == 1);

175
    migraphx::shape input{migraphx::shape::int8_type, {5}};
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190

    std::vector<migraphx::shape> expected_inputs = {input, input};
    auto co                                      = migraphx::make_op("gpu::code_object",
                                {{"code_object", migraphx::value::binary{binaries.front()}},
                                 {"symbol_name", "add_2"},
                                 {"global", input.elements()},
                                 {"local", 1024},
                                 {"expected_inputs", migraphx::to_value(expected_inputs)},
                                 {"output", migraphx::to_value(input)}});

    migraphx::program p;
    auto* mm            = p.get_main_module();
    auto input_literal  = migraphx::generate_literal(input);
    auto output_literal = migraphx::transform(input_literal, [](auto x) { return x + 2; });
    auto x              = mm->add_literal(input_literal);
191
    auto y              = mm->add_parameter("output", input);
192
193
194
195
    mm->add_instruction(co, x, y);
    migraphx::compile_options options;
    p.compile(migraphx::gpu::target{}, options);

196
197
    auto result =
        migraphx::gpu::from_gpu(p.eval({{"output", migraphx::gpu::allocate_gpu(input)}}).front());
198
199
200
201

    EXPECT(result == output_literal.get_argument());
}

202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
TEST_CASE(compile_code_object_hip)
{
    migraphx::shape input{migraphx::shape::float_type, {5, 2}};
    migraphx::gpu::hip_compile_options options;
    options.global = 256 * 1024;
    options.local  = 1024;
    options.inputs = {input, input};
    options.output = input;

    auto co = migraphx::gpu::compile_hip_code_object(simple_pointwise_increment, options);

    migraphx::program p;
    auto* mm            = p.get_main_module();
    auto input_literal  = migraphx::generate_literal(input);
    auto output_literal = migraphx::transform(input_literal, [](auto x) { return x + 1; });
    auto x              = mm->add_literal(input_literal);
218
    auto y              = mm->add_parameter("output", input);
219
220
221
    mm->add_instruction(co, x, y);
    p.compile(migraphx::gpu::target{}, migraphx::compile_options{});

222
223
    auto result =
        migraphx::gpu::from_gpu(p.eval({{"output", migraphx::gpu::allocate_gpu(input)}}).front());
224
225
226
227

    EXPECT(result == output_literal.get_argument());
}

228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
TEST_CASE(compile_pointwise)
{
    migraphx::shape input{migraphx::shape::float_type, {5, 2}};

    migraphx::gpu::context ctx;
    auto co = migraphx::gpu::compile_pointwise(ctx, {input, input}, "[](auto x) { return x + 1; }");

    migraphx::program p;
    auto* mm            = p.get_main_module();
    auto input_literal  = migraphx::generate_literal(input);
    auto output_literal = migraphx::transform(input_literal, [](auto x) { return x + 1; });
    auto x              = mm->add_literal(input_literal);
    auto y              = mm->add_parameter("output", input);
    mm->add_instruction(co, x, y);
    p.compile(migraphx::gpu::target{}, migraphx::compile_options{});

    auto result =
        migraphx::gpu::from_gpu(p.eval({{"output", migraphx::gpu::allocate_gpu(input)}}).front());

    EXPECT(result == output_literal.get_argument());
}

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