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

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

Writting to configuration file at the end of session

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