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

Last change on this file since 92583049 was 92583049, checked in by wojciech, 8 years ago

Adding back-compatibility support if SAS_OPENCL is not set in config_file

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