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