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

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 9863343 was 9863343, checked in by krzywon, 6 years ago

Address issues outlined in SVCC-79.

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