8

这是一个长镜头,如果您认为问题过于本地化,请投票结束。我在caffe2 github存储库上进行了搜索,打开了一个问题来询问相同的问题,在caffe2_ccp_tutorials存储库中打开了另一个问题,因为它的作者似乎最了解它,阅读了caffe2::Tensorcaffe2::CUDAContext上的 doxygen 文档,甚至浏览了 caffe2 的源代码,特别是tensor.h,context_gpu.hcontext_gpu.cc.

我知道目前caffe2 不允许将设备内存复制到 tensor。我愿意扩展图书馆并提出拉取请求以实现这一目标。我这样做的原因是我使用cv::cuda::*在设备内存上运行的方法进行所有图像预处理,因此我认为在 gpu 上进行预处理显然是一个问题,只是将结果下载回主机上,然后让它从主机到设备重新上传到网络。

看着构造函数Tensor<Context>我可以看到,也许只有

template<class SrcContext , class ContextForCopy > 
Tensor (const Tensor< SrcContext > &src, ContextForCopy *context)

可能会实现我想要的,但我不知道如何设置<ContextForCopy>然后将其用于构造。

此外,我看到我可以构建具有正确尺寸的张量,然后可能使用

template <typename T>
T* mutable_data()

我可以分配/复制数据。数据本身存储在 中std::vector<cv::cuda::GpuMat,因此我必须对其进行迭代,然后使用cuda::PtrStepSzcuda::PtrStep访问底层设备分配的数据。这与我需要复制/分配到caffe2::Tensor<CUDAContext>.

自从我看到它的例子以来,我一直试图找出它是如何在内部Tensor<CPUContext>复制Tensor<CUDAContext>的,但我无法弄清楚,尽管我认为使用的方法是CopyFrom. 如前所述,通常的示例是从 CPU 复制到 GPU:

TensorCPU tensor_cpu(...);
TensorCUDA tensor_cuda = workspace.CreateBlob("input")->GetMutable<TensorCUDA>();
tensor_cuda->ResizeLike(tensor_cpu);
tensor_cuda->ShareData(tensor_cpu);

我很惊讶还没有人遇到过这个任务,并且简短的搜索只产生一个未解决的问题,作者(@peterneher)或多或少地问同样的事情。

4

1 回答 1

1

我已经设法弄清楚了。最简单的方法是告诉 OpenCV使用哪个内存位置。这可以通过使用构造函数的第 7 次和第 8 次重载cv::cuda::GpuMat来完成,如下所示:

cv::cuda::GpuMat::GpuMat(int    rows,
                         int    cols,
                         int    type,
                         void *     data,
                         size_t     step = Mat::AUTO_STEP 
                        )       

cv::cuda::GpuMat::GpuMat(Size   size,
                         int    type,
                         void *     data,
                         size_t     step = Mat::AUTO_STEP 
                        )       

这样做意味着caffe2::TensorCUDA已经事先声明并分配了:

std::vector<caffe2::TIndex> dims({1, 3, 224, 224});
caffe2::TensorCUDA tensor;
auto ptr = tensor.mutable_data<float>();
cv::cuda::GpuMat matrix(224, 224, CV_32F, ptr);

例如,使用以下方法处理 3 通道 BGR 浮点矩阵cv::cuda::split

cv::cuda::GpuMat mfloat;
// TODO: put your BGR float data in `mfloat`
auto ptr = tensor.mutable_data<float>();
size_t width = mfloat.cols * mfloat.rows;
std::vector<cv::cuda::GpuMat> input_channels {
    cv::cuda::GpuMat(mfloat.rows, mfloat.cols, CV_32F, &ptr[0]),
    cv::cuda::GpuMat(mfloat.rows, mfloat.cols, CV_32F, &ptr[width]),
    cv::cuda::GpuMat(mfloat.rows, mfloat.cols, CV_32F, &ptr[width * 2])
};
cv::cuda::split(mfloat, input_channels);

希望这将帮助任何居住在 Caffe2 的 C++ 方面的人。

注意,这caffe2::Predictor不适用于caffe2::TensorCUDA,您将不得不手动传播张量。有关这方面的更多信息,请参阅 caffe2_cpp_tutorial mnist.cc

于 2017-11-14T12:09:27.540 回答