void OctreeBaseConvLayer::LayerSetUp()

in caffe/src/caffe/layers/octree_base_conv_layer.cpp [19:134]


void OctreeBaseConvLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
    const vector<Blob<Dtype>*>& top) {
  // kernel size
  ConvolutionParameter conv_param = this->layer_param_.convolution_param();
  size_t kss = conv_param.kernel_size_size();
  CHECK(kss == 1 || kss == 3) << "Specify 1 or 3 kernel_size paramters";
  kernel_size_.resize(3);
  if (kss == 1) {
    kernel_size_[0] = conv_param.kernel_size(0);
    kernel_size_[1] = conv_param.kernel_size(0);
    kernel_size_[2] = conv_param.kernel_size(0);
  } else {
    kernel_size_[0] = conv_param.kernel_size(0);
    kernel_size_[1] = conv_param.kernel_size(1);
    kernel_size_[2] = conv_param.kernel_size(2);
  }
  CHECK(kernel_size_[0] < 4 && kernel_size_[1] < 4 && kernel_size_[2] < 4)
      << "kernel_size should be less than 4";
  kernel_sdim_ = kernel_size_[0] * kernel_size_[1] * kernel_size_[2];

  // stride
  CHECK_LE(conv_param.stride_size(), 1);
  stride_ = conv_param.stride_size() == 0 ? 1 : conv_param.stride(0);
  CHECK_LE(stride_, 2) << "stride should be less than 2";

  // special case: im2col is the identity for 1x1 convolution with stride 1
  is_1x1_ = kernel_size_[0] == 1 && kernel_size_[1] == 1 &&
      kernel_size_[2] == 1 && stride_ == 1;

  // current octree depth
  CHECK(this->layer_param_.octree_param().has_curr_depth())
      << "Error in " << this->layer_param_.name() << ": "
      << "The octree depth of bottom blob should be set coreectly.";
  curr_depth_ = this->layer_param_.octree_param().curr_depth();
  //curr_depth_ = Octree::get_curr_depth();
  //if (stride_ == 2) {
  //	if (is_deconvolution_layer()) Octree::set_curr_depth(curr_depth_ + 1);
  //	else Octree::set_curr_depth(curr_depth_ - 1);
  //}

  // channels & num_output_
  channels_ = conv_in_channels_ = bottom[0]->shape(1);
  num_output_ = conv_out_channels_ = conv_param.num_output();
  if (is_deconvolution_layer()) {
    std::swap(conv_out_channels_, conv_in_channels_);
  }

  // Handle the parameters: weights and biases.
  // - blobs_[0] holds the filter weights
  // - blobs_[1] holds the biases (optional)
  vector<int> weight_shape{ conv_out_channels_, conv_in_channels_, kernel_sdim_, 1 };
  vector<int> bias_shape;
  bias_term_ = conv_param.bias_term();
  if (bias_term_) bias_shape.push_back(num_output_);

  if (this->blobs_.size() > 0) {
    CHECK_EQ(1 + bias_term_, this->blobs_.size())
        << "Incorrect number of weight blobs.";
    if (weight_shape != this->blobs_[0]->shape()) {
      Blob<Dtype> weight_shaped_blob(weight_shape);
      LOG(FATAL) << "Incorrect weight shape: expected shape "
          << weight_shaped_blob.shape_string()
          << "; instead, shape was "
          << this->blobs_[0]->shape_string();
    }
    if (bias_term_ && bias_shape != this->blobs_[1]->shape()) {
      Blob<Dtype> bias_shaped_blob(bias_shape);
      LOG(FATAL) << "Incorrect bias shape: expected shape "
          << bias_shaped_blob.shape_string()
          << "; instead, shape was "
          << this->blobs_[1]->shape_string();
    }
    LOG(INFO) << "Skipping parameter initialization";
  } else {
    if (bias_term_) this->blobs_.resize(2);
    else this->blobs_.resize(1);

    // Initialize and fill the weights:
    this->blobs_[0].reset(new Blob<Dtype>(weight_shape));
    shared_ptr<Filler<Dtype>> weight_filler(
            GetFiller<Dtype>(conv_param.weight_filler()));
    weight_filler->Fill(this->blobs_[0].get());

    // If necessary, initialize and fill the biases.
    if (bias_term_) {
      this->blobs_[1].reset(new Blob<Dtype>(bias_shape));
      shared_ptr<Filler<Dtype> > bias_filler(
          GetFiller<Dtype>(conv_param.bias_filler()));
      bias_filler->Fill(this->blobs_[1].get());
    }
  }
  kernel_dim_ = this->blobs_[0]->count(1);

  // Propagate gradients to the parameters (as directed by backward pass).
  this->param_propagate_down_.resize(this->blobs_.size(), true);

  // set the pointer of workspace
  workspace_ = Octree::get_workspace(Dtype(0), 0);
  result_buffer_ = Octree::get_workspace(Dtype(0), 1);
  // for the deconv layer, the following code is wrong in the backward pass
  //data_buffer_ = Octree::get_workspace(Dtype(0), 2);
  data_buffer_.reset(new Blob<Dtype>());

#if defined(USE_CUDNN) && !defined(CPU_ONLY)
  // cudnn
  CUDNN_CHECK(cudnnCreate(&handle_));
  cudnn::createFilterDesc<Dtype>(&filter_desc_, weight_shape[0],
      weight_shape[1], weight_shape[2], weight_shape[3]);
  cudnn::createTensor4dDesc<Dtype>(&bottom_desc_);
  cudnn::createTensor4dDesc<Dtype>(&top_desc_);
  cudnn::createConvolutionDesc<Dtype>(&conv_desc_);
  filter_workspace_size_ = 8 * 1024 * 1024;
  vector<int> filter_workspace_shape(1, filter_workspace_size_);
  filter_workspace_.Reshape(filter_workspace_shape);
#endif //USE_CUDNN
}