【发布时间】:2017-12-20 14:38:15
【问题描述】:
当我使用 TensorFlow-GPU + Python 多处理时,我注意到一个奇怪的行为。
我已经实现了一个DCGAN,其中包含一些自定义项和我自己的数据集。由于我让 DCGAN 适应某些特征,因此我有训练数据和测试数据以进行评估。
由于我的数据集的大小,我编写了并发运行的数据加载器,并使用 Python 的 multiprocessing 预加载到队列中。
代码的结构大致是这样的:
class ConcurrentLoader:
def __init__(self, dataset):
...
class DCGAN
...
net = DCGAN()
training_data = ConcurrentLoader(path_to_training_data)
test_data = ConcurrentLoader(path_to_test_data)
此代码在 TensorFlow-CPU 上运行良好和在 TensorFlow-GPU TensorFlow-GPU 1.4.1 运行完全相同的代码时和 CUDA 9(截至 2017 年 12 月的 TF 和 CUDA 的最新版本)崩溃:
2017-12-20 01:15:39.524761: E tensorflow/stream_executor/cuda/cuda_blas.cc:366] failed to create cublas handle: CUBLAS_STATUS_NOT_INITIALIZED
2017-12-20 01:15:39.527795: E tensorflow/stream_executor/cuda/cuda_blas.cc:366] failed to create cublas handle: CUBLAS_STATUS_NOT_INITIALIZED
2017-12-20 01:15:39.529548: E tensorflow/stream_executor/cuda/cuda_blas.cc:366] failed to create cublas handle: CUBLAS_STATUS_NOT_INITIALIZED
2017-12-20 01:15:39.535341: E tensorflow/stream_executor/cuda/cuda_dnn.cc:385] could not create cudnn handle: CUDNN_STATUS_INTERNAL_ERROR
2017-12-20 01:15:39.535383: E tensorflow/stream_executor/cuda/cuda_dnn.cc:352] could not destroy cudnn handle: CUDNN_STATUS_BAD_PARAM
2017-12-20 01:15:39.535397: F tensorflow/core/kernels/conv_ops.cc:667] Check failed: stream->parent()->GetConvolveAlgorithms( conv_parameters.ShouldIncludeWinogradNonfusedAlgo<T>(), &algorithms)
[1] 32299 abort (core dumped) python dcgan.py --mode train --save_path ~/tf_run_dir/test --epochs 1
真正让我困惑的是,如果我只是删除test_data,则不会发生错误。因此,出于某种奇怪的原因,TensorFlow-GPU 1.4.1 和 CUDA 9 只使用一个 ConcurrentLoader,但是当多个加载器被初始化时会崩溃。
更有趣的是(异常之后)我必须手动关闭 python 进程,因为 GPU 的 VRAM、系统的 RAM 甚至 python 进程在脚本崩溃后仍然保持活动状态。
此外,它必须与 Python 的 multiprocessing 模块有一些奇怪的联系,因为当我在 Keras 中实现 same 模型时(使用 TF 后端!)代码也运行得很好,有 2并发加载器。我猜 Keras 以某种方式在两者之间创建了一个抽象层,以防止 TF 崩溃。
我可能在哪里搞砸了 multiprocessing 模块,它会导致像这样的崩溃?
这些是在ConcurrentLoader 中使用multiprocessing 的代码部分:
def __init__(self, dataset):
...
self._q = mp.Queue(64)
self._file_cycler = cycle(img_files)
self._worker = mp.Process(target=self._worker_func, daemon=True)
self._worker.start()
def _worker_func(self):
while True:
... # gets next filepaths from self._file_cycler
buffer = list()
for im_path in paths:
... # uses OpenCV to load each image & puts it into the buffer
self._q.put(np.array(buffer).astype(np.float32))
...就是这样。
我在哪里写了“不稳定”或“非pythonic”multiprocessing 代码?我认为daemon=True 应该确保每个进程在主进程死亡后立即被杀死?不幸的是,此特定错误并非如此。
我是否在这里误用了默认的multiprocessing.Process 或multiprocessing.Queue?我认为只需编写一个类,将批量图像存储在队列中并通过方法/实例变量访问它就可以了。
【问题讨论】:
标签: python multithreading tensorflow multiprocessing