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

Last change on this file since 58b107f was 58b107f, checked in by wojciech, 8 years ago

Font changed so it looks better on Windows

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