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

Caffe 将同一网络的某些节点放在GPU上,而将其他节点放在CPU上?,caffe,pycaffe,caffe2,Caffe,Pycaffe,Caffe2,在Caffe/Caffe2中定义网络时,能否将一些节点放在CPU上,而将其他节点放在GPU上?如果是,怎么做 (如果您的答案与Caffe的特定版本有关,请指定哪个版本)不,不可能。如果查看solver.prototxt文件,您会注意到可以将模式指定为CPU或GPU,但不能同时指定两者。保持这种执行结构的原因是为了保持效率。CNN每层生成的数据可能以兆字节为单位。如果将网络的一部分放在CPU上,另一部分放在GPU上,则需要在设备之间来回传输大量数据。这将增加巨大的开销,这将完全取消GPU提供的杠杆

在Caffe/Caffe2中定义网络时,能否将一些节点放在CPU上,而将其他节点放在GPU上?如果是,怎么做


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

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

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

一般来说,答案是:由于所述原因,您无法为每一层单独配置设备

但是如果您查看特定的层,有时可能会得到所需的行为。例如,如果您的解算器配置为在GPU上运行,但您的网络中有一层没有GPU实现,那么该层将在CPU上运行(所有开销如中所述)。
一个这样的层是一个层:这个层只在CPU上运行,您可以在那里实现
word2vec

或者,您可以编写自己的层,而不使用GPU实现,以确保它们仅在CPU上运行


顺便说一句,你用的是caffe2吗?你同意他们的条款吗

更新:似乎fb决定购买caffe2的许可证。干得好

在创建所需节点及其blob之前,使用DeviceScope和相关设备选项(CPU/GPU)设备类型

简单的例子:

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())
  • 不要忘记在喂食它的斑点之前做同样的事情,否则,你希望能够接触到它们
输出为:

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"

谢谢你的前两句话,但我认为其余的都不正确。(1) 如果设置正确,PCIe带宽可与RAM带宽相媲美(2)在CPU上保留word2vec参数,而在GPU上执行其余操作实际上是很常见的。。。因为GPU内存是有限的,我觉得这里有点误解。我的意思是CPU内部总线比PCIe快,尽管这条信息在这里可能并不完全相关。第二点-GPU对SIMD操作很好,但CPU对涉及分支/决策的操作更好。word2vec涉及决策制定,因此它在CPU上更高效。但这是一个预处理步骤,可以在初始阶段在CPU上完成,但这并不意味着你可以一直做来来回回的事情。预处理不是真正意义上的网络的一部分。还要注意,我是从图像的角度讲的。但即使是在图像的情况下,预处理通常是在CPU本身上完成的。顺便说一句,如果你使用的是像Titan X这样的高端卡,那么现在的GPU RAM和CPU RAM一样多。“你同意他们的专利条款吗?!”看起来和Apache(谷歌发布的所有产品)一样,但是IANAL.@MaxB(1)IANAL也一样,但据我所知,它更具限制性,包括任何专利纠纷,即使是与CaFe2无关的专利。(2) 考虑到caffe1根本没有这种限制,而且caffe的强度主要来自社区开发的自由分布模型,而不是FB,这是相当令人不安的。