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

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

making conditional check for kernelcl module

  • 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    def __init__(self, parent, msg, title):
20
21        wx.Dialog.__init__(self, parent, title=title)
22
23        self.panel = wx.Panel(self, -1)
24        self.static_box = wx.StaticBox(self.panel, -1, "OpenCL test completed!")
25        self.boxsizer = wx.BoxSizer(orient=wx.VERTICAL)
26
27        self.text = wx.TextCtrl(self, -1, size=(500, 400),
28                           style=wx.TE_MULTILINE|wx.TE_READONLY)
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        if 'sasmodels.kernelcl' in sys.modules:
217            sasmodels.kernelcl.ENV = None
218
219        reload(sasmodels.core)
220        event.Skip()
221
222    def on_reset(self, event):
223        """
224        Close window on accpetance
225        """
226        for btn in self.buttons:
227            btn.SetValue(0)
228
229        self.sas_opencl=None
230
231    def on_test(self, event):
232        """
233        Run sasmodels check from here and report results from
234        """
235        import json
236        import platform
237        import sasmodels
238
239        #The same block of code as for OK but it is needed if we want to have
240        #active response to Test button
241        no_opencl_msg = False
242        if self.sas_opencl:
243            os.environ["SAS_OPENCL"] = self.sas_opencl
244            if self.sas_opencl.lower() == "none":
245                no_opencl_msg = True
246        else:
247            if "SAS_OPENCL" in os.environ:
248                del(os.environ["SAS_OPENCL"])
249
250        #Sasmodels kernelcl doesn't exist when initiated with None
251        if 'sasmodels.kernelcl' in sys.modules:
252            sasmodels.kernelcl.ENV = None
253
254
255        #Need to reload sasmodels.core module to account SAS_OPENCL = "None"
256        reload(sasmodels.core)
257
258
259        from sasmodels.model_test import model_tests
260
261        try:
262            from sasmodels.kernelcl import environment
263            env = environment()
264            clinfo = [(ctx.devices[0].platform.vendor,
265                      ctx.devices[0].platform.version,
266                      ctx.devices[0].vendor,
267                      ctx.devices[0].name,
268                      ctx.devices[0].version)
269                    for ctx in env.context]
270        except ImportError:
271            clinfo = None
272
273        failures = []
274        tests_completed = 0
275        for test in model_tests():
276            try:
277                test()
278            except Exception:
279                failures.append(test.description)
280
281            tests_completed += 1
282
283        info = {
284            'version':  sasmodels.__version__,
285            'platform': platform.uname(),
286            'opencl': clinfo,
287            'failing tests': failures,
288        }
289
290        msg_info = 'OpenCL tests results'
291
292        msg = str(tests_completed)+' tests completed.\n'
293        if len(failures) > 0:
294            msg += str(len(failures))+' tests failed.\n'
295            msg += 'Failing tests: '
296            msg += json.dumps(info['failing tests'])
297            msg +="\n"
298        else:
299            msg+="All tests passed!\n"
300
301        msg +="\nPlatform Details:\n\n"
302        msg += "Sasmodels version: "
303        msg += info['version']+"\n"
304        msg += "\nPlatform used: "
305        msg += json.dumps(info['platform'])+"\n"
306        if no_opencl_msg:
307            msg += "\nOpenCL driver: None"
308        else:
309            msg += "\nOpenCL driver: "
310            msg += json.dumps(info['opencl'])+"\n"
311
312        CustomMessageBox(self.panel1, msg, msg_info)
313
314    def on_help(self, event):
315        """
316        Provide help on opencl options.
317        """
318        TreeLocation = "user/gpu_computations.html"
319        anchor = "#device-selection"
320        DocumentationWindow(self, -1,
321                            TreeLocation, anchor, "OpenCL Options Help")
Note: See TracBrowser for help on using the repository browser.