我正在使用多处理池来管理 tesseract 进程(缩微胶片的 OCRing 页面)。很多时候,在一个包含 20 个 tesseract 进程的池中,有几页会更难 OCR,因此这些进程比其他进程花费的时间要长得多。同时,池只是挂起,大多数 CPU 都没有被利用。我希望让这些落后者继续下去,但我也想启动更多进程来填满现在闲置的许多其他 CPU,而这几个粘性页面正在完成。我的问题:有没有办法加载新进程来利用那些空闲的 CPU。换句话说,可以在等待整个池完成之前将池中的空位填满吗?
我可以使用星图的异步版本,然后在当前池下降到一定数量的活动进程时加载一个新池。但这似乎不优雅。根据需要自动保持在进程中的插槽会更优雅。
这是我的代码现在的样子:
def getMpBatchMap(fileList, commandTemplate, concurrentProcesses):
mpBatchMap = []
for i in range(concurrentProcesses):
fileName = fileList.readline()
if fileName:
mpBatchMap.append((fileName, commandTemplate))
return mpBatchMap
def executeSystemProcesses(objFileName, commandTemplate):
objFileName = objFileName.strip()
logging.debug(objFileName)
objDirName = os.path.dirname(objFileName)
command = commandTemplate.substitute(objFileName=objFileName, objDirName=objDirName)
logging.debug(command)
subprocess.call(command, shell=True)
def process(FILE_LIST_FILENAME, commandTemplateString, concurrentProcesses=3):
"""Go through the list of files and run the provided command against them,
one at a time. Template string maps the terms $objFileName and $objDirName.
Example:
>>> runBatchProcess('convert -scale 256 "$objFileName" "$objDirName/TN.jpg"')
"""
commandTemplate = Template(commandTemplateString)
with open(FILE_LIST_FILENAME) as fileList:
while 1:
# Get a batch of x files to process
mpBatchMap = getMpBatchMap(fileList, commandTemplate, concurrentProcesses)
# Process them
logging.debug('Starting MP batch of %i' % len(mpBatchMap))
if mpBatchMap:
with Pool(concurrentProcesses) as p:
poolResult = p.starmap(executeSystemProcesses, mpBatchMap)
logging.debug('Pool result: %s' % str(poolResult))
else:
break