![](/img/trans.png)
[英]Python 2.7: “can't start new thread” error from “multiprocessing.Pool”
[英]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.