1 /*******************************************************************************
2 * Copyright 2019-2021 Intel Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *******************************************************************************/
16
17 #include "dnnl_test_common.hpp"
18 #include "gtest/gtest.h"
19
20 #include "oneapi/dnnl/dnnl.h"
21 #include "oneapi/dnnl/dnnl_sycl.hpp"
22
23 #include <memory>
24 #include <CL/cl.h>
25 #include <CL/sycl.hpp>
26
27 using namespace cl::sycl;
28
29 namespace dnnl {
30 class sycl_stream_test : public ::testing::TestWithParam<engine::kind> {
31 protected:
SetUp()32 virtual void SetUp() {
33 if (engine::get_count(engine::kind::cpu) > 0) {
34 cpu_eng = engine(engine::kind::cpu, 0);
35 }
36 if (engine::get_count(engine::kind::gpu) > 0) {
37 gpu_eng = engine(engine::kind::gpu, 0);
38 }
39 }
40
has(engine::kind eng_kind) const41 bool has(engine::kind eng_kind) const {
42 switch (eng_kind) {
43 case engine::kind::cpu: return bool(cpu_eng);
44 case engine::kind::gpu: return bool(gpu_eng);
45 default: assert(!"Not expected");
46 }
47 return false;
48 }
49
get_engine(engine::kind eng_kind) const50 engine get_engine(engine::kind eng_kind) const {
51 switch (eng_kind) {
52 case engine::kind::cpu: return cpu_eng;
53 case engine::kind::gpu: return gpu_eng;
54 default: assert(!"Not expected");
55 }
56 return {};
57 }
58
get_device(engine::kind eng_kind) const59 device get_device(engine::kind eng_kind) const {
60 switch (eng_kind) {
61 case engine::kind::cpu: return sycl_interop::get_device(cpu_eng);
62 case engine::kind::gpu: return sycl_interop::get_device(gpu_eng);
63 default: assert(!"Not expected");
64 }
65 return {};
66 }
67
get_context(engine::kind eng_kind) const68 context get_context(engine::kind eng_kind) const {
69 switch (eng_kind) {
70 case engine::kind::cpu: return sycl_interop::get_context(cpu_eng);
71 case engine::kind::gpu: return sycl_interop::get_context(gpu_eng);
72 default: assert(!"Not expected");
73 }
74 return context();
75 }
76
77 engine cpu_eng;
78 engine gpu_eng;
79 };
80
TEST_P(sycl_stream_test,Create)81 TEST_P(sycl_stream_test, Create) {
82 engine::kind kind = GetParam();
83 SKIP_IF(!has(kind), "Device not found.");
84
85 stream s(get_engine(kind));
86
87 #if DNNL_CPU_RUNTIME != DNNL_RUNTIME_SYCL
88 if (kind == engine::kind::cpu) {
89 EXPECT_ANY_THROW(sycl_interop::get_queue(s));
90 return;
91 }
92 #endif
93 queue sycl_queue = sycl_interop::get_queue(s);
94
95 auto queue_dev = sycl_queue.get_device();
96 auto queue_ctx = sycl_queue.get_context();
97
98 EXPECT_EQ(get_device(kind), queue_dev);
99 EXPECT_EQ(get_context(kind), queue_ctx);
100 }
101
TEST_P(sycl_stream_test,BasicInterop)102 TEST_P(sycl_stream_test, BasicInterop) {
103 engine::kind kind = GetParam();
104 SKIP_IF(!has(kind), "Device not found.");
105
106 #if DNNL_CPU_RUNTIME != DNNL_RUNTIME_SYCL
107 if (kind == engine::kind::cpu) {
108 ::sycl::queue dummy;
109 EXPECT_ANY_THROW(sycl_interop::make_stream(get_engine(kind), dummy));
110 return;
111 }
112 #endif
113 queue interop_queue(get_context(kind), get_device(kind));
114 stream s = sycl_interop::make_stream(get_engine(kind), interop_queue);
115
116 EXPECT_EQ(interop_queue, sycl_interop::get_queue(s));
117 }
118
TEST_P(sycl_stream_test,InteropIncompatibleQueue)119 TEST_P(sycl_stream_test, InteropIncompatibleQueue) {
120 engine::kind kind = GetParam();
121 SKIP_IF(!has(engine::kind::cpu) || !has(engine::kind::gpu),
122 "CPU or GPU device not found.");
123
124 #if DNNL_CPU_RUNTIME != DNNL_RUNTIME_SYCL
125 SKIP_IF(true, "Skip this test for classic CPU runtime");
126 #endif
127
128 auto other_kind = (kind == engine::kind::gpu) ? engine::kind::cpu
129 : engine::kind::gpu;
130 queue interop_queue(get_context(other_kind), get_device(other_kind));
131
132 catch_expected_failures(
133 [&] { sycl_interop::make_stream(get_engine(kind), interop_queue); },
134 true, dnnl_invalid_arguments);
135 }
136
137 // TODO: Enable the test below after sycl_stream_t is fixed to not reuse the
138 // service stream. Now it ignores the input stream flags and reuses the service
139 // stream which is constructed without any flags.
140 #if 0
141 TEST_P(sycl_stream_test, Flags) {
142 engine::kind kind = GetParam();
143 SKIP_IF(!has(kind), "Device not found.");
144
145 stream in_order_stream(get_engine(kind), stream::flags::in_order);
146 auto in_order_queue = sycl_interop::get_queue(in_order_stream);
147 EXPECT_TRUE(in_order_queue.is_in_order());
148
149 stream out_of_order_stream(get_engine(kind), stream::flags::out_of_order);
150 auto out_of_order_queue = sycl_interop::get_queue(out_of_order_stream);
151 EXPECT_TRUE(!out_of_order_queue.is_in_order());
152 }
153 #endif
154
155 namespace {
156 struct PrintToStringParamName {
157 template <class ParamType>
operator ()dnnl::__anon96131d000211::PrintToStringParamName158 std::string operator()(
159 const ::testing::TestParamInfo<ParamType> &info) const {
160 switch (info.param) {
161 case engine::kind::cpu: return "cpu";
162 case engine::kind::gpu: return "gpu";
163 default: assert(!"Not expected");
164 }
165 return {};
166 }
167 };
168 } // namespace
169
170 INSTANTIATE_TEST_SUITE_P(AllEngineKinds, sycl_stream_test,
171 ::testing::Values(engine::kind::cpu, engine::kind::gpu),
172 PrintToStringParamName());
173
174 } // namespace dnnl
175