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

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

Added message dialog for testing results

  • Property mode set to 100644
File size: 10.0 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
13import logging
14from sas.sasgui.guiframe.documentation_window import DocumentationWindow
15import imp
16
17
18class CustomMessageBox(wx.Dialog):
19    def __init__(self, parent, msg, title):
20        wx.Dialog.__init__(self, parent, title=title)
21        text = wx.TextCtrl(self, style=wx.TE_READONLY|wx.BORDER_NONE)
22        text.SetValue(msg)
23        text.SetBackgroundColour(self.GetBackgroundColour())
24        self.ShowModal()
25        self.Destroy()
26
27
28class GpuOptions(wx.Dialog):
29    """
30    "OpenCL options" Dialog Box
31
32    Provides dialog for setting SAS_OPENCL variable, which defines
33    device choice for OpenCL calculation
34
35    """
36
37    def __init__(self, *args, **kwds):
38
39        kwds["style"] = wx.DEFAULT_DIALOG_STYLE
40        wx.Dialog.__init__(self, *args, **kwds)
41
42        clinfo = self._get_clinfo()
43
44        self.panel1 = wx.Panel(self, -1)
45        static_box1 = wx.StaticBox(self.panel1, -1, "Available OpenCL Options:")
46
47        boxsizer = wx.BoxSizer(orient=wx.VERTICAL)
48        self.option_button = {}
49        self.buttons = []
50        #Check if SAS_OPENCL is already set as enviromental variable
51        self.sas_opencl = os.environ.get("SAS_OPENCL","")
52        #self.sas_opencl =  os.environ["SAS_OPENCL"] \
53        #    if "SAS_OPENCL" in os.environ else SAS_OPENCL_CUSTOM
54
55        for clopt in clinfo:
56            button = wx.CheckBox(self.panel1, -1, label=clopt[1], name=clopt[1])
57
58            if clopt != "No OpenCL":
59                self.option_button[clopt[1]] = clopt[0]
60                if self.sas_opencl == clopt[0]:
61                    button.SetValue(1)
62            else:
63                self.option_button[clopt] = "None"
64                if self.sas_opencl.lower() == "none":
65                    button.SetValue(1)
66
67            self.Bind(wx.EVT_CHECKBOX, self.on_check, id=button.GetId())
68            self.buttons.append(button)
69            boxsizer.Add(button, 0, 0)
70
71        fit_hsizer = wx.StaticBoxSizer(static_box1, orient=wx.VERTICAL)
72        fit_hsizer.Add(boxsizer, 0, wx.ALL, 5)
73
74        self.panel1.SetSizer(fit_hsizer)
75
76        self.vbox = wx.BoxSizer(wx.VERTICAL)
77        self.vbox.Add(self.panel1, 0, wx.ALL, 10)
78
79        accept_btn = wx.Button(self, wx.ID_OK)
80        accept_btn.SetToolTipString("Accept new OpenCL settings. This will"
81                                    " overwrite SAS_OPENCL variable if set")
82
83        help_id = wx.NewId()
84        help_btn = wx.Button(self, help_id, 'Help')
85        help_btn.SetToolTipString("Help on the GPU options")
86
87        reset_id = wx.NewId()
88        reset_btn = wx.Button(self, reset_id, 'Reset')
89        reset_btn.SetToolTipString("Restore initial settings")
90
91        test_id = wx.NewId()
92        test_btn = wx.Button(self, test_id, 'Test')
93        test_btn.SetToolTipString("Test if models compile on the given infrastructure")
94
95        self.Bind(wx.EVT_BUTTON, self.on_OK, accept_btn)
96        self.Bind(wx.EVT_BUTTON, self.on_test, test_btn)
97        self.Bind(wx.EVT_BUTTON, self.on_reset, reset_btn)
98        self.Bind(wx.EVT_BUTTON, self.on_help, help_btn)
99
100
101        btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
102        btn_sizer.Add((10, 20), 1) # stretchable whitespace
103        btn_sizer.Add(accept_btn, 0)
104        btn_sizer.Add((10, 20), 0) # non-stretchable whitespace
105        btn_sizer.Add(test_btn, 0)
106        btn_sizer.Add((10, 20), 0) # non-stretchable whitespace
107        btn_sizer.Add(reset_btn, 0)
108        btn_sizer.Add((10, 20), 0) # non-stretchable whitespace
109        btn_sizer.Add(help_btn, 0)
110
111        # Add the button sizer to the main sizer.
112        self.vbox.Add(btn_sizer, 0, wx.EXPAND|wx.ALL, 10)
113
114        self.SetSizer(self.vbox)
115        self.vbox.Fit(self)
116        self.SetTitle("OpenCL options")
117        self.Centre()
118
119    def _get_clinfo(self):
120        """
121        Reading in information about available OpenCL infrastructure
122        :return:
123        """
124        clinfo = []
125        try:
126            import pyopencl as cl
127            platforms = cl.get_platforms()
128            p_index = 0
129            for platform in platforms:
130                d_index = 0
131                devices = platform.get_devices()
132                for device in devices:
133                    if len(devices) > 1 and len(platforms) > 1:
134                        combined_index = ":".join([str(p_index),str(d_index)])
135                    elif len(platforms) > 1:
136                        combined_index = str(p_index)
137                    else:
138                        combined_index = str(d_index)
139                    #combined_index = ":".join([str(p_index),str(d_index)]) \
140                    #    if len(platforms) > 1 else str(d_index)
141                    clinfo.append((combined_index, ":".join([platform.name,device.name])))
142                    d_index += 1
143                p_index += 1
144        except ImportError:
145            warnings.warn("pyopencl import failed. Using only CPU computations")
146
147        clinfo.append(("None","No OpenCL"))
148        return clinfo
149
150
151    def _write_to_config_file(self):
152        from sas.sasgui.guiframe.customdir import SetupCustom
153        from sas.sasgui.guiframe.gui_manager import _find_local_config
154
155        c_conf_dir = SetupCustom().find_dir()
156        self.custom_config = _find_local_config('custom_config', c_conf_dir)
157        if self.custom_config is None:
158            self.custom_config = _find_local_config('custom_config', os.getcwd())
159
160        #How to store it in file
161        new_config_lines = []
162        config_file = open(self.custom_config.__file__[:-1])
163        if self.custom_config is not None:
164            config_lines = config_file.readlines()
165            for line in config_lines:
166                if "SAS_OPENCL" in line:
167                    if self.sas_opencl:
168                        new_config_lines.append("SAS_OPENCL = \""+self.sas_opencl+"\"")
169                    else:
170                        new_config_lines.append("SAS_OPENCL = None")
171                else:
172                    new_config_lines.append(line)
173        config_file.close()
174        new_config_file = open(self.custom_config.__file__[:-1],"w")
175        new_config_file.writelines(new_config_lines)
176        new_config_file.close()
177
178        #After file is touched module needs to be reloaded
179        self.custom_config = _find_local_config('custom_config', c_conf_dir)
180        if self.custom_config is None:
181            self.custom_config = _find_local_config('custom_config', os.getcwd())
182
183    def on_check(self, event):
184        """
185        Action triggered when button is selected
186        :param event:
187        :return:
188        """
189        selected_button = event.GetEventObject()
190        for btn in self.buttons:
191            if btn != selected_button:
192                btn.SetValue(0)
193        if selected_button.GetValue():
194            self.sas_opencl = self.option_button[selected_button.Name]
195        else:
196            self.sas_opencl = None
197
198    def on_OK(self, event):
199        """
200        Close window on accpetance
201        """
202        import sasmodels
203        #If statement added to handle Reset
204        if self.sas_opencl:
205            os.environ["SAS_OPENCL"] = self.sas_opencl
206        else:
207            if "SAS_OPENCL" in os.environ:
208                del(os.environ["SAS_OPENCL"])
209        try:
210            imp.find_module('sasmodels.kernelcl')
211            kernelcl_exist = True
212        except:
213            kernelcl_exist = False
214        if kernelcl_exist:
215            sasmodels.kernelcl.ENV = None
216
217        self._write_to_config_file()
218        #Need to reload sasmodels.core module to account SAS_OPENCL = "None"
219        reload(sasmodels.core)
220        event.Skip()
221
222    def on_reset(self, event):
223        """
224        Close window on accpetance
225        """
226        import sasmodels
227        for btn in self.buttons:
228            btn.SetValue(0)
229
230        self.sas_opencl=None
231        del(os.environ["SAS_OPENCL"])
232
233        try:
234            imp.find_module('sasmodels.kernelcl')
235            kernelcl_exist = True
236        except:
237            kernelcl_exist = False
238        if kernelcl_exist:
239            sasmodels.kernelcl.ENV = None
240
241        self._write_to_config_file()
242        reload(sasmodels.core)
243        event.Skip()
244
245    def on_test(self, event):
246        """
247        Run sasmodels check from here and report results from
248        """
249        import json
250        import platform
251        import sasmodels
252        from sasmodels.model_test import model_tests
253
254        try:
255            from sasmodels.kernelcl import environment
256            env = environment()
257            clinfo = [(ctx.devices[0].platform.vendor,
258                      ctx.devices[0].platform.version,
259                      ctx.devices[0].vendor,
260                      ctx.devices[0].name,
261                      ctx.devices[0].version)
262                    for ctx in env.context]
263        except ImportError:
264            clinfo = None
265
266        failures = []
267        for test in model_tests():
268            try:
269                test()
270            except Exception:
271                failures.append(test.description)
272
273        info = {
274            'version':  sasmodels.__version__,
275            'platform': platform.uname(),
276            'opencl': clinfo,
277            'failing tests': failures,
278        }
279
280        msg_info = "OpenCL tests"
281        msg = "OpenCL test completed!\n"
282        msg += "Sasmodels version: "
283        msg += info['version']+"\n"
284        msg += "Platform used: "
285        msg += json.dumps(info['platform'])+"\n"
286        msg += "OpenCL driver: "
287        msg += json.dumps(info['opencl'])+"\n"
288        if len(failures) > 0:
289            msg += 'Failing tests:\n'
290            msg += json.dumps(info['failing tests'])
291        else:
292            msg+="All tests passed\n"
293
294        CustomMessageBox(self.panel1, msg, msg_info)
295
296    def on_help(self, event):
297        """
298        Provide help on opencl options.
299        """
300        TreeLocation = "user/gpu_computations.html"
301        anchor = "#device-selection"
302        DocumentationWindow(self, -1,
303                            TreeLocation, anchor, "OpenCL Options Help")
Note: See TracBrowser for help on using the repository browser.