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

ESS_GUIESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since 12db2db6 was db05c44, checked in by Torin Cooper-Bennun <torin.cooper-bennun@…>, 6 years ago

fix OpenCL device never being set correctly; fix loading in default device from config (and setting to no OpenCL by default)

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