source: sasview/src/sas/qtgui/Perspectives/Fitting/GPUOptions.py @ ced1bff

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since ced1bff was ced1bff, checked in by krzywon, 6 years ago

Enable OpenCL tests and display results in new window.

  • Property mode set to 100644
File size: 8.1 KB
Line 
1# global
2import os
3import sys
4import sasmodels
5import json
6import platform
7
8from PyQt4 import QtGui, QtCore, QtWebKit
9from sas.qtgui.Perspectives.Fitting.UI.GPUOptionsUI import Ui_GPUOptions
10from sas.qtgui.Perspectives.Fitting.UI.GPUTestResultsUI import Ui_GPUTestResults
11
12try:
13    _fromUtf8 = QtCore.QString.fromUtf8
14except AttributeError:
15    def _fromUtf8(s):
16        return s
17
18try:
19    _encoding = QtGui.QApplication.UnicodeUTF8
20    def _translate(context, text, disambig):
21        return QtGui.QApplication.translate(context, text, disambig, _encoding)
22except AttributeError:
23    def _translate(context, text, disambig):
24        return QtGui.QApplication.translate(context, text, disambig)
25
26
27class GPUOptions(QtGui.QDialog, Ui_GPUOptions):
28    """
29    OpenCL Dialog to modify the OpenCL options
30    """
31
32    clicked = False
33    sas_open_cl = None
34
35    def __init__(self, parent=None):
36        super(GPUOptions, self).__init__(parent)
37        self.parent = parent
38        self.setupUi(self)
39        self.addOpenCLOptions()
40        self.createLinks()
41
42    def addOpenCLOptions(self):
43        """
44        Populate the window with a list of OpenCL options
45        """
46        # Get list of openCL options and add to GUI
47        cl_tuple = _get_clinfo()
48        i = 0
49        self.sas_open_cl = os.environ.get("SAS_OPENCL", "")
50        self.setWindowFlags(self.windowFlags() | QtCore.Qt.CustomizeWindowHint)
51        self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.WindowCloseButtonHint)
52        for title, descr in cl_tuple:
53            checkBox = QtGui.QCheckBox(self.openCLCheckBoxGroup)
54            checkBox.setGeometry(20, 20 + i, 351, 30)
55            checkBox.setObjectName(_fromUtf8(descr))
56            checkBox.setText(_translate("GPUOptions", descr, None))
57            if (descr == self.sas_open_cl) or (title == "None" and not self.clicked):
58                checkBox.click()
59                self.clicked = True
60            # Expand group and shift items down as more are added
61            self.openCLCheckBoxGroup.resize(391, 60 + i)
62            self.label.setGeometry(QtCore.QRect(20, 90 + i, 391, 37))
63            self.okButton.setGeometry(QtCore.QRect(20, 127 + i, 93, 28))
64            self.resetButton.setGeometry(QtCore.QRect(120, 127 + i, 93, 28))
65            self.testButton.setGeometry(QtCore.QRect(220, 127 + i, 93, 28))
66            self.helpButton.setGeometry(QtCore.QRect(320, 127 + i, 93, 28))
67            self.resize(440, 167 + i)
68            i += 30
69
70    def createLinks(self):
71        """
72        Link actions to function calls
73        """
74        self.testButton.clicked.connect(lambda: self.testButtonClicked())
75        self.helpButton.clicked.connect(lambda: self.helpButtonClicked())
76        for item in self.openCLCheckBoxGroup.findChildren(QtGui.QCheckBox):
77            item.clicked.connect(lambda: self.checked())
78
79    def checked(self):
80        """
81        Action triggered when box is selected
82        """
83        checked = None
84        for box in self.openCLCheckBoxGroup.findChildren(QtGui.QCheckBox):
85            if box.isChecked() and (str(box.text()) == self.sas_open_cl or (
86                            str(box.text()) == "No OpenCL" and self.sas_open_cl == "")):
87                box.setChecked(False)
88            elif not box.isChecked():
89                pass
90            else:
91                checked = box
92        if hasattr(checked, "text"):
93            self.sas_open_cl = str(checked.text())
94        else:
95            self.sas_open_cl = None
96
97    def set_open_cl(self):
98        """
99        Set openCL value when tests run or OK button clicked
100        """
101        no_opencl_msg = False
102        if self.sas_open_cl:
103            os.environ["SAS_OPENCL"] = self.sas_open_cl
104            if self.sas_open_cl.lower() == "none":
105                no_opencl_msg = True
106        else:
107            if "SAS_OPENCL" in os.environ:
108                del os.environ["SAS_OPENCL"]
109        # Sasmodels kernelcl doesn't exist when initiated with None
110        if 'sasmodels.kernelcl' in sys.modules:
111            sasmodels.kernelcl.ENV = None
112        reload(sasmodels.core)
113        return no_opencl_msg
114
115    def testButtonClicked(self):
116        """
117        Run sasmodels check from here and report results from
118        """
119
120        no_opencl_msg = self.set_open_cl()
121
122        # Only import when tests are run
123        from sasmodels.model_test import model_tests
124
125        try:
126            from sasmodels.kernelcl import environment
127            env = environment()
128            clinfo = [(ctx.devices[0].platform.vendor,
129                       ctx.devices[0].platform.version,
130                       ctx.devices[0].vendor,
131                       ctx.devices[0].name,
132                       ctx.devices[0].version)
133                      for ctx in env.context]
134        except ImportError:
135            clinfo = None
136
137        failures = []
138        tests_completed = 0
139        for test in model_tests():
140            try:
141                test()
142            except Exception:
143                failures.append(test.description)
144
145            tests_completed += 1
146
147        info = {
148            'version': sasmodels.__version__,
149            'platform': platform.uname(),
150            'opencl': clinfo,
151            'failing tests': failures,
152        }
153
154        msg_info = 'OpenCL tests results'
155
156        msg = str(tests_completed) + ' tests completed.\n'
157        if len(failures) > 0:
158            msg += str(len(failures)) + ' tests failed.\n'
159            msg += 'Failing tests: '
160            msg += json.dumps(info['failing tests'])
161            msg += "\n"
162        else:
163            msg += "All tests passed!\n"
164
165        msg += "\nPlatform Details:\n\n"
166        msg += "Sasmodels version: "
167        msg += info['version'] + "\n"
168        msg += "\nPlatform used: "
169        msg += json.dumps(info['platform']) + "\n"
170        if no_opencl_msg:
171            msg += "\nOpenCL driver: None"
172        else:
173            msg += "\nOpenCL driver: "
174            msg += json.dumps(info['opencl']) + "\n"
175        GPUTestResults(self, msg, msg_info)
176
177    def helpButtonClicked(self):
178        """
179        Open the help menu when the help button is clicked
180        """
181        tree_location = "user/sasgui/perspectives/fitting/gpu_setup.html"
182        anchor = "#device-selection"
183        self.helpView = QtWebKit.QWebView()
184        help_location = tree_location + anchor
185        self.helpView.load(QtCore.QUrl(help_location))
186        self.helpView.show()
187
188    def reject(self):
189        """
190        Close the window without modifying SAS_OPENCL
191        """
192        self.closeEvent(None)
193        self.parent.gpu_options_widget.open()
194
195    def accept(self):
196        """
197        Close the window after modifying the SAS_OPENCL value
198        """
199        self.set_open_cl()
200        super(GPUOptions, self).reject()
201
202    def closeEvent(self, event):
203        """
204        Overwrite QDialog close method to allow for custom widget close
205        """
206        self.close()
207        self.parent.gpu_options_widget = GPUOptions(self)
208
209
210class GPUTestResults(QtGui.QDialog, Ui_GPUTestResults):
211    """
212    OpenCL Dialog to modify the OpenCL options
213    """
214    def __init__(self, parent, msg, title):
215        super(GPUTestResults, self).__init__(parent)
216        self.setupUi(self)
217        self.resultsText.setText(_translate("GPUTestResults", msg, None))
218        self.open()
219
220
221def _get_clinfo():
222    """
223    Reading in information about available OpenCL infrastructure
224    :return:
225    """
226    clinfo = []
227    platforms = []
228    try:
229        import pyopencl as cl
230        platforms = cl.get_platforms()
231    except ImportError:
232        print("pyopencl import failed. Using only CPU computations")
233
234    p_index = 0
235    for platform in platforms:
236        d_index = 0
237        devices = platform.get_devices()
238        for device in devices:
239            if len(devices) > 1 and len(platforms) > 1:
240                combined_index = ":".join([str(p_index), str(d_index)])
241            elif len(platforms) > 1:
242                combined_index = str(p_index)
243            else:
244                combined_index = str(d_index)
245            clinfo.append((combined_index, ":".join([platform.name, device.name])))
246            d_index += 1
247        p_index += 1
248
249    clinfo.append(("None", "No OpenCL"))
250    return clinfo
Note: See TracBrowser for help on using the repository browser.