我正在研究一種科學演算法(影像處理),它是用 C 撰寫的,并使用大量并行化,由 OpenMP 處理。我需要它可以從 Python 呼叫,所以我創建了一個 CPython 包,它處理演算法的包裝。現在我需要一些 UI,因為用戶互動對于初始化一些東西是必不可少的。我的問題是當我運行演算法時 UI 凍結。我在一個單獨的執行緒中啟動演算法,所以這應該不是問題(我什至通過用 替換函式呼叫來證明它time.sleep,它作業正常,不會導致任何凍結)。為了測驗,我將 UI 簡化為兩個按鈕:一個用于啟動演算法,另一個只是將一些隨機字串列印到控制臺(以檢查 UI 互動)。
我也經歷了一些非常奇怪的事情。如果我開始移動滑鼠,然后按下按鈕開始計算,然后不斷移動滑鼠,UI 不會凍結,因此將滑鼠懸停在按鈕上會給它們帶來通常的藍色 Windows 風格色調。但是,如果我停止在應用程式視窗上移動滑鼠幾秒鐘、單擊一個按鈕或切換到另一個視窗,UI 就會再次凍結。更奇怪的是,如果我將滑鼠放在應用程式視窗之外,UI 仍然處于活動狀態。
這是我的代碼(不幸的是,由于多種原因,我無法分享演算法,但我希望即使這樣也能得到一些幫助):
if __name__ == "__main__":
from PyQt5.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget
from PyQt5.QtCore import QThread, QObject, pyqtSignal
import time
from CustomAlgorithm import Estimator # my custom Python package implemented in C
class Worker(QObject):
finished = pyqtSignal()
def run(self):
estimator = Estimator()
estimator.calculate()
# if the above two lines are commented, and the next line is uncommented,
# everything's fine
# time.sleep(5)
print("done")
app = QApplication([])
thread = QThread()
window = QWidget()
layout = QVBoxLayout()
# button to start the calculation
btn = QPushButton("start")
layout.addWidget(btn)
btn.clicked.connect(thread.start)
# button to print some text to console
btn2 = QPushButton("other button")
layout.addWidget(btn2)
btn2.clicked.connect(lambda: print("other button clicked"))
window.setLayout(layout)
# handling events
worker = Worker(app)
worker.moveToThread(thread)
thread.started.connect(worker.run)
worker.finished.connect(thread.quit)
worker.finished.connect(worker.deleteLater)
thread.finished.connect(thread.deleteLater)
window.show()
app.exec_()
我嘗試了多種使用執行緒的變體,例如threading.Thread, multiprocessing.Process, PyQt5.QtCore.QThread(如上所示),甚至napari是作業執行緒的實作,但結果是一樣的。我什至嘗試從代碼中洗掉 omp,以防它以某種方式干擾 python 執行緒,但它沒有幫助。
至于我使用 python 的原因,最終目標是讓我的實作在napari.
任何幫助將不勝感激!
uj5u.com熱心網友回復:
由于 Python 的“全域解釋器鎖”,一次只能有一個執行緒運行 Python 代碼。但是,其他執行緒可以同時進行 I/O。
如果你想允許其他執行緒運行(就像 I/O 一樣),你可以用這些宏包圍你的代碼:
Py_BEGIN_ALLOW_THREADS
// computation goes here
Py_END_ALLOW_THREADS
在計算發生時,其他 Python 執行緒將被允許運行。在這兩行之間,您無法從 Python 訪問任何內容- 所以在之前 Py_BEGIN_ALLOW_THREADS按順序獲取這些資料。
參考
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/448139.html
上一篇:QT按鈕創建物件
