简体   繁体   English

使用 Pyside2 QThread 线程时 Scipy curve_fit 崩溃

[英]Scipy curve_fit crashes when threaded with Pyside2 QThread

I'm using pyside2 to make a QT5 application where I'm fitting thousands of functions with scipy.optimize.curve_fit.我正在使用 pyside2 制作一个 QT5 应用程序,我在其中使用 scipy.optimize.curve_fit 拟合了数千个函数。 To avoid freezing the gui I'm using Qthread() to put these thousands of calls to curve_fit on a separate thread.为了避免冻结 gui,我使用 Qthread() 将这数千个对 curve_fit 的调用放在一个单独的线程上。 Sometimes this works, but if I run this program repeatedly it will occasionally crash on one of the calls to curve_fit.有时这有效,但如果我重复运行这个程序,它偶尔会在调用 curve_fit 时崩溃。

I created a minimal example that can reproduce this error.我创建了一个可以重现此错误的最小示例。 Sometimes I have to run it 20 times before it crashes.有时我必须在它崩溃之前运行它 20 次。 The errors are: "Segmentation fault: 11" and "Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)"错误是:“分段错误:11”和“进程已完成,退出代码为 139(被信号 11:SIGSEGV 中断)”

I'm on Python 3.8.2 with all libraries updated.我在 Python 3.8.2 上更新了所有库。

import sys
from PySide2.QtWidgets import QApplication, QLabel, QMainWindow
from PySide2.QtCore import Qt, QThread, QObject, Signal
import numpy as np
from scipy.optimize import curve_fit

class ProcessData(QObject):
    loaded = Signal(int)
    ready = Signal(list)
    finished = Signal()

    def __init__(self, data):
        super().__init__()
        self._data = data

    def func(self, x, a, b, c):
        return a * np.exp(-b * x) + c

    def run(self):
        result = []
        y = self.func(self._data, 2.5, 1.3, 0.5)
        for i in range(1000):
            y_noise = 0.2 * np.random.normal(size=self._data.size)
            ydata = y + y_noise
            print("start fit: {}".format(i))
            popt, pcov = curve_fit(self.func, self._data, ydata)
            print("finished fit: {}".format(i))
            result.append(popt)
        self.ready.emit(result)
        self.finished.emit()

    def stop(self):
        self._stop = True

class MainWindow(QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.setWindowTitle("Test Application")
        self.thread = QThread()
        self.data = np.linspace(0, 4, 50)
        self.process_data = ProcessData(self.data)
        self.process_data.moveToThread(self.thread)
        self.process_data.ready.connect(self.show_result)
        self.process_data.finished.connect(self.thread.quit)
        self.thread.started.connect(self.process_data.run)
        self.thread.finished.connect(self.process_data.deleteLater)
        self.thread.start()

    def show_result(self, result):
        label = QLabel("Fitted {} functions".format(len(result)))
        label.setAlignment(Qt.AlignCenter)
        self.setCentralWidget(label)


app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()

Disclaimer: I could not reproduce the issue.免责声明:我无法重现该问题。

As far as I know scipy.optimize.curve_fit uses scipy.optimize.leastsq under the hood, which is not thread-safe, and you should acquire thread lock before calling curve_fit (however it might break your purpose).据我所知scipy.optimize.curve_fit在引擎盖下使用scipy.optimize.leastsq ,这不是线程安全的,您应该在调用 curve_fit 之前获取线程锁(但是它可能会破坏您的目的)。 The segmentation fault is also a sign that something's wrong with memory management, probably reading data that's not mapped in the process.分段错误也是内存管理出现问题的标志,可能是读取过程中未映射的数据。 You could try multiprocessing, but I don't think that would make anything better (since you're making a GUI).您可以尝试多处理,但我认为这不会使任何事情变得更好(因为您正在制作 GUI)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM