Это долгий путь, если вы думаете, что вопрос слишком локализован, пожалуйста, проголосуйте, чтобы закрыть. Я искал на caffe2 github хранилище, открытое проблема задавая тот же вопрос, открыл еще один вопрос на caffe2_ccp_tutorials хранилище, потому что его автор, кажется, понимает это лучше, прочитайте документацию по Doxygen caffe2 :: Тензор а также caffe2 :: CUDAContext,
и даже прошел через caffe2 исходный код, и в частности tensor.h
, context_gpu.h
а также context_gpu.cc
,
Я понимаю что сейчас caffe2 не позволяет копировать память устройства в тензор. Я хочу расширить библиотеку и сделать запрос на получение доступа для достижения этой цели. Моя причина в том, что я делаю всю предварительную обработку изображений, используя 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::PtrStepSz
или же cuda::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) просит то же самое более или менее.
Мне удалось выяснить это.
Самый простой способ — рассказать 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);
Надеюсь, что это поможет любому, кто углубится в C ++ сторону Caffe2.
НОТА тот caffe2::Predictor
не будет работать с caffe2::TensorCUDA
вместо этого вам придется размножать тензор вручную.
Для получения дополнительной информации об этом, caffe2_cpp_tutorial mnist.cc.
Других решений пока нет …