使用单个 GPU 进行 keras 模型预测的多处理

Posted

技术标签:

【中文标题】使用单个 GPU 进行 keras 模型预测的多处理【英文标题】:multiprocessing for keras model predict with single GPU 【发布时间】:2018-05-23 10:21:39 【问题描述】:

背景

我想使用带有 Inception-Resnet_v2 的 keras 预测病理图像。我已经训练了模型并得到了一个 .hdf5 文件。因为病理图像非常大(例如:20,000 x 20,000 像素),所以我必须扫描图像以获得小块进行预测。

我想使用带有 python2.7 的多处理库来加快预测过程。主要思想是使用不同的子进程扫描不同的行,然后将补丁发送到模型。

我看到有人建议在子进程中导入 keras 和加载模型。但我认为它不适合我的任务。使用keras.models.load_model()加载模型一次大约需要47s,非常耗时。所以每次启动新的子流程时,我都无法重新加载模型。

问题

我的问题是我可以在主进程中加载​​模型并将其作为参数传递给子进程吗?

我尝试了两种方法,但都没有奏效。

方法一。使用 multiprocessing.Pool

代码是:

import keras
from keras.models import load_model
import multiprocessing

def predict(num,model):
    print dir(model)
    print num
    model.predict("image data, type:list")

if __name__ == '__main__':
    model = load_model("path of hdf5 file")
    list = [(1,model),(2,model),(3,model),(4,model),(5,model),(6,model)]
    pool = multiprocessing.Pool(4)
    pool.map(predict,list)
    pool.close()
    pool.join()

输出是

cPickle.PicklingError: Can't pickle <type 'module'>: attribute lookup __builtin__.module failed

我查错发现Pool can't map unpickelable parameters,所以我尝试方法2。

方法二。使用 multiprocessing.Process

代码是

import keras
from keras.models import load_model
import multiprocessing

def predict(num,model):
    print num
    print dir(model)
    model.predict("image data, type:list")

if __name__ == '__main__':
    model = load_model("path of hdf5 file")
    list = [(1,model),(2,model),(3,model),(4,model),(5,model),(6,model)]
    proc = []
    for i in range(4):
        proc.append(multiprocessing.Process(predict, list[i]))
        proc[i].start()
    for i in range(4):
        proc[i].join()

在方法 2 中,我可以打印 dir(model)。我认为这意味着模型已成功传递给子流程。但是我得到了这个错误

E tensorflow/stream_executor/cuda/cuda_driver.cc:1296] failed to enqueue async memcpy from host to device: CUDA_ERROR_NOT_INITIALIZED; GPU dst: 0x13350b2200; host src: 0x2049e2400; size: 4=0x4

我使用的环境:

Ubuntu 16.04,python 2.7 keras 2.0.8(张量流后端) 一个 Titan X,驱动程序版本 384.98,CUDA 8.0

期待回复!谢谢!

【问题讨论】:

你解决过这个问题吗?在这里面临同样的酸洗问题。使用纯进程而不是池使进程挂起而不是无法腌制。但是我不确定这是否是一个进步。 【参考方案1】:

正如 Statham 所说,多进程要求所有参数都与 pickle 兼容。这篇博文描述了如何将 keras 模型保存为 pickle:[http://zachmoshe.com/2017/04/03/pickling-keras-models.html][1] 将您的 keras 模型作为 arg 传递给多进程可能是一个足够的解决方法,但我自己还没有测试过这个想法。

我还要补充一点,我最好使用 windows 而不是 linux 在单个 gpu 上运行两个 keras 进程。在 linux 上,我在第二个进程中出现内存不足错误,但相同的内存分配(每个进程的总 GPU 内存的 45%)在 windows 上工作。在我的情况下,它们很合适 - 仅用于运行预测,内存需求可能更少。

【讨论】:

【参考方案2】:

多处理在 CPU 上进行,而模型预测在 GPU 中进行,只有一个。我看不出多处理如何帮助您进行预测。

相反,我认为您可以使用多处理来扫描不同的补丁,您似乎已经设法实现了这一点。然后将这些补丁堆叠成一个或多个批次以在 GPU 中并行预测。

【讨论】:

【参考方案3】:

也许你可以使用 apply_async() 而不是 Pool()

您可以在此处找到更多详细信息:

Python multiprocessing pickling error

【讨论】:

以上是关于使用单个 GPU 进行 keras 模型预测的多处理的主要内容,如果未能解决你的问题,请参考以下文章

keras上的多GPU训练错误(OOM)(足够的内存,可能是配置问题)

Keras强制使用CPU

如何在 keras 中进行深度学习中的多标签分类?

具有Tensorflow后端的Keras - 运行在CPU上预测但适合GPU

Keras 中的多分类预测不止一个?

DSVM GPU 内存不足