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

Last change on this file since 55b935e was 55b935e, checked in by wojciech, 8 years ago

Code cleanup

  • 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 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        self.panel = wx.Panel(self, -1)
23        self.static_box = wx.StaticBox(self.panel, -1, "OpenCL test completed!")
24        self.boxsizer = wx.BoxSizer(orient=wx.VERTICAL)
25
26        self.text = wx.TextCtrl(self, -1, size=(500, 400),
27                           style=wx.TE_MULTILINE|wx.TE_READONLY
28                                 |wx.SUNKEN_BORDER|wx.HSCROLL)
29        self.text.SetValue(msg)
30        self.text.SetBackgroundColour(self.GetBackgroundColour())
31
32        self.boxsizer.Add(self.text, proportion=1, flag=wx.EXPAND)
33
34        self.fit_hsizer = wx.StaticBoxSizer(self.static_box, orient=wx.VERTICAL)
35        self.fit_hsizer.Add(self.boxsizer, 0, wx.ALL, 5)
36
37        self.panel.SetSizer(self.fit_hsizer)
38
39        self.vbox = wx.BoxSizer(wx.VERTICAL)
40        self.vbox.Add(self.panel, 0, wx.ALL, 10)
41
42        self.message_text = wx.StaticText(self, -1,"If tests fail on OpenCL devices, "
43                                "please select No OpenCL option.\n\n"
44                                "In case of large number of failing tests, "
45                                "please consider sending above\n"
46                                "report to help@sasview.org.")
47
48        self.message_text.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.NORMAL, 0, ""))
49        self.vbox.Add(self.message_text, 0, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 10)
50
51        self.ok_btn = wx.Button(self, wx.ID_OK)
52
53        self.btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
54        self.btn_sizer.Add((10, 20), 1) # stretchable whitespace
55        self.btn_sizer.Add(self.ok_btn, 0)
56
57        self.vbox.Add(self.btn_sizer, 0, wx.EXPAND|wx.ALL, 10)
58
59        self.SetSizer(self.vbox)
60        self.vbox.Fit(self)
61
62        self.Centre()
63        self.ShowModal()
64        self.Destroy()
65
66
67class GpuOptions(wx.Dialog):
68    """
69    "OpenCL options" Dialog Box
70
71    Provides dialog for setting SAS_OPENCL variable, which defines
72    device choice for OpenCL calculation
73
74    """
75
76    def __init__(self, *args, **kwds):
77
78        kwds["style"] = wx.DEFAULT_DIALOG_STYLE
79        wx.Dialog.__init__(self, *args, **kwds)
80
81        clinfo = self._get_clinfo()
82
83        self.panel1 = wx.Panel(self, -1)
84        static_box1 = wx.StaticBox(self.panel1, -1, "Available OpenCL Options:")
85
86        boxsizer = wx.BoxSizer(orient=wx.VERTICAL)
87        self.option_button = {}
88        self.buttons = []
89        #Check if SAS_OPENCL is already set as enviromental variable
90        self.sas_opencl = os.environ.get("SAS_OPENCL","")
91
92        for clopt in clinfo:
93            button = wx.CheckBox(self.panel1, -1, label=clopt[1], name=clopt[1])
94
95            if clopt != "No OpenCL":
96                self.option_button[clopt[1]] = clopt[0]
97                if self.sas_opencl == clopt[0]:
98                    button.SetValue(1)
99            else:
100                self.option_button[clopt] = "None"
101                if self.sas_opencl.lower() == "none":
102                    button.SetValue(1)
103
104            self.Bind(wx.EVT_CHECKBOX, self.on_check, id=button.GetId())
105            self.buttons.append(button)
106            boxsizer.Add(button, 0, 0)
107
108        fit_hsizer = wx.StaticBoxSizer(static_box1, orient=wx.VERTICAL)
109        fit_hsizer.Add(boxsizer, 0, wx.ALL, 5)
110
111        self.panel1.SetSizer(fit_hsizer)
112
113        self.vbox = wx.BoxSizer(wx.VERTICAL)
114        self.vbox.Add(self.panel1, 0, wx.ALL, 10)
115
116        accept_btn = wx.Button(self, wx.ID_OK)
117        accept_btn.SetToolTipString("Accept new OpenCL settings. This will"
118                                    " override SAS_OPENCL variable if set")
119
120        help_id = wx.NewId()
121        help_btn = wx.Button(self, help_id, 'Help')
122        help_btn.SetToolTipString("Help on the GPU options")
123
124        reset_id = wx.NewId()
125        reset_btn = wx.Button(self, reset_id, 'Reset')
126        reset_btn.SetToolTipString("Restore initial settings")
127
128        test_id = wx.NewId()
129        test_btn = wx.Button(self, test_id, 'Test')
130        test_btn.SetToolTipString("Test if models compile on the given infrastructure")
131
132        self.Bind(wx.EVT_BUTTON, self.on_OK, accept_btn)
133        self.Bind(wx.EVT_BUTTON, self.on_test, test_btn)
134        self.Bind(wx.EVT_BUTTON, self.on_reset, reset_btn)
135        self.Bind(wx.EVT_BUTTON, self.on_help, help_btn)
136
137        test_text = wx.StaticText(self, -1,"WARNING: Running tests can take a few minutes!")
138        test_text.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.NORMAL, 0, ""))
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        try:
166            import pyopencl as cl
167            platforms = cl.get_platforms()
168            p_index = 0
169            for platform in platforms:
170                d_index = 0
171                devices = platform.get_devices()
172                for device in devices:
173                    if len(devices) > 1 and len(platforms) > 1:
174                        combined_index = ":".join([str(p_index),str(d_index)])
175                    elif len(platforms) > 1:
176                        combined_index = str(p_index)
177                    else:
178                        combined_index = str(d_index)
179                    #combined_index = ":".join([str(p_index),str(d_index)]) \
180                    #    if len(platforms) > 1 else str(d_index)
181                    clinfo.append((combined_index, ":".join([platform.name,device.name])))
182                    d_index += 1
183                p_index += 1
184        except ImportError:
185            warnings.warn("pyopencl import failed. Using only CPU computations")
186
187        clinfo.append(("None","No OpenCL"))
188        return clinfo
189
190    def on_check(self, event):
191        """
192        Action triggered when box is selected
193        :param event:
194        :return:
195        """
196        selected_button = event.GetEventObject()
197        for btn in self.buttons:
198            if btn != selected_button:
199                btn.SetValue(0)
200        if selected_button.GetValue():
201            self.sas_opencl = self.option_button[selected_button.Name]
202        else:
203            self.sas_opencl = None
204
205    def on_OK(self, event):
206        """
207        Close window on accpetance
208        """
209        import sasmodels
210        #If statement added to handle Reset
211        if self.sas_opencl:
212            os.environ["SAS_OPENCL"] = self.sas_opencl
213        else:
214            if "SAS_OPENCL" in os.environ:
215                del(os.environ["SAS_OPENCL"])
216
217        #Sasmodels kernelcl doesn't exist when initiated with None
218        try:
219            sasmodels.kernelcl.ENV = None
220        except:
221            #TODO: Need to provide reasonable exception case
222            pass
223
224        #Need to reload sasmodels.core module to account SAS_OPENCL = "None"
225        reload(sasmodels.core)
226        event.Skip()
227
228    def on_reset(self, event):
229        """
230        Close window on accpetance
231        """
232        for btn in self.buttons:
233            btn.SetValue(0)
234
235        self.sas_opencl=None
236
237    def on_test(self, event):
238        """
239        Run sasmodels check from here and report results from
240        """
241        import json
242        import platform
243        import sasmodels
244
245        #The same block of code as for OK but it is needed if we want to have
246        #active response to Test button
247        no_opencl_msg = False
248        if self.sas_opencl:
249            os.environ["SAS_OPENCL"] = self.sas_opencl
250            if self.sas_opencl.lower() == "none":
251                no_opencl_msg = True
252        else:
253            if "SAS_OPENCL" in os.environ:
254                del(os.environ["SAS_OPENCL"])
255
256        #Sasmodels kernelcl doesn't exist when initiated with None
257        try:
258            sasmodels.kernelcl.ENV = None
259        except:
260            #TODO: Need to provide reasonable exception case
261            pass
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/gpu_computations.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.