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

ticket-1094-headless
Last change on this file since 3388337 was 42a6e02, checked in by Adam Washington <adam.washington@…>, 7 years ago

Improve logging messages

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