簡體   English   中英

Python 無法啟動新線程多處理

[英]Python can't start new thread multiprocessing

我正在嘗試使用一組計算機來運行數百萬個小型模擬。 為此,我嘗試在我的主計算機上設置兩台“服務器”,一台用於將隊列中的輸入變量添加到網絡,另一台用於處理結果。

這是將東西放入模擬變量隊列的代碼:

"""This script reads start parameters and calls on run_sim to run the
simulations"""
import time
from multiprocessing import Process, freeze_support, Manager, Value, Queue, current_process
from multiprocessing.managers import BaseManager


class QueueManager(BaseManager):
    pass


class MultiComputers(Process):
    def __init__(self, sim_name, queue):
        self.sim_name = sim_name
        self.queue = queue
        super(MultiComputers, self).__init__()

    def get_sim_obj(self, offset, db):
        """returns a list of lists from a database query"""

    def handle_queue(self):
        self.sim_nr = 0
        sims = self.get_sim_obj()
        self.total = len(sims)
        while len(sims) > 0:
            if self.queue.qsize() > 100:
                self.queue.put(sims[0])
                self.sim_nr += 1
                print(self.sim_nr, round(self.sim_nr/self.total * 100, 2), self.queue.qsize())
                del sims[0]

    def run(self):
        self.handle_queue()

if __name__ == '__main__':
    freeze_support()
    queue = Queue()
    w = MultiComputers('seed_1_hundred', queue)
    w.start()
    QueueManager.register('get_queue', callable=lambda: queue)
    m = QueueManager(address=('', 8001), authkey=b'abracadabra')
    s = m.get_server()
    s.serve_forever()

然后這個隊列運行以處理模擬結果:

__author__ = 'axa'
from multiprocessing import Process, freeze_support, Queue
from multiprocessing.managers import BaseManager
import time


class QueueManager(BaseManager):
    pass


class SaveFromMultiComp(Process):
    def __init__(self, sim_name, queue):
        self.sim_name = sim_name
        self.queue = queue
        super(SaveFromMultiComp, self).__init__()

    def run(self):
        res_got = 0
        with open('sim_type1_' + self.sim_name, 'a') as f_1:
            with open('sim_type2_' + self.sim_name, 'a') as f_2:
                while True:
                    if self.queue.qsize() > 0:
                        while self.queue.qsize() > 0:
                            res = self.queue.get()
                            res_got += 1
                            if res[0] == 1:
                                f_1.write(str(res[1]) + '\n')
                            elif res[0] == 2:
                                f_2.write(str(res[1]) + '\n')
                            print(res_got)
                    time.sleep(0.5)


if __name__ == '__main__':
    queue = Queue()
    w = SaveFromMultiComp('seed_1_hundred', queue)
    w.start()
    m = QueueManager(address=('', 8002), authkey=b'abracadabra')
    s = m.get_server()
    s.serve_forever()

這些腳本按預期工作以處理前〜7-800個模擬,之后我在運行接收結果腳本的終端中收到以下錯誤:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Python35\lib\threading.py", line 914, in _bootstrap_inner
    self.run()
  File "C:\Python35\lib\threading.py", line 862, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Python35\lib\multiprocessing\managers.py", line 177, in accepter
    t.start()
  File "C:\Python35\lib\threading.py", line 844, in start
    _start_new_thread(self._bootstrap, ())
RuntimeError: can't start new thread

任何人都可以就線程的產生位置和方式提供一些見解,每次我調用queue.get()時是否都會產生一個新線程,或者它是如何工作的? 如果有人知道我可以做些什么來避免這種失敗,我會很高興? (我正在使用Python3.5-32運行腳本)

所有跡象都表明您的系統沒有啟動線程所需的資源(可能是 memory,但您可能正在泄漏線程或其他資源)。 您可以使用 OS 系統監控工具(Linux 的top ,Windows 的Resource Monitor )查看線程數和 memory 的使用情況來跟蹤這一點,但我建議您使用更簡單、更有效的編程模式。

雖然不是一個完美的比較,但您通常會看到C10K 問題,它指出等待結果的阻塞線程不能很好地擴展,並且容易出現這樣的泄漏錯誤。 解決方案是實現異步 IO 模式(一個啟動其他工作線程的阻塞線程),這在 Web 服務器中非常簡單。

aiohttp這樣的框架應該很適合你想要的。 您只需要一個可以獲取遠程代碼的 ID 和結果的處理程序。 該框架應該有望為您解決擴展問題。

因此,在您的情況下,您可以保留啟動代碼,但在遠程機器上啟動進程后,終止線程。 然后讓遠程代碼向您的服務器發送一條 HTTP 消息,其中包含 1)它的 ID 和 2)它的結果。 如果它沒有得到 200 'OK' 狀態碼,請輸入一些額外的代碼,讓它再試一次,你的狀態應該會好得多。

我認為您必須為您的系統運行許多線程。 我會首先檢查您的系統資源,然后重新考慮我的程序。 嘗試限制您的線程並盡可能少地使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM