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

Last change on this file since 65d1d04 was 65d1d04, checked in by wojciech, 7 years ago

Minor code changes to make pylint happy

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