void OctreeBaseConvLayer::Reshape()

in caffe/src/caffe/layers/octree_base_conv_layer.cpp [137:220]


void OctreeBaseConvLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
    const vector<Blob<Dtype>*>& top) {
  // a workaround for the first time reshape
  if (top[0]->count() == 0) {
    vector<int> top_shape = bottom[0]->shape();
    top_shape[1] = num_output_;
    top_shape[2] = 8;
    top[0]->Reshape(top_shape);
    return;
  }

  // set octree_batch_
  bool octree_in = bottom.size() == 2;
  Blob<Dtype>& the_octree = octree_in ? *bottom[1] : Octree::get_octree(Dtype(0));
  octree::set_octree_parser(octree_batch_, the_octree);

  // check bottom shape
  int bottom_h = bottom[0]->shape(2);
  int nnum = octree_batch_.info().node_num(curr_depth_);
  if (nnum != 0) {
    CHECK_EQ(bottom_h, nnum)
        << "The octree node number is inconsistent in " << this->layer_param_.name()
            << ", and the curr_depth_ = " << curr_depth_;
  } else {
    CHECK_EQ(bottom_h, 1);
    LOG(INFO) << "Warning in layer" << this->layer_param().name()
        << ": This octree layer is empty";
  }

  // compute top shape
  int top_blob_depth = curr_depth_;
  if (stride_ == 2) {
    if (is_deconvolution_layer()) top_blob_depth++;
    else top_blob_depth--;
    CHECK(0 <= top_blob_depth && top_blob_depth <= octree_batch_.info().depth())
        << "Error in " << this->layer_param_.name() << ": top_blob_depth "
            << top_blob_depth << "- octree_depth " << octree_batch_.info().depth();
  }
  int top_h = octree_batch_.info().node_num(top_blob_depth);
  if (top_h == 0) top_h = 1;
  vector<int> top_shape{ 1, num_output_, top_h, 1 };
  top[0]->Reshape(top_shape);

  // reshape workspce
  workspace_depth_ = curr_depth_;
  if (is_deconvolution_layer() && stride_ == 2) workspace_depth_++;
  workspace_h_ = bottom_h;
  if (stride_ == 2) {
    if (is_deconvolution_layer()) workspace_h_ = top_h >> 3;
    else workspace_h_ = bottom_h >> 3;
  }
  workspace_n_ = 1;
  workspace_ha_ = workspace_h_;
  // In some other layers, such as octree_pooling, the workspace blob is also
  // resized, without considering the get_workspace_maxsize(), the actual
  // size of workspace might be larger than get_workspace_maxsize(), so 
  // calculate the MAX_SIZE from get_workspace_maxsize() and its original count()
  const int MAX_SIZE = std::max(Octree::get_workspace_maxsize(), workspace_->count());
  int ideal_size = workspace_h_ * kernel_dim_;
  if (ideal_size > MAX_SIZE && !is_1x1_) {
    workspace_n_ = (ideal_size + MAX_SIZE - 1) / MAX_SIZE;
    workspace_ha_ = (workspace_h_ + workspace_n_ - 1) / workspace_n_;
  }
  workspace_->Reshape(vector<int> { 1, kernel_dim_, workspace_ha_, 1 });

  // reshape result_buffer_
  if (workspace_n_ > 1) {
    result_buffer_->Reshape(vector<int> { conv_out_channels_, workspace_ha_ });
  }

  // reshape data_buffer_
  if (stride_ == 2) {
    data_buffer_shape_ = vector<int> { 1, conv_out_channels_, workspace_h_, 1 };
    data_buffer_->Reshape(data_buffer_shape_);
  }

  // Set up the all ones "bias multiplier" for adding biases by BLAS
  if (bias_term_) {
    bias_multiplier_h_ = is_deconvolution_layer() ? top_h : workspace_h_;
    bias_multiplier_.Reshape(vector<int> { bias_multiplier_h_ });
    caffe_set(bias_multiplier_.count(), Dtype(1),
        bias_multiplier_.mutable_cpu_data());
  }
}