Python 线程因 pandas 操作而“饥饿”

问题描述 投票:0回答:1

我正在用 Python 中的 Qt 创建一个 UI 应用程序。它在单独的

threading.Thread
中对 pandas DataFrame 执行操作,以保持 UI 响应;没有个人熊猫指令需要花费大量时间。但是,主线程中仍然存在约一秒左右的延迟。

我听说过全局解释器锁(GIL),但据我了解,它应该在几毫秒后释放。当单独的线程已经执行了一整秒时,为什么它仍然执行更多的Python指令?如何正确消除延迟?

我发现,如果我在单独的线程中撒上

time.sleep(0.00001)
,那么延迟就会消失。但这不是解决方案。

如果我在没有 pandas 的情况下使用其他一些繁重的计算(仅尝试了完全用 Python 实现的其他操作),则主线程中没有延迟。

我在以下脚本中重现了该问题。对我来说最高的 deltaTime 约为 1 秒,而评论的

sleep
约为 0.1 秒。

import threading
import time
from datetime import datetime
import pandas as pd

longest_so_far = 0
last_timestamp = datetime.now()
first_run = True


def print_delta_time(interval=0.001):
    global longest_so_far
    global last_timestamp
    global first_run
    while True:
        time.sleep(interval)
        current_time = datetime.now()

        if first_run:
            first_run = False
        else:
            delta_time = (current_time - last_timestamp).total_seconds()
            if delta_time > longest_so_far:
                print("New longest deltaTime:", delta_time)
                longest_so_far = delta_time
        last_timestamp = current_time


def perform_pandas_operations():
    time.sleep(1)
    print("Starting pandas operations")
    df = pd.DataFrame({
        'A': [f"{i}" for i in range(1000)],
    })
    for _ in range(20000):
        df['A'].str.contains(r'123$').sum()
        # time.sleep(0.0000001)
    print("Finished pandas operations")


pandas_thread = threading.Thread(target=perform_pandas_operations)
pandas_thread.daemon = True  # Ensure the thread exits when the main program exits
pandas_thread.start()

print_delta_time()
python pandas concurrency python-multithreading
1个回答
0
投票

我对 numpy/scipy 案例进行了相同的观察(在单独的线程中运行

minimize
)。如果 CPU 线程不间断地运行,它可以使 Tkinter 线程饥饿任意长时间。至少在 Windows 下(尚未在 Linux 中尝试过)。

解决方案确实是进行接近零时间的睡眠。这似乎向调度程序发出信号,表明该线程可以挂起,而其他线程有机会运行。当然,这要求您至少有一些可以放置该调用的“断点”。

实际上,您可以利用它来获得有益的效果:

  • 您可以将
    time.sleep
    替换为
    threading.Event.wait
    ,并将该事件用作“取消”标志,以允许中断计算。
  • 此外,这是更新进度条或其他显示的完美断点:-)
© www.soinside.com 2019 - 2024. All rights reserved.