将相同网络的某些节点放在GPU上,将其他节点放在CPU上?

时间:2017-06-05 03:17:00

标签: caffe pycaffe caffe2

在Caffe / Caffe2中定义网络时,您是否可以在CPU上放置一些节点,在GPU上放置其他节点?如果是这样,怎么样?

(如果您的答案与Caffe的特定版本相关,请指明哪个)

4 个答案:

答案 0 :(得分:1)

不,这是不可能的。如果查看solver.prototxt文件,您会注意到您可以将模式指定为CPU或GPU,但不能同时指定两者。保持这种执行结构的原因是为了保持效率。 CNN的每一层生成的数据可能以兆字节为单位。如果您将部分网络保留在CPU上并将其中的一部分保留在GPU上,则需要在设备之间来回传输大量数据。这将增加巨大的开销,这将完全取消GPU给出的杠杆作用。因此,在CPU上训练整个网络而不是CPU-GPU组合更有效。另请注意,GPU通过PCIe接口与CPU连接,该接口明显慢于内部CPU总线。因此,设备之间的数据传输非常昂贵。这就是为什么更大的批量大小是训练CNN的首选原因之一,因为一堆图像可以立即发送到GPU,避免重复的内存读写。

答案 1 :(得分:1)

这可能在Caffe2中实际可行,但我从未测试过它。 在Caffe2中,每个blob和operator都有一个分配给它的设备。操作员在分配给它的设备上运行。但是,您需要手动处理初始化和通信,因为Caffe2中的data_parallel_model仅适用于多GPU设置。

答案 2 :(得分:1)

一般来说,答案是:由于Pooya DavoodiHarsh Wardhan描述的原因,您无法单独为每个图层配置设备。

但是,如果您查看特定图层,有时可能会获得您要查找的行为。例如,如果您的求解器配置为在GPU上运行,但您的网络中有一个没有GPU实现的层,那么该层将在CPU上运行(具有Harsh Wardhan's answer中描述的所有开销) 。
一个这样的图层是"Python"图层:此图层仅在CPU上运行,您可以在那里执行word2vec
或者,您可以在没有GPU实现的情况下编写自己的图层,确保它们仅在CPU上运行。

BTW,你在使用caffe2吗?你对他们的PATENTS条款没问题吗?!
更新:似乎fb决定soften caffe2的许可证。做得好!

答案 3 :(得分:0)

在创建所需的节点及其Blob之前,将DeviceScope与相关的DeviceOption(CPU / GPU)device_type一起使用

简单的例子:

from caffe2.python import workspace, model_helper
from caffe2.proto import caffe2_pb2
from caffe2.python import core
import numpy as np

m = model_helper.ModelHelper(name="my first net")
data = np.random.rand(16, 100).astype(np.float32)
gpu_device_id = 1
cpu_device_id = -1
with core.DeviceScope(core.DeviceOption(workspace.GpuDeviceType, gpu_device_id)):
    with core.DeviceScope(core.DeviceOption(caffe2_pb2.CPU, cpu_device_id)):
        # Feed relevant blobs
        workspace.FeedBlob("data", data)
        weight = m.param_init_net.XavierFill([], 'fc_w', shape=[10, 100])
        bias = m.param_init_net.ConstantFill([], 'fc_b', shape=[10, ])
        # Create you cpu Node
        fc_1 = m.net.FC(["data", "fc_w", "fc_b"], "fc1")
    # Create GPU Node
    pred = m.net.Sigmoid(fc_1, "pred")
    softmax, loss = m.net.SoftmaxWithLoss([pred, "label"], ["softmax", "loss"])

print(m.net.Proto())
  • 别忘了在喂食blob之前做同样的事情,否则,您希望能够到达它们。

输出为:

name: "my first net"
op {
name: "my first net"
op {
  input: "data"
  input: "fc_w"
  input: "fc_b"
  output: "fc1"
  name: ""
  type: "FC"
  device_option {
    device_type: 0
    device_id: -1
  }
}
op {
  input: "fc1"
  output: "pred"
  name: ""
  type: "Sigmoid"
  device_option {
    device_type: 1
    device_id: 1
  }
}
op {
  input: "pred"
  input: "label"
  output: "softmax"
  output: "loss"
  name: ""
  type: "SoftmaxWithLoss"
  device_option {
    device_type: 1
    device_id: 1
  }
}
external_input: "data"
external_input: "fc_w"
external_input: "fc_b"
external_input: "label"