|
22 | 22 | #include <cstring>
|
23 | 23 | #include <iostream>
|
24 | 24 | #include <map>
|
| 25 | +#include <sstream> |
25 | 26 | #include <stddef.h>
|
26 | 27 | #include <string>
|
27 |
| -#include <sstream> |
28 | 28 |
|
29 | 29 | #ifdef XPTI_ENABLE_INSTRUMENTATION
|
30 | 30 | // Include the headers necessary for emitting
|
@@ -141,39 +141,80 @@ std::string memFlagsToString(pi_mem_flags Flags) {
|
141 | 141 | return Sstream.str();
|
142 | 142 | }
|
143 | 143 |
|
144 |
| -// Check for manually selected BE at run-time. |
145 |
| -static Backend getBackend() { |
146 |
| - static const char *GetEnv = std::getenv("SYCL_BE"); |
147 |
| - // Current default backend as SYCL_BE_PI_OPENCL |
148 |
| - // Valid values of GetEnv are "PI_OPENCL", "PI_CUDA" and "PI_OTHER" |
149 |
| - std::string StringGetEnv = (GetEnv ? GetEnv : "PI_OPENCL"); |
150 |
| - static const Backend Use = |
151 |
| - std::map<std::string, Backend>{ |
152 |
| - { "PI_OPENCL", SYCL_BE_PI_OPENCL }, |
153 |
| - { "PI_CUDA", SYCL_BE_PI_CUDA }, |
154 |
| - { "PI_OTHER", SYCL_BE_PI_OTHER } |
155 |
| - }[ GetEnv ? StringGetEnv : "PI_OPENCL"]; |
156 |
| - return Use; |
| 144 | +// A singleton class to aid that PI configuration parameters |
| 145 | +// are processed only once, like reading a string from environment |
| 146 | +// and converting it into a typed object. |
| 147 | +// |
| 148 | +template <typename T, const char *E> class Config { |
| 149 | + static Config *m_Instance; |
| 150 | + T m_Data; |
| 151 | + Config(); |
| 152 | + |
| 153 | +public: |
| 154 | + static T get() { |
| 155 | + if (!m_Instance) { |
| 156 | + m_Instance = new Config(); |
| 157 | + } |
| 158 | + return m_Instance->m_Data; |
| 159 | + } |
| 160 | +}; |
| 161 | + |
| 162 | +template <typename T, const char *E> |
| 163 | +Config<T, E> *Config<T, E>::m_Instance = nullptr; |
| 164 | + |
| 165 | +// Lists valid configuration environment variables. |
| 166 | +static constexpr char SYCL_BE[] = "SYCL_BE"; |
| 167 | +static constexpr char SYCL_INTEROP_BE[] = "SYCL_INTEROP_BE"; |
| 168 | +static constexpr char SYCL_PI_TRACE[] = "SYCL_PI_TRACE"; |
| 169 | + |
| 170 | +// SYCL_PI_TRACE gives the mask of enabled tracing components (0 default) |
| 171 | +template <> Config<int, SYCL_PI_TRACE>::Config() { |
| 172 | + const char *Env = std::getenv(SYCL_PI_TRACE); |
| 173 | + m_Data = (Env ? std::atoi(Env) : 0); |
| 174 | +} |
| 175 | + |
| 176 | +static Backend getBE(const char *EnvVar) { |
| 177 | + const char *BE = std::getenv(EnvVar); |
| 178 | + const std::map<std::string, Backend> SyclBeMap{ |
| 179 | + {"PI_OTHER", SYCL_BE_PI_OTHER}, |
| 180 | + {"PI_CUDA", SYCL_BE_PI_CUDA}, |
| 181 | + {"PI_OPENCL", SYCL_BE_PI_OPENCL}}; |
| 182 | + if (BE) { |
| 183 | + auto It = SyclBeMap.find(BE); |
| 184 | + if (It == SyclBeMap.end()) |
| 185 | + pi::die("Invalid backend. " |
| 186 | + "Valid values are PI_OPENCL/PI_CUDA"); |
| 187 | + return It->second; |
| 188 | + } |
| 189 | + // Default backend |
| 190 | + return SYCL_BE_PI_OPENCL; |
157 | 191 | }
|
158 | 192 |
|
159 |
| -// Check for manually selected BE at run-time. |
160 |
| -bool useBackend(Backend TheBackend) { |
161 |
| - return TheBackend == getBackend(); |
| 193 | +template <> Config<Backend, SYCL_BE>::Config() { m_Data = getBE(SYCL_BE); } |
| 194 | + |
| 195 | +// SYCL_INTEROP_BE is a way to specify the interoperability plugin. |
| 196 | +template <> Config<Backend, SYCL_INTEROP_BE>::Config() { |
| 197 | + m_Data = getBE(SYCL_INTEROP_BE); |
162 | 198 | }
|
163 | 199 |
|
| 200 | +// Helper interface to not expose "pi::Config" outside of pi.cpp |
| 201 | +Backend getPreferredBE() { return Config<Backend, SYCL_BE>::get(); } |
| 202 | + |
164 | 203 | // GlobalPlugin is a global Plugin used with Interoperability constructors that
|
165 | 204 | // use OpenCL objects to construct SYCL class objects.
|
166 | 205 | std::shared_ptr<plugin> GlobalPlugin;
|
167 | 206 |
|
168 | 207 | // Find the plugin at the appropriate location and return the location.
|
169 |
| -// TODO: Change the function appropriately when there are multiple plugins. |
170 |
| -bool findPlugins(vector_class<std::string> &PluginNames) { |
| 208 | +bool findPlugins(vector_class<std::pair<std::string, Backend>> &PluginNames) { |
171 | 209 | // TODO: Based on final design discussions, change the location where the
|
172 | 210 | // plugin must be searched; how to identify the plugins etc. Currently the
|
173 | 211 | // search is done for libpi_opencl.so/pi_opencl.dll file in LD_LIBRARY_PATH
|
174 | 212 | // env only.
|
175 |
| - PluginNames.push_back(OPENCL_PLUGIN_NAME); |
176 |
| - PluginNames.push_back(CUDA_PLUGIN_NAME); |
| 213 | + // |
| 214 | + PluginNames.push_back(std::make_pair<std::string, Backend>( |
| 215 | + OPENCL_PLUGIN_NAME, SYCL_BE_PI_OPENCL)); |
| 216 | + PluginNames.push_back( |
| 217 | + std::make_pair<std::string, Backend>(CUDA_PLUGIN_NAME, SYCL_BE_PI_CUDA)); |
177 | 218 | return true;
|
178 | 219 | }
|
179 | 220 |
|
@@ -207,52 +248,51 @@ bool bindPlugin(void *Library, PiPlugin *PluginInformation) {
|
207 | 248 | return true;
|
208 | 249 | }
|
209 | 250 |
|
210 |
| -// Load the plugin based on SYCL_BE. |
211 |
| -// TODO: Currently only accepting OpenCL and CUDA plugins. Edit it to identify |
212 |
| -// and load other kinds of plugins, do the required changes in the |
213 |
| -// findPlugins, loadPlugin and bindPlugin functions. |
| 251 | +bool trace(TraceLevel Level) { |
| 252 | + auto TraceLevelMask = Config<int, SYCL_PI_TRACE>::get(); |
| 253 | + return (TraceLevelMask & Level) == Level; |
| 254 | +} |
| 255 | + |
| 256 | +// Initializes all available Plugins. |
214 | 257 | vector_class<plugin> initialize() {
|
215 | 258 | vector_class<plugin> Plugins;
|
216 |
| - |
217 |
| - if (!useBackend(SYCL_BE_PI_OPENCL) && !useBackend(SYCL_BE_PI_CUDA)) { |
218 |
| - die("Unknown SYCL_BE"); |
219 |
| - } |
220 |
| - |
221 |
| - bool EnableTrace = (std::getenv("SYCL_PI_TRACE") != nullptr); |
222 |
| - |
223 |
| - vector_class<std::string> PluginNames; |
| 259 | + vector_class<std::pair<std::string, Backend>> PluginNames; |
224 | 260 | findPlugins(PluginNames);
|
225 | 261 |
|
226 |
| - if (PluginNames.empty() && EnableTrace) |
227 |
| - std::cerr << "No Plugins Found." << std::endl; |
| 262 | + if (PluginNames.empty() && trace(PI_TRACE_ALL)) |
| 263 | + std::cerr << "SYCL_PI_TRACE[-1]: No Plugins Found." << std::endl; |
228 | 264 |
|
229 |
| - PiPlugin PluginInformation; // TODO: include. |
| 265 | + PiPlugin PluginInformation; |
230 | 266 | for (unsigned int I = 0; I < PluginNames.size(); I++) {
|
231 |
| - void *Library = loadPlugin(PluginNames[I]); |
| 267 | + void *Library = loadPlugin(PluginNames[I].first); |
232 | 268 |
|
233 | 269 | if (!Library) {
|
234 |
| - if (EnableTrace) { |
235 |
| - std::cerr << "Check if plugin is present. Failed to load plugin: " |
236 |
| - << PluginNames[I] << std::endl; |
| 270 | + if (trace(PI_TRACE_ALL)) { |
| 271 | + std::cerr << "SYCL_PI_TRACE[-1]: Check if plugin is present. " |
| 272 | + << "Failed to load plugin: " << PluginNames[I].first |
| 273 | + << std::endl; |
237 | 274 | }
|
238 | 275 | continue;
|
239 | 276 | }
|
240 | 277 |
|
241 |
| - if (!bindPlugin(Library, &PluginInformation) && EnableTrace) { |
242 |
| - std::cerr << "Failed to bind PI APIs to the plugin: " << PluginNames[I] |
243 |
| - << std::endl; |
244 |
| - } |
245 |
| - if (useBackend(SYCL_BE_PI_OPENCL) && |
246 |
| - PluginNames[I].find("opencl") != std::string::npos) { |
247 |
| - // Use the OpenCL plugin as the GlobalPlugin |
248 |
| - GlobalPlugin = std::make_shared<plugin>(PluginInformation); |
| 278 | + if (!bindPlugin(Library, &PluginInformation)) { |
| 279 | + if (trace(PI_TRACE_ALL)) { |
| 280 | + std::cerr << "SYCL_PI_TRACE[-1]: Failed to bind PI APIs to the plugin: " |
| 281 | + << PluginNames[I].first << std::endl; |
| 282 | + } |
| 283 | + continue; |
249 | 284 | }
|
250 |
| - if (useBackend(SYCL_BE_PI_CUDA) && |
251 |
| - PluginNames[I].find("cuda") != std::string::npos) { |
252 |
| - // Use the CUDA plugin as the GlobalPlugin |
253 |
| - GlobalPlugin = std::make_shared<plugin>(PluginInformation); |
| 285 | + // Set the Global Plugin based on SYCL_INTEROP_BE. |
| 286 | + // Rework this when it will be explicit in the code which BE is used in the |
| 287 | + // interoperability methods. |
| 288 | + if (Config<Backend, SYCL_INTEROP_BE>::get() == PluginNames[I].second) { |
| 289 | + GlobalPlugin = |
| 290 | + std::make_shared<plugin>(PluginInformation, PluginNames[I].second); |
254 | 291 | }
|
255 |
| - Plugins.push_back(plugin(PluginInformation)); |
| 292 | + Plugins.emplace_back(plugin(PluginInformation, PluginNames[I].second)); |
| 293 | + if (trace(TraceLevel::PI_TRACE_BASIC)) |
| 294 | + std::cerr << "SYCL_PI_TRACE[1]: Plugin found and successfully loaded: " |
| 295 | + << PluginNames[I].first << std::endl; |
256 | 296 | }
|
257 | 297 |
|
258 | 298 | #ifdef XPTI_ENABLE_INSTRUMENTATION
|
|
0 commit comments