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

Last change on this file since 755ecb0 was 755ecb0, checked in by wojciech, 7 years ago

and fixing line

  • 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 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)
29        self.text.SetValue(msg)
30        self.text.SetBackgroundColour(self.GetBackgroundColour())
31        self.text.SetFocus()
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\n"
46                                "above report to help@sasview.org.")
47
48        self.vbox.Add(self.message_text, 0, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 10)
49
50        self.ok_btn = wx.Button(self, wx.ID_OK)
51
52        self.btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
53        self.btn_sizer.Add((10, 20), 1) # stretchable whitespace
54        self.btn_sizer.Add(self.ok_btn, 0)
55
56        self.vbox.Add(self.btn_sizer, 0, wx.EXPAND|wx.ALL, 10)
57
58        self.SetSizer(self.vbox)
59        self.vbox.Fit(self)
60
61        self.SetAutoLayout(True)
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        self.vbox.Add(test_text, 0, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 10)
138
139        btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
140        btn_sizer.Add((10, 20), 1) # stretchable whitespace
141        btn_sizer.Add(accept_btn, 0)
142        btn_sizer.Add((10, 20), 0) # non-stretchable whitespace
143        btn_sizer.Add(test_btn, 0)
144        btn_sizer.Add((10, 20), 0) # non-stretchable whitespace
145        btn_sizer.Add(reset_btn, 0)
146        btn_sizer.Add((10, 20), 0) # non-stretchable whitespace
147        btn_sizer.Add(help_btn, 0)
148
149        # Add the button sizer to the main sizer.
150        self.vbox.Add(btn_sizer, 0, wx.EXPAND|wx.ALL, 10)
151
152        self.SetSizer(self.vbox)
153        self.vbox.Fit(self)
154        self.SetTitle("OpenCL options")
155        self.Centre()
156
157    def _get_clinfo(self):
158        """
159        Reading in information about available OpenCL infrastructure
160        :return:
161        """
162        clinfo = []
163        try:
164            import pyopencl as cl
165            platforms = cl.get_platforms()
166            p_index = 0
167            for platform in platforms:
168                d_index = 0
169                devices = platform.get_devices()
170                for device in devices:
171                    if len(devices) > 1 and len(platforms) > 1:
172                        combined_index = ":".join([str(p_index),str(d_index)])
173                    elif len(platforms) > 1:
174                        combined_index = str(p_index)
175                    else:
176                        combined_index = str(d_index)
177                    #combined_index = ":".join([str(p_index),str(d_index)]) \
178                    #    if len(platforms) > 1 else str(d_index)
179                    clinfo.append((combined_index, ":".join([platform.name,device.name])))
180                    d_index += 1
181                p_index += 1
182        except ImportError:
183            warnings.warn("pyopencl import failed. Using only CPU computations")
184
185        clinfo.append(("None","No OpenCL"))
186        return clinfo
187
188    def on_check(self, event):
189        """
190        Action triggered when box is selected
191        :param event:
192        :return:
193        """
194        selected_button = event.GetEventObject()
195        for btn in self.buttons:
196            if btn != selected_button:
197                btn.SetValue(0)
198        if selected_button.GetValue():
199            self.sas_opencl = self.option_button[selected_button.Name]
200        else:
201            self.sas_opencl = None
202
203    def on_OK(self, event):
204        """
205        Close window on accpetance
206        """
207        import sasmodels
208        #If statement added to handle Reset
209        if self.sas_opencl:
210            os.environ["SAS_OPENCL"] = self.sas_opencl
211        else:
212            if "SAS_OPENCL" in os.environ:
213                del(os.environ["SAS_OPENCL"])
214
215        #Sasmodels kernelcl doesn't exist when initiated with None
216        try:
217            sasmodels.kernelcl.ENV = None
218        except:
219            #TODO: Need to provide reasonable exception case
220            pass
221
222        #Need to reload sasmodels.core module to account SAS_OPENCL = "None"
223        reload(sasmodels.core)
224        event.Skip()
225
226    def on_reset(self, event):
227        """
228        Close window on accpetance
229        """
230        for btn in self.buttons:
231            btn.SetValue(0)
232
233        self.sas_opencl=None
234
235    def on_test(self, event):
236        """
237        Run sasmodels check from here and report results from
238        """
239        import json
240        import platform
241        import sasmodels
242
243        #The same block of code as for OK but it is needed if we want to have
244        #active response to Test button
245        no_opencl_msg = False
246        if self.sas_opencl:
247            os.environ["SAS_OPENCL"] = self.sas_opencl
248            if self.sas_opencl.lower() == "none":
249                no_opencl_msg = True
250        else:
251            if "SAS_OPENCL" in os.environ:
252                del(os.environ["SAS_OPENCL"])
253
254        #Sasmodels kernelcl doesn't exist when initiated with None
255        try:
256            sasmodels.kernelcl.ENV = None
257        except:
258            #TODO: Need to provide reasonable exception case
259            pass
260
261        #Need to reload sasmodels.core module to account SAS_OPENCL = "None"
262        reload(sasmodels.core)
263
264
265        from sasmodels.model_test import model_tests
266
267        try:
268            from sasmodels.kernelcl import environment
269            env = environment()
270            clinfo = [(ctx.devices[0].platform.vendor,
271                      ctx.devices[0].platform.version,
272                      ctx.devices[0].vendor,
273                      ctx.devices[0].name,
274                      ctx.devices[0].version)
275                    for ctx in env.context]
276        except ImportError:
277            clinfo = None
278
279        failures = []
280        tests_completed = 0
281        for test in model_tests():
282            try:
283                test()
284            except Exception:
285                failures.append(test.description)
286
287            tests_completed += 1
288
289        info = {
290            'version':  sasmodels.__version__,
291            'platform': platform.uname(),
292            'opencl': clinfo,
293            'failing tests': failures,
294        }
295
296        msg_info = 'OpenCL tests results'
297
298        msg = str(tests_completed)+' tests completed.\n'
299        if len(failures) > 0:
300            msg += str(len(failures))+' tests failed.\n'
301            msg += 'Failing tests: '
302            msg += json.dumps(info['failing tests'])
303            msg +="\n"
304        else:
305            msg+="All tests passed!\n"
306
307        msg +="\nPlatform Details:\n\n"
308        msg += "Sasmodels version: "
309        msg += info['version']+"\n"
310        msg += "\nPlatform used: "
311        msg += json.dumps(info['platform'])+"\n"
312        if no_opencl_msg:
313            msg += "\nOpenCL driver: None"
314        else:
315            msg += "\nOpenCL driver: "
316            msg += json.dumps(info['opencl'])+"\n"
317
318        CustomMessageBox(self.panel1, msg, msg_info)
319
320    def on_help(self, event):
321        """
322        Provide help on opencl options.
323        """
324        TreeLocation = "user/gpu_computations.html"
325        anchor = "#device-selection"
326        DocumentationWindow(self, -1,
327                            TreeLocation, anchor, "OpenCL Options Help")
Note: See TracBrowser for help on using the repository browser.