/usr/local/lib64/python3.6/site-packages/torch/include/caffe2/operators
NameSizeModeActions
abs_op.h7050644editdlrm
accumulate_op.h10730644editdlrm
accuracy_op.h6520644editdlrm
acos_op.h7110644editdlrm
activation_ops_cudnn.h41220644editdlrm
affine_channel_op.h34500644editdlrm
alias_with_name.h12340644editdlrm
apmeter_op.h10270644editdlrm
arg_ops.h23190644editdlrm
asin_op.h7110644editdlrm
assert_op.h13350644editdlrm
async_net_barrier_op.h9040644editdlrm
atan_op.h7110644editdlrm
batch_box_cox_op.h22870644editdlrm
batch_bucketize_op.h7200644editdlrm
batch_gather_ops.h52640644editdlrm
batch_matmul_op.h96020644editdlrm
batch_moments_op.h33640644editdlrm
batch_permutation_op.h9540644editdlrm
batch_sparse_to_dense_op.h61470644editdlrm
bbox_transform_op.h26680644editdlrm
bisect_percentile_op.h49210644editdlrm
boolean_mask_ops.h26650644editdlrm
boolean_unmask_ops.h3780644editdlrm
box_with_nms_limit_op.h49600644editdlrm
bucketize_op.h13610644editdlrm
byte_weight_dequant_op.h17220644editdlrm
cast_op.h13930644editdlrm
cbrt_op.h7230644editdlrm
cc_bmm_bg_op.h38940644editdlrm
ceil_op.h7820644editdlrm
channel_backprop_stats_op.h7370644editdlrm
channel_shuffle_op.h19020644editdlrm
channel_stats_op.h18070644editdlrm
clip_op.h16390644editdlrm
collect_and_distribute_fpn_rpn_proposals_op.h68750644editdlrm
concat_split_op.h118500644editdlrm
conditional_op.h4870644editdlrm
conv_op.h31250644editdlrm
conv_op_cache_cudnn.h19350644editdlrm
conv_op_impl.h287290644editdlrm
conv_op_shared.h6720644editdlrm
conv_pool_op_base.h321090644editdlrm
conv_transpose_op.h17270644editdlrm
conv_transpose_op_impl.h182640644editdlrm
conv_transpose_op_mobile.h14700644editdlrm
conv_transpose_op_mobile_impl.h195870644editdlrm
conv_transpose_unpool_op_base.h103030644editdlrm
copy_op.h12960644editdlrm
copy_rows_to_tensor_op.h25990644editdlrm
cosh_op.h7110644editdlrm
cosine_embedding_criterion_op.h11270644editdlrm
cos_op.h7050644editdlrm
counter_ops.h45960644editdlrm
create_scope_op.h52320644editdlrm
cross_entropy_op.h44200644editdlrm
ctc_beam_search_decoder_op.h11020644editdlrm
ctc_greedy_decoder_op.h8170644editdlrm
cube_op.h7230644editdlrm
dataset_ops.h55010644editdlrm
data_couple.h4640644editdlrm
deform_conv_op.h35430644editdlrm
deform_conv_op_impl.h131710644editdlrm
dense_vector_to_id_list_op.h17970644editdlrm
distance_op.h84190644editdlrm
do_op.h69810644editdlrm
dropout_op.h15160644editdlrm
elementwise_add_op.h20240644editdlrm
elementwise_div_op.h12240644editdlrm
elementwise_linear_op.h11700644editdlrm
elementwise_logical_ops.h50830644editdlrm
elementwise_mul_op.h12240644editdlrm
elementwise_ops.h191150644editdlrm
elementwise_ops_utils.h10080644editdlrm
elementwise_op_test.h92370644editdlrm
elementwise_sub_op.h20250644editdlrm
elu_op.h8750644editdlrm
enforce_finite_op.h23030644editdlrm
ensure_clipped_op.h16080644editdlrm
ensure_cpu_output_op.h14650644editdlrm
erf_op.h7510644editdlrm
expand_op.h38770644editdlrm
expand_squeeze_dims_op.h34510644editdlrm
exp_op.h4250644editdlrm
fc_inference.h7750644editdlrm
feature_maps_ops.h324370644editdlrm
feed_blob_op.h8020644editdlrm
filler_op.h184310644editdlrm
find_duplicate_elements_op.h15630644editdlrm
find_op.h20550644editdlrm
flatten_op.h15250644editdlrm
flexible_top_k.h9360644editdlrm
floor_op.h7880644editdlrm
free_op.h7770644editdlrm
fully_connected_op.h93510644editdlrm
fused_rowwise_8bit_conversion_ops.h66010644editdlrm
fused_rowwise_nbitfake_conversion_ops.h43750644editdlrm
fused_rowwise_nbit_conversion_ops.h87230644editdlrm
fused_rowwise_random_quantization_ops.h26070644editdlrm
gather_fused_8bit_rowwise_op.h21790644editdlrm
gather_op.h75050644editdlrm
gather_ranges_to_dense_op.h81880644editdlrm
gelu_op.h14520644editdlrm
generate_proposals_op.h62560644editdlrm
generate_proposals_op_util_boxes.h143090644editdlrm
generate_proposals_op_util_nms.h262140644editdlrm
generate_proposals_op_util_nms_gpu.h21280644editdlrm
given_tensor_byte_string_to_uint8_fill_op.h21500644editdlrm
given_tensor_fill_op.h30020644editdlrm
glu_op.h14580644editdlrm
group_norm_op.h89670644editdlrm
gru_unit_op.h66260644editdlrm
half_float_ops.h27320644editdlrm
hard_sigmoid_op.h9940644editdlrm
heatmap_max_keypoint_op.h9390644editdlrm
histogram_op.h24210644editdlrm
h_softmax_op.h49540644editdlrm
if_op.h17640644editdlrm
im2col_op.h89430644editdlrm
index_hash_ops.h22320644editdlrm
index_ops.h31550644editdlrm
inference_lstm_op.h98810644editdlrm
instance_norm_op.h74410644editdlrm
integral_image_op.h9230644editdlrm
is_empty_op.h5580644editdlrm
jsd_op.h7210644editdlrm
key_split_ops.h14000644editdlrm
layer_norm_op.h80980644editdlrm
leaky_relu_op.h11110644editdlrm
lengths_pad_op.h25740644editdlrm
lengths_reducer_fused_8bit_rowwise_ops.h55320644editdlrm
lengths_reducer_fused_nbit_rowwise_ops.h234650644editdlrm
lengths_reducer_ops.h233150644editdlrm
lengths_reducer_rowwise_8bit_ops.h61800644editdlrm
lengths_tile_op.h5820644editdlrm
lengths_top_k_op.h13580644editdlrm
length_split_op.h22590644editdlrm
listwise_l2r_op.h16770644editdlrm
load_save_op.h140910644editdlrm
load_save_op_util.h16420644editdlrm
locally_connected_op.h38720644editdlrm
locally_connected_op_impl.h264950644editdlrm
locally_connected_op_util.h13320644editdlrm
local_response_normalization_op.h28040644editdlrm
log1p_op.h7170644editdlrm
logit_op.h11290644editdlrm
log_op.h4310644editdlrm
loss_op.h10580644editdlrm
lpnorm_op.h12790644editdlrm
lstm_unit_op.h67330644editdlrm
lstm_utils.h94240644editdlrm
map_ops.h80110644editdlrm
margin_ranking_criterion_op.h11130644editdlrm
matmul_op.h28430644editdlrm
max_pool_with_index_gpu.h11550644editdlrm
mean_op.h32520644editdlrm
merge_id_lists_op.h25700644editdlrm
minmax_ops.h38290644editdlrm
mish_op.h7940644editdlrm
mod_op.h9840644editdlrm
moments_op.h40510644editdlrm
multi_class_accuracy_op.h5390644editdlrm
negate_gradient_op.h5660644editdlrm
negative_op.h4510644editdlrm
ngram_ops.h26440644editdlrm
normalize_l1_op.h10750644editdlrm
normalize_op.h30130644editdlrm
no_default_engine_op.h10630644editdlrm
numpy_tile_op.h36430644editdlrm
one_hot_ops.h25620644editdlrm
onnx_while_op.h106550644editdlrm
operator_fallback_gpu.h41550644editdlrm
op_utils_cudnn.h21120644editdlrm
order_switch_ops.h21490644editdlrm
pack_rnn_sequence_op.h30740644editdlrm
pack_segments.h27290644editdlrm
pad_op.h29020644editdlrm
partition_ops.h99580644editdlrm
percentile_op.h10090644editdlrm
perplexity_op.h4470644editdlrm
piecewise_linear_transform_op.h82810644editdlrm
pool_op.h85250644editdlrm
pool_op_util.h11050644editdlrm
pow_op.h46770644editdlrm
prefetch_op.h46610644editdlrm
prelu_op.h10670644editdlrm
prepend_dim_op.h27600644editdlrm
quantile_op.h41200644editdlrm
quant_decode_op.h53700644editdlrm
rank_loss_op.h8200644editdlrm
reciprocal_op.h7210644editdlrm
reducer_functors.h245560644editdlrm
reduce_front_back_max_ops.h43990644editdlrm
reduce_front_back_sum_mean_ops.h53370644editdlrm
reduce_ops.h99620644editdlrm
reduction_ops.h59440644editdlrm
relu_n_op.h9900644editdlrm
relu_op.h6240644editdlrm
remove_data_blocks_op.h26510644editdlrm
replace_nan_op.h11700644editdlrm
reshape_op.h57230644editdlrm
resize_3d_op.h26770644editdlrm
resize_op.h23070644editdlrm
reverse_packed_segs_op.h27720644editdlrm
rmac_regions_op.h7080644editdlrm
rms_norm_op.h29680644editdlrm
roi_align_gradient_op.h14860644editdlrm
roi_align_op.h28570644editdlrm
roi_align_rotated_gradient_op.h13690644editdlrm
roi_align_rotated_op.h16360644editdlrm
roi_pool_op.h25030644editdlrm
rowmul_op.h19470644editdlrm
rsqrt_op.h7290644editdlrm
scale_blobs_op.h14580644editdlrm
scale_op.h10190644editdlrm
segment_reduction_op.h710220644editdlrm
self_binning_histogram_op.h62580644editdlrm
selu_op.h15450644editdlrm
sequence_ops.h82640644editdlrm
shape_op.h16380644editdlrm
sigmoid_op.h6390644editdlrm
sinh_op.h7110644editdlrm
sinusoid_position_encoding_op.h28340644editdlrm
sin_op.h7050644editdlrm
slice_op.h100710644editdlrm
softmax_op.h11740644editdlrm
softmax_utils.h4470644editdlrm
softmax_with_loss_op.h28830644editdlrm
softplus_op.h7810644editdlrm
softsign_op.h6750644editdlrm
space_batch_op.h68480644editdlrm
sparse_dropout_with_replacement_op.h11220644editdlrm
sparse_itemwise_dropout_with_replacement_op.h11630644editdlrm
sparse_lp_regularizer_op.h11300644editdlrm
sparse_normalize_op.h8340644editdlrm
sparse_to_dense_mask_op.h100510644editdlrm
sparse_to_dense_op.h39770644editdlrm
spatial_batch_norm_op.h151750644editdlrm
spatial_softmax_with_loss_op.h21820644editdlrm
sqrt_op.h4480644editdlrm
sqr_op.h4310644editdlrm
square_root_divide_op.h18570644editdlrm
stats_put_ops.h28130644editdlrm
stop_gradient.h5480644editdlrm
string_ops.h20670644editdlrm
stump_func_op.h21120644editdlrm
summarize_op.h18750644editdlrm
swish_op.h7720644editdlrm
tanh_op.h7230644editdlrm
tan_op.h7050644editdlrm
tensor_protos_db_input.h36330644editdlrm
text_file_reader_utils.h29000644editdlrm
thresholded_relu_op.h11370644editdlrm
tile_op.h87410644editdlrm
top_k.h10610644editdlrm
transpose_op.h20820644editdlrm
tt_linear_op.h65010644editdlrm
unique_ops.h16660644editdlrm
unsafe_coalesce.h24810644editdlrm
upsample_op.h22460644editdlrm
utility_ops.h499940644editdlrm
variable_length_sequence_padding.h13780644editdlrm
weighted_multi_sampling_op.h6020644editdlrm
weighted_sample_op.h7390644editdlrm
while_op.h19610644editdlrm
zero_gradient_op.h3470644editdlrm
Edit: /usr/local/lib64/python3.6/site-packages/torch/include/caffe2/operators/locally_connected_op_impl.h (26495B)
// locally_connected_impl.h is the templated implementation of the // locally_connected.h file. #ifndef CAFFE2_OPERATORS_LOCALLY_CONNECTED_OP_IMPL_H_ #define CAFFE2_OPERATORS_LOCALLY_CONNECTED_OP_IMPL_H_ #include #include "caffe2/core/context.h" #include "caffe2/core/flags.h" #include "caffe2/core/logging.h" #include "caffe2/core/operator.h" #include "caffe2/operators/conv_pool_op_base.h" #include "caffe2/operators/locally_connected_op.h" #include "caffe2/utils/math.h" namespace caffe2 { template bool LocallyConnectedOp::RunOnDeviceWithOrderNCHW() { const auto& X = Input(INPUT); const auto& filter = Input(FILTER); auto* Y = Output(0); const int image_ndim = X.dim() - 2; CAFFE_ENFORCE_EQ(X.dim() + image_ndim, filter.dim()); lc_op_util::ShapeParams shape; shape.N = X.dim32(0); shape.C = X.dim32(1); shape.M = filter.dim32(image_ndim); CAFFE_ENFORCE( shape.C == filter.dim32(image_ndim + 1) * group_, "Locally Connected op: input channels does not match: " "# of input channels ", shape.C, " is not equal to kernel channels * group:", filter.dim32(image_ndim + 1), "*", group_); CAFFE_ENFORCE_EQ( shape.M % group_, 0, "The number of output channels is not divisible by group."); ConvPoolOpBase::SetOutputSize(X, Y, shape.M); shape.input_image_size = GetDimsSize(X); shape.output_image_size = GetDimsSize(*Y); const std::vector output_image_dims = GetDims(*Y); for (int i = 0; i < image_ndim; ++i) { CAFFE_ENFORCE_EQ(output_image_dims[i], filter.dim32(i)); } int kernel_dims_size = 1; for (std::size_t i = 0; i < kernel_.size(); ++i) { CAFFE_ENFORCE_EQ(filter.dim32(i + image_ndim + 2), kernel_[i]); kernel_dims_size *= kernel_[i]; } shape.X_dims.assign(X.sizes().cbegin() + 1, X.sizes().cend()); shape.kernel_size = shape.C / group_ * kernel_dims_size; lc_op_util::SetColumnBufferShape( shape.N, shape.kernel_size, shape.output_image_size, output_image_dims, order_, &shape.column_slice_dims, &shape.column_dims, &shape.column_transposed_dims, &shape.column_axes); lc_op_util::SetYBufferShape( shape.N, shape.M, shape.output_image_size, order_, &shape.Y_dims, &shape.Y_transposed_dims, &shape.Y_axes); const T* X_data = X.template data(); const T* filter_data = filter.template data(); const T* bias_data = nullptr; if (InputSize() == 3) { const auto& bias = Input(BIAS); CAFFE_ENFORCE_EQ(bias.dim(), image_ndim + 1); for (int i = 0; i < image_ndim; ++i) { CAFFE_ENFORCE_EQ(bias.dim32(i), output_image_dims[i]); } CAFFE_ENFORCE_EQ(bias.dim32(image_ndim), shape.M); bias_data = bias.template data(); ConvPoolOpBase::template SetBiasMultiplier( shape.N, &bias_multiplier_); } T* Y_data = Y->template mutable_data(); RunOnDeviceWithOrderNCHWImpl( shape, X_data, filter_data, bias_data, Y_data, &column_buffer_, &column_transposed_buffer_, &Y_transposed_buffer_); return true; } template bool LocallyConnectedOp::RunOnDeviceWithOrderNHWC() { const auto& X = Input(INPUT); const auto& filter = Input(FILTER); auto* Y = Output(0); CAFFE_ENFORCE_EQ( kernel_.size(), 2, "Only 2d locally connected op is supported for NHWC storage type."); const int image_ndim = X.dim() - 2; CAFFE_ENFORCE_EQ(X.dim() + image_ndim, filter.dim()); lc_op_util::ShapeParams shape; shape.N = X.dim32(0); shape.C = X.dim32(3); shape.X_dims = {X.dim32(1), X.dim32(2), X.dim32(3)}; shape.M = filter.dim32(image_ndim); CAFFE_ENFORCE_EQ(filter.dim32(image_ndim + 1), kernel_h()); CAFFE_ENFORCE_EQ(filter.dim32(image_ndim + 2), kernel_w()); CAFFE_ENFORCE_EQ(filter.dim32(image_ndim + 3), shape.C); ConvPoolOpBase::SetOutputSize(X, Y, shape.M); shape.input_image_size = GetDimsSize(X); shape.output_image_size = GetDimsSize(*Y); const std::vector output_image_dims = GetDims(*Y); for (int i = 0; i < image_ndim; ++i) { CAFFE_ENFORCE_EQ(output_image_dims[i], filter.dim32(i)); } shape.kernel_size = kernel_h() * kernel_w() * shape.C; lc_op_util::SetColumnBufferShape( shape.N, shape.kernel_size, shape.output_image_size, output_image_dims, order_, &shape.column_slice_dims, &shape.column_dims, &shape.column_transposed_dims, &shape.column_axes); lc_op_util::SetYBufferShape( shape.N, shape.M, shape.output_image_size, order_, &shape.Y_dims, &shape.Y_transposed_dims, &shape.Y_axes); const T* X_data = X.template data(); const T* filter_data = filter.template data(); const T* bias_data = nullptr; if (InputSize() == 3) { const auto& bias = Input(BIAS); CAFFE_ENFORCE_EQ(bias.dim(), image_ndim + 1); for (int i = 0; i < image_ndim; ++i) { CAFFE_ENFORCE_EQ(bias.dim32(i), output_image_dims[i]); } CAFFE_ENFORCE_EQ(bias.dim32(image_ndim), shape.M); bias_data = bias.template data(); ConvPoolOpBase::template SetBiasMultiplier( shape.N, &bias_multiplier_); } T* Y_data = Y->template mutable_data(); RunOnDeviceWithOrderNHWCImpl( shape, X_data, filter_data, bias_data, Y_data, &column_buffer_, &column_transposed_buffer_, &Y_transposed_buffer_); return true; } template void LocallyConnectedOp::RunOnDeviceWithOrderNCHWImpl( const lc_op_util::ShapeParams& shape, const T* X_data, const T* filter_data, const T* bias_data, T* Y_data, Tensor* column_buffer, Tensor* column_transposed_buffer, Tensor* Y_transposed_buffer) { const int input_stride = shape.C / group_ * shape.input_image_size; const int column_stride = shape.kernel_size * shape.output_image_size; column_buffer->Resize(shape.column_dims); column_transposed_buffer->Resize(shape.column_transposed_dims); Y_transposed_buffer->Resize(shape.Y_transposed_dims); T* column_buffer_data = column_buffer->template mutable_data(); T* Y_transposed_buffer_data = Y_transposed_buffer->template mutable_data(); for (int image_id = 0; image_id < shape.N; ++image_id) { for (int group_id = 0; group_id < group_; ++group_id) { if (kernel_.size() == 2) { math::Im2Col( shape.C / group_, shape.X_dims[1], shape.X_dims[2], kernel_h(), kernel_w(), dilation_h(), dilation_w(), pad_t(), pad_l(), pad_b(), pad_r(), stride_h(), stride_w(), X_data + group_id * input_stride, column_buffer_data + group_id * column_stride, &context_); } else { math::Im2ColNd( kernel_.size(), shape.C * shape.input_image_size, column_stride, shape.X_dims.data(), shape.column_slice_dims.data(), kernel_.data(), stride_.data(), dilation_.data(), pads_.data(), X_data + group_id * input_stride, column_buffer_data + group_id * column_stride, &context_); } } X_data += input_stride * group_; column_buffer_data += column_stride * group_; } math::Transpose( shape.column_dims.size(), shape.column_dims.data(), shape.column_axes.data(), column_buffer->template data(), column_transposed_buffer->template mutable_data(), &context_); math::GemmStridedBatched( CblasNoTrans, CblasNoTrans, shape.output_image_size * group_, shape.M / group_, shape.N, shape.kernel_size, 1.0f, filter_data, shape.M / group_ * shape.kernel_size, column_transposed_buffer->template data(), shape.kernel_size * shape.N, 0.0f, Y_transposed_buffer_data, shape.M / group_ * shape.N, &context_); if (bias_data != nullptr) { math::Gemm( CblasNoTrans, CblasNoTrans, shape.output_image_size * shape.M, shape.N, 1, 1.0, bias_data, bias_multiplier_.template data(), 1.0, Y_transposed_buffer_data, &context_); } math::Transpose( shape.Y_transposed_dims.size(), shape.Y_transposed_dims.data(), shape.Y_axes.data(), Y_transposed_buffer_data, Y_data, &context_); } template void LocallyConnectedOp::RunOnDeviceWithOrderNHWCImpl( const lc_op_util::ShapeParams& shape, const T* X_data, const T* filter_data, const T* bias_data, T* Y_data, Tensor* column_buffer, Tensor* column_transposed_buffer, Tensor* Y_transposed_buffer) { const int input_stride = shape.C * shape.input_image_size; const int column_stride = shape.kernel_size * shape.output_image_size; column_buffer->Resize(shape.column_dims); column_transposed_buffer->Resize(shape.column_transposed_dims); Y_transposed_buffer->Resize(shape.Y_transposed_dims); T* column_buffer_data = column_buffer->template mutable_data(); T* Y_transposed_buffer_data = Y_transposed_buffer->template mutable_data(); for (int image_id = 0; image_id < shape.N; ++image_id) { math::Im2Col( shape.C, shape.X_dims[0], shape.X_dims[1], kernel_h(), kernel_w(), dilation_h(), dilation_w(), pad_t(), pad_l(), pad_b(), pad_r(), stride_h(), stride_w(), X_data + image_id * input_stride, column_buffer_data + image_id * column_stride, &context_); } math::Transpose( shape.column_dims.size(), shape.column_dims.data(), shape.column_axes.data(), column_buffer->template data(), column_transposed_buffer->template mutable_data(), &context_); math::GemmStridedBatched( CblasNoTrans, CblasTrans, shape.output_image_size, shape.N, shape.M, shape.kernel_size, 1.0f, column_transposed_buffer->template data(), shape.N * shape.kernel_size, filter_data, shape.kernel_size * shape.M, 0.0f, Y_transposed_buffer_data, shape.N * shape.M, &context_); math::Transpose( shape.Y_transposed_dims.size(), shape.Y_transposed_dims.data(), shape.Y_axes.data(), Y_transposed_buffer_data, Y_data, &context_); if (bias_data != nullptr) { math::Gemm( CblasNoTrans, CblasNoTrans, shape.N, shape.output_image_size * shape.M, 1, 1.0f, bias_multiplier_.template data(), bias_data, 1.0f, Y_data, &context_); } } template bool LocallyConnectedGradientOp::RunOnDeviceWithOrderNCHW() { const auto& X = Input(INPUT); const auto& filter = Input(FILTER); const auto& dY = Input(OUTPUT_GRAD); const int image_ndim = X.dim() - 2; CAFFE_ENFORCE_EQ(X.dim() + image_ndim, filter.dim()); lc_op_util::ShapeParams shape; shape.N = X.dim32(0); shape.C = X.dim32(1); shape.M = filter.dim32(image_ndim); CAFFE_ENFORCE_EQ(filter.dim32(image_ndim + 1) * group_, shape.C); CAFFE_ENFORCE_EQ(shape.M % group_, 0); const std::vector input_image_dims = GetDims(X); shape.input_image_size = GetDimsSize(X); const std::vector output_image_dims = GetDims(dY); shape.output_image_size = GetDimsSize(dY); for (int i = 0; i < image_ndim; ++i) { CAFFE_ENFORCE_EQ(output_image_dims[i], filter.dim32(i)); } ConvPoolOpBase::ComputePads(input_image_dims); int kernel_dims_size = 1; for (std::size_t i = 0; i < kernel_.size(); ++i) { CAFFE_ENFORCE_EQ(filter.dim32(i + image_ndim + 2), kernel_[i]); kernel_dims_size *= kernel_[i]; } shape.X_dims.assign(X.sizes().cbegin() + 1, X.sizes().cend()); shape.kernel_size = shape.C / group_ * kernel_dims_size; lc_op_util::SetColumnBufferShape( shape.N, shape.kernel_size, shape.output_image_size, output_image_dims, order_, &shape.column_slice_dims, &shape.column_dims, &shape.column_transposed_dims, &shape.column_axes); lc_op_util::SetYBufferShape( shape.N, shape.M, shape.output_image_size, order_, &shape.Y_dims, &shape.Y_transposed_dims, &shape.Y_axes); auto* dfilter = Output(FILTER_GRAD, filter.sizes(), at::dtype()); const T* X_data = X.template data(); const T* filter_data = filter.template data(); const T* dY_data = dY.template data(); T* dfilter_data = dfilter->template mutable_data(); T* dX_data = nullptr; T* dbias_data = nullptr; if (OutputSize() == 3 || (no_bias_ && OutputSize() == 2)) { auto* dX = Output( no_bias_ ? BIAS_OR_INPUT_GRAD : INPUT_GRAD, X.sizes(), at::dtype()); dX_data = dX->template mutable_data(); } if (!no_bias_) { std::vector dbias_dims; std::copy( output_image_dims.cbegin(), output_image_dims.cend(), std::back_inserter(dbias_dims)); dbias_dims.push_back(shape.M); auto* dbias = Output(BIAS_OR_INPUT_GRAD, dbias_dims, at::dtype()); ConvPoolOpBase::template SetBiasMultiplier( shape.N, &bias_multiplier_); dbias_data = dbias->template mutable_data(); } RunOnDeviceWithOrderNCHWImpl( shape, X_data, filter_data, dY_data, dfilter_data, dX_data, dbias_data, &column_buffer_, &column_transposed_buffer_, &dY_transposed_buffer_); return true; } template bool LocallyConnectedGradientOp::RunOnDeviceWithOrderNHWC() { const auto& X = Input(INPUT); const auto& filter = Input(FILTER); const auto& dY = Input(OUTPUT_GRAD); CAFFE_ENFORCE_EQ( kernel_.size(), 2, "Only 2d locally connected op is supported for NHWC storage type."); const int image_ndim = X.dim() - 2; CAFFE_ENFORCE_EQ(X.dim() + image_ndim, filter.dim()); lc_op_util::ShapeParams shape; shape.N = X.dim32(0); shape.C = X.dim32(3); shape.X_dims = {X.dim32(1), X.dim32(2), X.dim32(3)}; shape.M = filter.dim32(image_ndim); CAFFE_ENFORCE_EQ(filter.dim32(image_ndim + 1), kernel_h()); CAFFE_ENFORCE_EQ(filter.dim32(image_ndim + 2), kernel_w()); CAFFE_ENFORCE_EQ(filter.dim32(image_ndim + 3), shape.C); const std::vector input_image_dims = {X.dim32(1), X.dim32(2)}; ConvPoolOpBase::ComputePads(input_image_dims); shape.input_image_size = GetDimsSize(X); shape.output_image_size = GetDimsSize(dY); const std::vector output_image_dims = GetDims(dY); for (int i = 0; i < image_ndim; ++i) { CAFFE_ENFORCE_EQ(output_image_dims[i], filter.dim32(i)); } shape.kernel_size = kernel_h() * kernel_w() * shape.C; lc_op_util::SetColumnBufferShape( shape.N, shape.kernel_size, shape.output_image_size, output_image_dims, order_, &shape.column_slice_dims, &shape.column_dims, &shape.column_transposed_dims, &shape.column_axes); lc_op_util::SetYBufferShape( shape.N, shape.M, shape.output_image_size, order_, &shape.Y_dims, &shape.Y_transposed_dims, &shape.Y_axes); auto* dfilter = Output(FILTER_GRAD, filter.sizes(), at::dtype()); const T* X_data = X.template data(); const T* filter_data = filter.template data(); const T* dY_data = dY.template data(); T* dfilter_data = dfilter->template mutable_data(); T* dX_data = nullptr; T* dbias_data = nullptr; if (OutputSize() == 3 || (no_bias_ && OutputSize() == 2)) { auto* dX = Output( no_bias_ ? BIAS_OR_INPUT_GRAD : INPUT_GRAD, X.sizes(), at::dtype()); dX_data = dX->template mutable_data(); } if (!no_bias_) { std::vector dbias_dims; std::copy( output_image_dims.cbegin(), output_image_dims.cend(), std::back_inserter(dbias_dims)); dbias_dims.push_back(shape.M); auto* dbias = Output(BIAS_OR_INPUT_GRAD, dbias_dims, at::dtype()); ConvPoolOpBase::template SetBiasMultiplier( shape.N, &bias_multiplier_); dbias_data = dbias->template mutable_data(); } RunOnDeviceWithOrderNHWCImpl( shape, X_data, filter_data, dY_data, dfilter_data, dX_data, dbias_data, &column_buffer_, &column_transposed_buffer_, &dY_transposed_buffer_); return true; } template void LocallyConnectedGradientOp::RunOnDeviceWithOrderNCHWImpl( const lc_op_util::ShapeParams& shape, const T* X_data, const T* filter_data, const T* dY_data, T* dfilter_data, T* dX_data, T* dbias_data, Tensor* column_buffer, Tensor* column_transposed_buffer, Tensor* dY_transposed_buffer) { const int input_stride = shape.C * shape.input_image_size; const int column_stride = shape.kernel_size * shape.output_image_size; column_buffer->Resize(shape.column_dims); column_transposed_buffer->Resize(shape.column_transposed_dims); dY_transposed_buffer->Resize(shape.Y_transposed_dims); T* column_buffer_data = column_buffer->template mutable_data(); T* dY_transposed_buffer_data = dY_transposed_buffer->template mutable_data(); for (int image_id = 0; image_id < shape.N; ++image_id) { for (int group_id = 0; group_id < group_; ++group_id) { if (kernel_.size() == 2) { math::Im2Col( shape.C / group_, shape.X_dims[1], shape.X_dims[2], kernel_h(), kernel_w(), dilation_h(), dilation_w(), pad_t(), pad_l(), pad_b(), pad_r(), stride_h(), stride_w(), X_data + group_id * input_stride, column_buffer_data + group_id * column_stride, &context_); } else { math::Im2ColNd( kernel_.size(), shape.C * shape.input_image_size, column_stride, shape.X_dims.data(), shape.column_slice_dims.data(), kernel_.data(), stride_.data(), dilation_.data(), pads_.data(), X_data + group_id * input_stride, column_buffer_data + group_id * column_stride, &context_); } } X_data += input_stride * group_; column_buffer_data += column_stride * group_; } math::Transpose( shape.column_dims.size(), shape.column_dims.data(), shape.column_axes.data(), column_buffer->template data(), column_transposed_buffer->template mutable_data(), &context_); math::Transpose( shape.Y_dims.size(), shape.Y_dims.data(), shape.Y_axes.data(), dY_data, dY_transposed_buffer_data, &context_); // Gradient respect to filter. math::GemmStridedBatched( CblasNoTrans, CblasTrans, shape.output_image_size * group_, shape.M / group_, shape.kernel_size, shape.N, 1.0f, dY_transposed_buffer_data, shape.M / group_ * shape.N, column_transposed_buffer->template data(), shape.N * shape.kernel_size, 0.0f, dfilter_data, shape.M / group_ * shape.kernel_size, &context_); if (dbias_data != nullptr) { // Gradient respect to bias. math::Gemv( CblasNoTrans, shape.output_image_size * shape.M, shape.N, 1.0f, dY_transposed_buffer_data, bias_multiplier_.template data(), 0.0f, dbias_data, &context_); } if (dX_data != nullptr) { // Gradient respect to X. math::GemmStridedBatched( CblasTrans, CblasNoTrans, shape.output_image_size * group_, shape.kernel_size, shape.N, shape.M / group_, 1.0f, filter_data, shape.kernel_size * shape.M / group_, dY_transposed_buffer_data, shape.M / group_ * shape.N, 0.0f, column_transposed_buffer->template mutable_data(), shape.kernel_size * shape.N, &context_); math::Transpose( shape.column_transposed_dims.size(), shape.column_transposed_dims.data(), shape.column_axes.data(), column_transposed_buffer->template data(), column_buffer->template mutable_data(), &context_); const T* const_column_buffer_data = column_buffer->template data(); for (int image_id = 0; image_id < shape.N; ++image_id) { for (int group_id = 0; group_id < group_; ++group_id) { if (kernel_.size() == 2) { math::Col2Im( shape.C / group_, shape.X_dims[1], shape.X_dims[2], kernel_h(), kernel_w(), dilation_h(), dilation_w(), pad_t(), pad_l(), pad_b(), pad_r(), stride_h(), stride_w(), const_column_buffer_data + group_id * column_stride, dX_data + group_id * input_stride, &context_); } else { math::Col2ImNd( kernel_.size(), shape.C * shape.input_image_size, column_stride, shape.X_dims.data(), shape.column_slice_dims.data(), kernel_.data(), stride_.data(), dilation_.data(), pads_.data(), const_column_buffer_data + group_id * column_stride, dX_data + group_id * input_stride, &context_); } } dX_data += input_stride * group_; const_column_buffer_data += column_stride * group_; } } } template void LocallyConnectedGradientOp::RunOnDeviceWithOrderNHWCImpl( const lc_op_util::ShapeParams& shape, const T* X_data, const T* filter_data, const T* dY_data, T* dfilter_data, T* dX_data, T* dbias_data, Tensor* column_buffer, Tensor* column_transposed_buffer, Tensor* dY_transposed_buffer) { const int input_stride = shape.C * shape.input_image_size; const int column_stride = shape.kernel_size * shape.output_image_size; column_buffer->Resize(shape.column_dims); column_transposed_buffer->Resize(shape.column_transposed_dims); dY_transposed_buffer->Resize(shape.Y_transposed_dims); T* column_buffer_data = column_buffer->template mutable_data(); T* dY_transposed_buffer_data = dY_transposed_buffer->template mutable_data(); for (int image_id = 0; image_id < shape.N; ++image_id) { math::Im2Col( shape.C, shape.X_dims[0], shape.X_dims[1], kernel_h(), kernel_w(), dilation_h(), dilation_w(), pad_t(), pad_l(), pad_b(), pad_r(), stride_h(), stride_w(), X_data + image_id * input_stride, column_buffer_data + image_id * column_stride, &context_); } math::Transpose( shape.column_dims.size(), shape.column_dims.data(), shape.column_axes.data(), column_buffer->template data(), column_transposed_buffer->template mutable_data(), &context_); math::Transpose( shape.Y_dims.size(), shape.Y_dims.data(), shape.Y_axes.data(), dY_data, dY_transposed_buffer_data, &context_); // Gradient respect to filter. math::GemmStridedBatched( CblasTrans, CblasNoTrans, shape.output_image_size, shape.M, shape.kernel_size, shape.N, 1.0f, dY_transposed_buffer_data, shape.M * shape.N, column_transposed_buffer->template data(), shape.N * shape.kernel_size, 0.0f, dfilter_data, shape.M * shape.kernel_size, &context_); if (dbias_data != nullptr) { // Gradient respect to bias. math::Gemv( CblasTrans, shape.N, shape.output_image_size * shape.M, 1.0f, dY_data, bias_multiplier_.template data(), 0.0f, dbias_data, &context_); } if (dX_data != nullptr) { // Gradient respect to X. math::GemmStridedBatched( CblasNoTrans, CblasNoTrans, shape.output_image_size, shape.N, shape.kernel_size, shape.M, 1.0f, dY_transposed_buffer_data, shape.N * shape.M, filter_data, shape.M * shape.kernel_size, 0.0f, column_transposed_buffer->template mutable_data(), shape.N * shape.kernel_size, &context_); math::Transpose( shape.column_transposed_dims.size(), shape.column_transposed_dims.data(), shape.column_axes.data(), column_transposed_buffer->template data(), column_buffer->template mutable_data(), &context_); const T* const_column_buffer_data = column_buffer->template data(); for (int image_id = 0; image_id < shape.N; ++image_id) { math::Col2Im( shape.C, shape.X_dims[0], shape.X_dims[1], kernel_h(), kernel_w(), dilation_h(), dilation_w(), pad_t(), pad_l(), pad_b(), pad_r(), stride_h(), stride_w(), const_column_buffer_data, dX_data, &context_); dX_data += input_stride; const_column_buffer_data += column_stride; } } } } // namespace caffe2 #endif // CAFFE2_OPERATORS_LOCALLY_CONNECTED_OP_IMPL_H_