source: sasview/src/sas/sasgui/perspectives/fitting/gpu_options.py @ 66285f5

magnetic_scattrelease-4.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 66285f5 was 66285f5, checked in by Adam Washington <adam.washington@…>, 6 years ago

Catch OpenCL errors thrown during platform detection.

  • Property mode set to 100644
File size: 10.7 KB
Line 
1'''
2Module provides dialog for setting SAS_OPENCL variable, which defines
3device choice for OpenCL calculation
4
5Created on Nov 29, 2016
6
7@author: wpotrzebowski
8'''
9
10import os
11import sys
12import warnings
13import wx
14import sasmodels
15from sas.sasgui.guiframe.documentation_window import DocumentationWindow
16
17
18
19class CustomMessageBox(wx.Dialog):
20    """
21    Custom message box for OpenCL results
22    """
23    def __init__(self, parent, msg, title):
24
25        wx.Dialog.__init__(self, parent, title=title)
26
27        self.static_box = wx.StaticBox(self, -1, "OpenCL test completed!")
28        self.boxsizer = wx.BoxSizer(orient=wx.VERTICAL)
29
30        self.text = wx.TextCtrl(self, -1, size=(500, 300),
31                                style=wx.TE_MULTILINE|wx.TE_READONLY)
32        self.text.SetValue(msg)
33        self.text.SetBackgroundColour(self.GetBackgroundColour())
34        self.text.SetFocus()
35        self.text.SetInsertionPoint(self.text.GetLastPosition())
36        self.boxsizer.Add(self.text, proportion=1, flag=wx.EXPAND)
37
38        self.fit_hsizer = wx.StaticBoxSizer(self.static_box, orient=wx.VERTICAL)
39        self.fit_hsizer.Add(self.boxsizer, 0, wx.ALL, 5)
40
41        self.vbox = wx.BoxSizer(wx.VERTICAL)
42        self.vbox.Add(self.fit_hsizer, 0, wx.ALL, 10)
43
44        self.message_text = wx.StaticText(self, -1, "If tests fail on OpenCL devices, "
45                                                    "please select No OpenCL option.\n\n"
46                                                    "In case of large number of failing tests, "
47                                                    "please consider sending\n"
48                                                    "above report to help@sasview.org.")
49
50        self.vbox.Add(self.message_text, 0, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 10)
51
52        self.ok_btn = wx.Button(self, wx.ID_OK)
53
54        self.btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
55        self.btn_sizer.Add((10, 20), 1) # stretchable whitespace
56        self.btn_sizer.Add(self.ok_btn, 0)
57
58        self.vbox.Add(self.btn_sizer, 0, wx.EXPAND|wx.ALL, 10)
59
60        self.SetSizer(self.vbox)
61        self.vbox.Fit(self)
62
63        self.SetAutoLayout(True)
64        self.ShowModal()
65        self.Destroy()
66
67
68class GpuOptions(wx.Dialog):
69    """
70    "OpenCL options" Dialog Box
71
72    Provides dialog for setting SAS_OPENCL variable, which defines
73    device choice for OpenCL calculation
74
75    """
76
77    def __init__(self, *args, **kwds):
78
79        kwds["style"] = wx.DEFAULT_DIALOG_STYLE
80        wx.Dialog.__init__(self, *args, **kwds)
81
82        clinfo = self._get_clinfo()
83
84        self.panel1 = wx.Panel(self, -1)
85        static_box1 = wx.StaticBox(self.panel1, -1, "Available OpenCL Options:")
86
87        boxsizer = wx.BoxSizer(orient=wx.VERTICAL)
88        self.option_button = {}
89        self.buttons = []
90        #Check if SAS_OPENCL is already set as environment variable
91        self.sas_opencl = os.environ.get("SAS_OPENCL", "")
92
93        for clopt in clinfo:
94            button = wx.CheckBox(self.panel1, -1, label=clopt[1], name=clopt[1])
95
96            if clopt != "No OpenCL":
97                self.option_button[clopt[1]] = clopt[0]
98                if self.sas_opencl == clopt[0]:
99                    button.SetValue(1)
100            else:
101                self.option_button[clopt] = "None"
102                if self.sas_opencl.lower() == "none":
103                    button.SetValue(1)
104
105            self.Bind(wx.EVT_CHECKBOX, self.on_check, id=button.GetId())
106            self.buttons.append(button)
107            boxsizer.Add(button, 0, 0)
108
109        fit_hsizer = wx.StaticBoxSizer(static_box1, orient=wx.VERTICAL)
110        fit_hsizer.Add(boxsizer, 0, wx.ALL, 5)
111
112        self.panel1.SetSizer(fit_hsizer)
113
114        self.vbox = wx.BoxSizer(wx.VERTICAL)
115        self.vbox.Add(self.panel1, 0, wx.ALL, 10)
116
117        accept_btn = wx.Button(self, wx.ID_OK)
118        accept_btn.SetToolTipString("Accept new OpenCL settings. This will"
119                                    " override SAS_OPENCL variable if set")
120
121        help_id = wx.NewId()
122        help_btn = wx.Button(self, help_id, 'Help')
123        help_btn.SetToolTipString("Help on the GPU options")
124
125        reset_id = wx.NewId()
126        reset_btn = wx.Button(self, reset_id, 'Reset')
127        reset_btn.SetToolTipString("Restore initial settings")
128
129        test_id = wx.NewId()
130        test_btn = wx.Button(self, test_id, 'Test')
131        test_btn.SetToolTipString("Test if models compile on the given infrastructure")
132
133        self.Bind(wx.EVT_BUTTON, self.on_OK, accept_btn)
134        self.Bind(wx.EVT_BUTTON, self.on_test, test_btn)
135        self.Bind(wx.EVT_BUTTON, self.on_reset, reset_btn)
136        self.Bind(wx.EVT_BUTTON, self.on_help, help_btn)
137
138        test_text = wx.StaticText(self, -1, "WARNING: Running tests can take a few minutes!")
139        self.vbox.Add(test_text, 0, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 10)
140
141        btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
142        btn_sizer.Add((10, 20), 1) # stretchable whitespace
143        btn_sizer.Add(accept_btn, 0)
144        btn_sizer.Add((10, 20), 0) # non-stretchable whitespace
145        btn_sizer.Add(test_btn, 0)
146        btn_sizer.Add((10, 20), 0) # non-stretchable whitespace
147        btn_sizer.Add(reset_btn, 0)
148        btn_sizer.Add((10, 20), 0) # non-stretchable whitespace
149        btn_sizer.Add(help_btn, 0)
150
151        # Add the button sizer to the main sizer.
152        self.vbox.Add(btn_sizer, 0, wx.EXPAND|wx.ALL, 10)
153
154        self.SetSizer(self.vbox)
155        self.vbox.Fit(self)
156        self.SetTitle("OpenCL options")
157        self.Centre()
158
159    def _get_clinfo(self):
160        """
161        Reading in information about available OpenCL infrastructure
162        :return:
163        """
164        clinfo = []
165        platforms = []
166        try:
167            import pyopencl as cl
168            platforms = cl.get_platforms()
169        except ImportError:
170            warnings.warn("Unable to import the pyopencl package.  It may not \
171            have been installed.  If you wish to use OpenCL, try running pip \
172            install --user pyopencl")
173        except cl.LogicError as e:
174            warnings.warn("Unable to fetch the OpenCL platforms.  This likely \
175            means that the opencl drivers for your system are not installed.")
176            warnings.warn(e)
177
178        p_index = 0
179        for platform in platforms:
180            d_index = 0
181            devices = platform.get_devices()
182            for device in devices:
183                if len(devices) > 1 and len(platforms) > 1:
184                    combined_index = ":".join([str(p_index), str(d_index)])
185                elif len(platforms) > 1:
186                    combined_index = str(p_index)
187                else:
188                    combined_index = str(d_index)
189                clinfo.append((combined_index, ":".join([platform.name, device.name])))
190                d_index += 1
191            p_index += 1
192
193        clinfo.append(("None", "No OpenCL"))
194        return clinfo
195
196    def on_check(self, event):
197        """
198        Action triggered when box is selected
199        :param event:
200        :return:
201        """
202        selected_button = event.GetEventObject()
203        for btn in self.buttons:
204            if btn != selected_button:
205                btn.SetValue(0)
206        if selected_button.GetValue():
207            self.sas_opencl = self.option_button[selected_button.Name]
208        else:
209            self.sas_opencl = None
210
211    def on_OK(self, event):
212        """
213        Close window on accpetance
214        """
215
216        #If statement added to handle Reset
217        if self.sas_opencl:
218            os.environ["SAS_OPENCL"] = self.sas_opencl
219        else:
220            if "SAS_OPENCL" in os.environ:
221                del os.environ["SAS_OPENCL"]
222
223        #Sasmodels kernelcl doesn't exist when initiated with None
224        if 'sasmodels.kernelcl' in sys.modules:
225            sasmodels.kernelcl.ENV = None
226
227        reload(sasmodels.core)
228        event.Skip()
229
230    def on_reset(self, event):
231        """
232        Resets selected values
233        """
234        for btn in self.buttons:
235            btn.SetValue(0)
236
237        self.sas_opencl = None
238
239    def on_test(self, event):
240        """
241        Run sasmodels check from here and report results from
242        """
243        import json
244        import platform
245        #import sasmodels
246
247        #The same block of code as for OK but it is needed if we want to have
248        #active response to Test button
249        no_opencl_msg = False
250        if self.sas_opencl:
251            os.environ["SAS_OPENCL"] = self.sas_opencl
252            if self.sas_opencl.lower() == "none":
253                no_opencl_msg = True
254        else:
255            if "SAS_OPENCL" in os.environ:
256                del os.environ["SAS_OPENCL"]
257
258        #Sasmodels kernelcl doesn't exist when initiated with None
259        if 'sasmodels.kernelcl' in sys.modules:
260            sasmodels.kernelcl.ENV = None
261
262
263        #Need to reload sasmodels.core module to account SAS_OPENCL = "None"
264        reload(sasmodels.core)
265
266
267        from sasmodels.model_test import model_tests
268
269        try:
270            from sasmodels.kernelcl import environment
271            env = environment()
272            clinfo = [(ctx.devices[0].platform.vendor,
273                       ctx.devices[0].platform.version,
274                       ctx.devices[0].vendor,
275                       ctx.devices[0].name,
276                       ctx.devices[0].version)
277                      for ctx in env.context]
278        except ImportError:
279            clinfo = None
280
281        failures = []
282        tests_completed = 0
283        for test in model_tests():
284            try:
285                test()
286            except Exception:
287                failures.append(test.description)
288
289            tests_completed += 1
290
291        info = {
292            'version':  sasmodels.__version__,
293            'platform': platform.uname(),
294            'opencl': clinfo,
295            'failing tests': failures,
296        }
297
298        msg_info = 'OpenCL tests results'
299
300        msg = str(tests_completed)+' tests completed.\n'
301        if len(failures) > 0:
302            msg += str(len(failures))+' tests failed.\n'
303            msg += 'Failing tests: '
304            msg += json.dumps(info['failing tests'])
305            msg += "\n"
306        else:
307            msg += "All tests passed!\n"
308
309        msg += "\nPlatform Details:\n\n"
310        msg += "Sasmodels version: "
311        msg += info['version']+"\n"
312        msg += "\nPlatform used: "
313        msg += json.dumps(info['platform'])+"\n"
314        if no_opencl_msg:
315            msg += "\nOpenCL driver: None"
316        else:
317            msg += "\nOpenCL driver: "
318            msg += json.dumps(info['opencl'])+"\n"
319
320        CustomMessageBox(self.panel1, msg, msg_info)
321
322    def on_help(self, event):
323        """
324        Provide help on opencl options.
325        """
326        TreeLocation = "user/sasgui/perspectives/fitting/gpu_setup.html"
327        anchor = "#device-selection"
328        DocumentationWindow(self, -1,
329                            TreeLocation, anchor, "OpenCL Options Help")
Note: See TracBrowser for help on using the repository browser.