Caffe Python MemoryDataLayer Segmentation Fault


轉載請注明出處,樓燚(yì)航的blog,http://home.cnblogs.com/louyihang-loves-baiyan/

因為利用Pyhon來做數據的預處理比較方便,因此在data_layer選擇上,采用了MemoryDataLayer,可以比較方便的直接用Python 根據set_input_array進行feed數據,然后再調用solver進行step就可以了。說一下我碰到的問題,當時檢查了一下感覺沒有哪里出錯,但是報

Segmentation Fault(Core Abort)

感覺好囧,最怕這個了。一般說段錯誤都是內存錯誤,比如數組越界,無效的指針,引用被釋放的資源等等。經過一步步debug之后發現問題出現在

solver.net.set_input_arrays

solver在將數據傳送到網絡低端的時候報錯。那么接下來找到python目錄下的caffe\python\caffe\_caffe.cpp文件,這個文件是基於boost python的,用來將C++的接口導出,供python調用。進一步我們找到相關函數

void Net_SetInputArrays(Net<Dtype>* net, bp::object data_obj,
    bp::object labels_obj) {
  // check that this network has an input MemoryDataLayer
  shared_ptr<MemoryDataLayer<Dtype> > md_layer =
    boost::dynamic_pointer_cast<MemoryDataLayer<Dtype> >(net->layers()[0]);
  if (!md_layer) {
    throw std::runtime_error("set_input_arrays may only be called if the"
        " first layer is a MemoryDataLayer");
  }
  // check that we were passed appropriately-sized contiguous memory
  PyArrayObject* data_arr =
      reinterpret_cast<PyArrayObject*>(data_obj.ptr());
  PyArrayObject* labels_arr =
      reinterpret_cast<PyArrayObject*>(labels_obj.ptr());
  CheckContiguousArray(data_arr, "data array", md_layer->channels(),
      md_layer->height(), md_layer->width());
  CheckContiguousArray(labels_arr, "labels array", 1, 1, 1);
  if (PyArray_DIMS(data_arr)[0] != PyArray_DIMS(labels_arr)[0]) {
    throw std::runtime_error("data and labels must have the same first"
        " dimension");
  }
  if (PyArray_DIMS(data_arr)[0] % md_layer->batch_size() != 0) {
    throw std::runtime_error("first dimensions of input arrays must be a"
        " multiple of batch size");
  }
  md_layer->Reset(static_cast<Dtype*>(PyArray_DATA(data_arr)),
      static_cast<Dtype*>(PyArray_DATA(labels_arr)),
      PyArray_DIMS(data_arr)[0]);
}

問題就出在了最后的一個語句

 md_layer->Reset(static_cast<Dtype*>(PyArray_DATA(data_arr)),
      static_cast<Dtype*>(PyArray_DATA(labels_arr)),
      PyArray_DIMS(data_arr)[0]);

當執行reset MemoryDataLayer的Reset函數時出錯。於此同時在github上也發現了同樣的問題,https://github.com/BVLC/caffe/issues/2334也是因為Python MemoryDataLayer引發的段錯誤。他說到,在里面把傳入的data和label做要給深拷貝就可以解決,估計是運行時數據已經被釋放了,只傳了指針引發了段錯誤。

解決方案:
找到caffe\src\layers\memory_data_layer.cpp打開,給Reset函數添加相應的深拷貝代碼

template <typename Dtype>
void MemoryDataLayer<Dtype>::Reset(Dtype* data, Dtype* labels, int n) {
  CHECK(data);
  CHECK(labels);
  CHECK_EQ(n % batch_size_, 0) << "n must be a multiple of batch size";
  // Warn with transformation parameters since a memory array is meant to
  // be generic and no transformations are done with Reset().
  if (this->layer_param_.has_transform_param()) {
    LOG(WARNING) << this->type() << " does not transform array data on Reset()";
  }
  // data_ = data; 將這里注釋掉,
  // labels_ = labels;

  //以下部分是進行深拷貝
  if(data_)
      delete []data_;
  if(labels_)
      delete [] labels_;
  data_ = new Dtype[n*size_];
  labels_ = new Dtype[n * num_tasks_];

  memcpy(data_, data, sizeof(Dtype)*n*size_);
  memcpy(labels_, labels, sizeof(Dtype) * n * num_tasks_);

  n_ = n;
  pos_ = 0;
}

Ok進行修改之后,回到Caffe的根目錄,執行make all,make test,``make runtest,make pycaffe`。重新編譯完成之后,重新運行就好了,繼續開始訓練。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM