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

Last change on this file since 4ecf91a was 4ecf91a, checked in by wojciech, 5 years ago

Fixes for opencl info

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