Python Theano正在配置中未指定的设备上创建其他线程

Python Theano正在配置中未指定的设备上创建其他线程,python,multithreading,theano,keras,theano-cuda,Python,Multithreading,Theano,Keras,Theano Cuda,因此,我有以下情况: 带有3个图形卡的计算机 使用Keras的python脚本,无后端和多线程 我在.theanoc中指定了要使用的设备,如文档中所述 python脚本的形式如下(仍在处理一个独立的示例): 启动脚本Theano使用指定的设备,但一段时间后,另一个python线程出现在另一个图形卡上(并耗尽资源) 第二个线程似乎忽略了配置,因为它在错误的GPU上运行,并且没有按照CNEM标志指定的方式分配ram 根据文档,这是不可能的,因为从启动Theano计算的线程派生的所有内容都应该在同一个

因此,我有以下情况:

  • 带有3个图形卡的计算机
  • 使用Keras的python脚本,无后端和多线程
  • 我在
    .theanoc
    中指定了要使用的设备,如文档中所述

    python脚本的形式如下(仍在处理一个独立的示例):

    启动脚本Theano使用指定的设备,但一段时间后,另一个python线程出现在另一个图形卡上(并耗尽资源)

    第二个线程似乎忽略了配置,因为它在错误的GPU上运行,并且没有按照
    CNEM
    标志指定的方式分配ram

    根据文档,这是不可能的,因为从启动Theano计算的线程派生的所有内容都应该在同一个设备上运行(通过在开始时正确导入Theano来确保)

    经过一番探索,我发现当我没有在单独的线程中运行Keras代码时,这种行为就会停止

    因此,在我开始创建Github问题之前,我想了解一些最有可能的建议:

  • 这是Theano里的虫子吗
  • 这是Keras的一只虫子吗
  • 这是我自己代码中的错误吗
  • @三,。我的整个项目不创建单独的Python进程(通过进程列表确认),也不更改任何Theano配置

    知道什么会导致这种行为吗?

    一个线程的设备(gpu)设置与同一进程中的其他线程是独立的。寻找更多细节

    在Theano中,我还没有找到为当前线程设置设备的方法。我使用过时的
    cuda\u ndarray
    后端,没有办法做到这一点,但我不知道在
    gpuarray
    后端是否有办法做到这一点

    我做了一些变通:

    import numpy as np
    import theano
    from theano import Apply
    from theano import tensor as T
    from theano.scalar import Scalar
    from theano.sandbox.cuda import GpuOp, nvcc_compiler
    
    class SetGpu(GpuOp):
        '''
        Set device(gpu) for current thread.
        '''
    
        def c_compiler(self):
            return nvcc_compiler.NVCC_compiler
    
        def make_node(self, gpu_id):
            dummy_out = Scalar("int32")()
            return Apply(self, [gpu_id], [dummy_out])
    
        def __str__(self):
            return "SetGpu"
    
        def c_support_code_apply(self, node, nodename):
            return ""
    
        def c_code(self, node, nodename, inps, outs, sub):
            gpu_id, = inps
            dummy_out, = outs
            return """
            int _gpu_id = *((int*)PyArray_DATA(%(gpu_id)s));
            %(dummy_out)s = _gpu_id;
            cudaError_t err = cudaSetDevice(_gpu_id);
            if(err != cudaSuccess){
                PyErr_Format(PyExc_RuntimeError, "Cuda err:\\"%%s\\" when calling cudaSetDevice(%%d).", cudaGetErrorString(err), _gpu_id);
                return 0;
            }
        """ % locals()
    
    def set_gpu(gpu_id):
        if not hasattr(set_gpu, "f"):
            set_gpu_op = SetGpu()
            gpu_id_var = T.iscalar()
            dummy_out = set_gpu_op(gpu_id_var)
            set_gpu.f = theano.function([gpu_id_var], [dummy_out])
        _dummy_out = set_gpu.f(gpu_id)
    
    if __name__ == "__main__":
        def test():
            set_gpu(5)
            print "Test thread is using gpu %d." % theano.sandbox.cuda.active_device_number()
        print "Main thread is using gpu %d." % theano.sandbox.cuda.active_device_number()
        from threading import Thread
        thread = Thread(target=test)
        thread.start()
        thread.join()
    
    因此,我们将此文件称为set\gpu.py

    下面是我运行它的结果:

    python set_gpu.py 
    WARNING (theano.sandbox.cuda): The cuda backend is deprecated and will be removed in the next release (v0.10).  Please switch to the gpuarray backend. You can get more information about how to switch at this URL:
     https://github.com/Theano/Theano/wiki/Converting-to-the-new-gpu-back-end%28gpuarray%29
    
    Using gpu device 0: Tesla K80 (CNMeM is enabled with initial size: 95.0% of memory, cuDNN 5110)
    Main thread is using gpu 0.
    Test thread is using gpu 5.
    
    一个线程的设备(gpu)设置独立于同一进程中的其他线程。寻找更多细节

    在Theano中,我还没有找到为当前线程设置设备的方法。我使用过时的
    cuda\u ndarray
    后端,没有办法做到这一点,但我不知道在
    gpuarray
    后端是否有办法做到这一点

    我做了一些变通:

    import numpy as np
    import theano
    from theano import Apply
    from theano import tensor as T
    from theano.scalar import Scalar
    from theano.sandbox.cuda import GpuOp, nvcc_compiler
    
    class SetGpu(GpuOp):
        '''
        Set device(gpu) for current thread.
        '''
    
        def c_compiler(self):
            return nvcc_compiler.NVCC_compiler
    
        def make_node(self, gpu_id):
            dummy_out = Scalar("int32")()
            return Apply(self, [gpu_id], [dummy_out])
    
        def __str__(self):
            return "SetGpu"
    
        def c_support_code_apply(self, node, nodename):
            return ""
    
        def c_code(self, node, nodename, inps, outs, sub):
            gpu_id, = inps
            dummy_out, = outs
            return """
            int _gpu_id = *((int*)PyArray_DATA(%(gpu_id)s));
            %(dummy_out)s = _gpu_id;
            cudaError_t err = cudaSetDevice(_gpu_id);
            if(err != cudaSuccess){
                PyErr_Format(PyExc_RuntimeError, "Cuda err:\\"%%s\\" when calling cudaSetDevice(%%d).", cudaGetErrorString(err), _gpu_id);
                return 0;
            }
        """ % locals()
    
    def set_gpu(gpu_id):
        if not hasattr(set_gpu, "f"):
            set_gpu_op = SetGpu()
            gpu_id_var = T.iscalar()
            dummy_out = set_gpu_op(gpu_id_var)
            set_gpu.f = theano.function([gpu_id_var], [dummy_out])
        _dummy_out = set_gpu.f(gpu_id)
    
    if __name__ == "__main__":
        def test():
            set_gpu(5)
            print "Test thread is using gpu %d." % theano.sandbox.cuda.active_device_number()
        print "Main thread is using gpu %d." % theano.sandbox.cuda.active_device_number()
        from threading import Thread
        thread = Thread(target=test)
        thread.start()
        thread.join()
    
    因此,我们将此文件称为set\gpu.py

    下面是我运行它的结果:

    python set_gpu.py 
    WARNING (theano.sandbox.cuda): The cuda backend is deprecated and will be removed in the next release (v0.10).  Please switch to the gpuarray backend. You can get more information about how to switch at this URL:
     https://github.com/Theano/Theano/wiki/Converting-to-the-new-gpu-back-end%28gpuarray%29
    
    Using gpu device 0: Tesla K80 (CNMeM is enabled with initial size: 95.0% of memory, cuDNN 5110)
    Main thread is using gpu 0.
    Test thread is using gpu 5.
    

    因为你没有共享任何代码,所以很难说。。。我可以看到你正在运行一个线程。。。但没有更多…这就是为什么我问这怎么可能发生的原因(我仍然在做一个独立的例子,因为我目前无法使用一个以上的图形卡访问计算机)。就像那样,我会说这可能是你的代码,但Theano可能会有这样的问题,对凯拉斯来说,这会很奇怪,但为什么不呢?你能告诉我该找什么吗?我想我直接用Theano做的唯一一件事就是为Keras定义一个自定义损失函数。。。我可以看到你正在运行一个线程。。。但没有更多…这就是为什么我问这怎么可能发生的原因(我仍然在做一个独立的例子,因为我目前无法使用一个以上的图形卡访问计算机)。就像那样,我会说这可能是你的代码,但Theano可能会有这样的问题,对凯拉斯来说,这会很奇怪,但为什么不呢?你能告诉我该找什么吗?我想我直接用Theano做的唯一一件事就是为Keras定义一个自定义损失函数。