98228ace61197df50d246482871f0247bdce7fbc
[platform/upstream/dldt.git] / inference-engine / thirdparty / clDNN / src / gpu / ocl_builder.cpp
1 /*
2 // Copyright (c) 2018 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 ///////////////////////////////////////////////////////////////////////////////////////////////////
18 #include "ocl_builder.h"
19 #include "configuration.h"
20 #include "include/to_string_utils.h"
21 #include <string>
22 #include <vector>
23 #include <list>
24 #include <utility>
25
26 // NOTE: Due to buggy scope transition of warnings we need to disable warning in place of use/instantation
27 //       of some types (even though we already disabled them in scope of definition of these types).
28 //       Moreover this warning is pretty much now only for annoyance: it is generated due to lack
29 //       of proper support for mangling of custom GCC attributes into type name (usually when used
30 //       with templates, even from standard library).
31 #if defined __GNUC__ && __GNUC__ >= 6
32 #pragma GCC diagnostic ignored "-Wignored-attributes"
33 #endif
34
35 namespace cldnn {
36 namespace gpu {
37 static constexpr auto INTEL_PLATFORM_VENDOR = "Intel(R) Corporation";
38
39 std::map<std::string, device_impl::ptr> ocl_builder::get_available_devices(void* user_context, void* user_device) const {
40     bool host_out_of_order = true;  // Change to false, if debug requires in-order queue.
41     if (user_context != nullptr) {
42         return build_device_list_from_user_context(host_out_of_order, user_context);
43     } else if (user_device != nullptr) {
44         return build_device_list_from_user_device(host_out_of_order, user_device);
45     } else {
46         return build_device_list(host_out_of_order);
47     }
48 }
49
50 std::map<std::string, device_impl::ptr> ocl_builder::build_device_list(bool out_out_order) const {
51     cl_uint n = 0;
52     // Get number of platforms availible
53     cl_int err = clGetPlatformIDs(0, NULL, &n);
54     if (err != CL_SUCCESS) {
55         throw std::runtime_error("[CLDNN ERROR]. clGetPlatformIDs error " + std::to_string(err));
56     }
57
58     // Get platform list
59     std::vector<cl_platform_id> platform_ids(n);
60     err = clGetPlatformIDs(n, platform_ids.data(), NULL);
61     if (err != CL_SUCCESS) {
62         throw std::runtime_error("[CLDNN ERROR]. clGetPlatformIDs error " + std::to_string(err));
63     }
64
65     uint32_t idx = 0;
66     std::map<std::string, device_impl::ptr> ret;
67     for (auto& id : platform_ids) {
68         cl::Platform platform = cl::Platform(id);
69
70         if (platform.getInfo<CL_PLATFORM_VENDOR>() != INTEL_PLATFORM_VENDOR)
71             continue;
72
73         std::vector<cl::Device> devices;
74         platform.getDevices(CL_DEVICE_TYPE_ALL, &devices);
75         for (auto& device : devices) {
76             if (!does_device_match_config(out_out_order, device)) continue;
77             ret.insert(get_device(idx++, device, id));
78         }
79     }
80     if (ret.empty()) {
81         throw std::runtime_error("[CLDNN ERROR]. No GPU device was found.");
82     }
83     return ret;
84 }
85
86 std::map<std::string, device_impl::ptr>  ocl_builder::build_device_list_from_user_context(bool out_out_order, void* user_context) const {
87     cl::Context ctx = cl::Context(static_cast<cl_context>(user_context), true);
88     auto all_devices = ctx.getInfo<CL_CONTEXT_DEVICES>();
89
90     std::map<std::string, device_impl::ptr> ret;
91     uint32_t idx = 0;
92     for (auto& device : all_devices) {
93         if (!does_device_match_config(out_out_order, device)) continue;
94         ret.insert(get_device(idx++, device, device.getInfo<CL_DEVICE_PLATFORM>()));
95     }
96
97     if (ret.empty()) {
98         throw std::runtime_error("[CLDNN ERROR]. User defined context does not have GPU device included!");
99     }
100     return ret;
101 }
102
103 std::map<std::string, device_impl::ptr>  ocl_builder::build_device_list_from_user_device(bool out_out_order, void* user_device) const {
104     cl_uint n = 0;
105     // Get number of platforms availible
106     cl_int err = clGetPlatformIDs(0, NULL, &n);
107     if (err != CL_SUCCESS) {
108         throw std::runtime_error("[CLDNN ERROR]. clGetPlatformIDs error " + std::to_string(err));
109     }
110
111     // Get platform list
112     std::vector<cl_platform_id> platform_ids(n);
113     err = clGetPlatformIDs(n, platform_ids.data(), NULL);
114     if (err != CL_SUCCESS) {
115         throw std::runtime_error("[CLDNN ERROR]. clGetPlatformIDs error " + std::to_string(err));
116     }
117
118     uint32_t idx = 0;
119     std::map<std::string, device_impl::ptr> ret;
120     for (auto& id : platform_ids) {
121         cl::PlatformVA platform = cl::PlatformVA(id);
122
123         if (platform.getInfo<CL_PLATFORM_VENDOR>() != INTEL_PLATFORM_VENDOR)
124             continue;
125
126         std::vector<cl::Device> devices;
127 #ifdef WIN32
128         platform.getDevices(CL_D3D11_DEVICE_KHR,
129             user_device,
130             CL_PREFERRED_DEVICES_FOR_D3D11_KHR,
131 #else
132         platform.getDevices(CL_VA_API_DISPLAY_INTEL,
133             user_device,
134             CL_PREFERRED_DEVICES_FOR_VA_API_INTEL,
135 #endif
136             &devices);
137
138         for (auto& device : devices) {
139             if (!does_device_match_config(out_out_order, device)) continue;
140             ret.insert(get_device_shared(idx++, device, id, user_device));
141         }
142     }
143     if (ret.empty()) {
144         throw std::runtime_error("[CLDNN ERROR]. No corresponding GPU device was found.");
145     }
146     return ret;
147 }
148
149 std::pair<std::string, device_impl::ptr> ocl_builder::get_device(const uint32_t index,
150                                                                  const cl::Device& dev_to_add,
151                                                                  const cl_platform_id platform) const {
152     return {
153         std::to_string(index),
154         device_impl::ptr{ new device_impl(dev_to_add, cl::Context(dev_to_add), platform, device_info_internal(dev_to_add)),
155         false}
156     };
157 }
158
159 std::pair<std::string, device_impl::ptr> ocl_builder::get_device_shared(const uint32_t index,
160                                                                         const cl::Device& dev_to_add,
161                                                                         const cl_platform_id platform,
162                                                                         void* user_device) const {
163     cl_context_properties props[] = {
164 #ifdef WIN32
165         CL_CONTEXT_D3D11_DEVICE_KHR,
166 #else
167         CL_CONTEXT_VA_API_DISPLAY_INTEL,
168 #endif
169         (intptr_t)user_device,
170         CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE,
171         CL_CONTEXT_PLATFORM, (cl_context_properties)platform,
172         0 };
173
174     return {
175         std::to_string(index),
176         device_impl::ptr{ new device_impl(dev_to_add, cl::Context(dev_to_add, props), platform, device_info_internal(dev_to_add)),
177         false }
178     };
179 }
180
181 bool ocl_builder::does_device_match_config(bool out_of_order, const cl::Device& device) const {
182     // Is it intel gpu
183     if (device.getInfo<CL_DEVICE_TYPE>() != device_type ||
184         device.getInfo<CL_DEVICE_VENDOR_ID>() != device_vendor) {
185         return false;
186     }
187
188     // Does device support OOOQ?
189     if (out_of_order) {
190         auto queue_properties = device.getInfo<CL_DEVICE_QUEUE_PROPERTIES>();
191         using cmp_t = std::common_type<decltype(queue_properties),
192             typename std::underlying_type<cl::QueueProperties>::type>::type;
193         if (!(static_cast<cmp_t>(queue_properties) & static_cast<cmp_t>(cl::QueueProperties::OutOfOrder))) {
194             return false;
195         }
196     }
197
198     return true;
199 }
200
201 }  // namespace gpu
202 }  // namespace cldnn