使用 Pyside2 QThread 线程化时,Scipy curve_fit 崩溃
Posted
技术标签:
【中文标题】使用 Pyside2 QThread 线程化时,Scipy curve_fit 崩溃【英文标题】:Scipy curve_fit crashes when threaded with Pyside2 QThread 【发布时间】:2020-11-17 10:20:03 【问题描述】:我正在使用 pyside2 制作一个 QT5 应用程序,我在其中使用 scipy.optimize.curve_fit 拟合数千个函数。为了避免冻结 gui,我使用 Qthread() 将这数千个对 curve_fit 的调用放在单独的线程上。 有时这可行,但如果我反复运行这个程序,它偶尔会在调用 curve_fit 时崩溃。
我创建了一个可以重现此错误的最小示例。有时我必须运行它 20 次才能崩溃。错误是:“分段错误:11”和“进程以退出代码 139 完成(被信号 11 中断:SIGSEGV)”
我使用的是 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_()
【问题讨论】:
我没有在 Linux 上使用 PySide2 5.15.1 重现该问题 我在 Mac 上使用 python 3.8.2,numpy 1.19.4,scipy 1.5.4,Pyside2 5.15.1 【参考方案1】:免责声明:我无法重现该问题。
据我所知scipy.optimize.curve_fit
在后台使用scipy.optimize.leastsq
,这不是线程安全的,您应该在调用curve_fit 之前获取线程锁(但是它可能会破坏您的目的)。分段错误也是内存管理出现问题的标志,可能读取了未在进程中映射的数据。您可以尝试多处理,但我认为这不会有更好的效果(因为您正在制作 GUI)。
【讨论】:
以上是关于使用 Pyside2 QThread 线程化时,Scipy curve_fit 崩溃的主要内容,如果未能解决你的问题,请参考以下文章
访问在QThread内部由Pynput侦听器调用的线程中访问的SQLite3数据库连接时关注竞争条件
关注在 QThread 内由 Pynput 侦听器调用的线程中访问的 SQLite3 数据库连接时的竞争条件