| 803 | |
| 804 | template <typename TensorDataType, El::Device Device> |
| 805 | void base_convolution_layer<TensorDataType, Device>::apply_convolution_im2col( |
| 806 | bool during_forward_prop) |
| 807 | { |
| 808 | |
| 809 | // Local matrices |
| 810 | const auto& local_kernel = this->weights_values(0).LockedMatrix(); |
| 811 | const auto& local_input = |
| 812 | (during_forward_prop ? this->get_local_prev_activations() |
| 813 | : this->get_local_prev_error_signals()); |
| 814 | auto& local_output = (during_forward_prop ? this->get_local_activations() |
| 815 | : this->get_local_error_signals()); |
| 816 | |
| 817 | // Matrix parameters |
| 818 | const int output_size = local_output.Height(); |
| 819 | const El::Int local_width = local_input.Width(); |
| 820 | std::vector<int> input_dims, output_dims; |
| 821 | if (during_forward_prop) { |
| 822 | input_dims = this->get_input_dims(); |
| 823 | output_dims = this->get_output_dims(); |
| 824 | } |
| 825 | else { |
| 826 | input_dims = this->get_output_dims(); |
| 827 | output_dims = this->get_input_dims(); |
| 828 | } |
| 829 | const auto& kernel_dims = this->get_kernel_dims(); |
| 830 | const auto kernel_size = get_linear_size(kernel_dims); |
| 831 | |
| 832 | // Initialize matrices |
| 833 | const int m = output_size / output_dims[0]; |
| 834 | const int n = output_dims[0]; |
| 835 | const int k = kernel_size / output_dims[0]; |
| 836 | DMatDT<Device> input_col, output_col; |
| 837 | DMatDT<Device> im2col_matrix(k, m); |
| 838 | const DMatDT<Device> kernel_matrix(k, n, local_kernel.LockedBuffer(), k); |
| 839 | |
| 840 | // Iterate through input columns |
| 841 | for (El::Int col = 0; col < local_width; ++col) { |
| 842 | |
| 843 | // Construct im2col matrix from current input column |
| 844 | El::LockedView(input_col, local_input, El::ALL, El::IR(col)); |
| 845 | im2col<TensorDataType>(input_col, |
| 846 | im2col_matrix, |
| 847 | input_dims[0], |
| 848 | input_dims.size() - 1, |
| 849 | &input_dims[1], |
| 850 | m_pads.data(), |
| 851 | &kernel_dims[2], |
| 852 | m_strides.data()); |
| 853 | |
| 854 | // Apply convolution to current input column |
| 855 | output_col.Attach(m, n, local_output.Buffer(0, col), m); |
| 856 | El::Gemm(El::TRANSPOSE, |
| 857 | El::NORMAL, |
| 858 | El::TypeTraits<TensorDataType>::One(), |
| 859 | im2col_matrix, |
| 860 | kernel_matrix, |
| 861 | El::TypeTraits<TensorDataType>::Zero(), |
| 862 | output_col); |
nothing calls this directly
no test coverage detected