diff --git a/nnforge/cuda/upsampling_layer_tester_cuda.cuh b/nnforge/cuda/upsampling_layer_tester_cuda.cuh index d68d4a1..daabdfd 100644 --- a/nnforge/cuda/upsampling_layer_tester_cuda.cuh +++ b/nnforge/cuda/upsampling_layer_tester_cuda.cuh @@ -187,22 +187,32 @@ namespace nnforge feature_map_upsampling_size = layer_derived->feature_map_upsampling_size; entry_upsampling_size = layer_derived->entry_upsampling_size; - int_fastdiv current_stride(layer_derived->upsampling_sizes[0]); + std::vector local_upsampling_sizes = layer_derived->upsampling_sizes; + if (local_upsampling_sizes.empty()) + local_upsampling_sizes.push_back(1); + std::vector local_input_dimension_sizes = input_configuration_specific_list[0].dimension_sizes; + if (local_input_dimension_sizes.empty()) + local_input_dimension_sizes.push_back(1); + std::vector local_output_dimension_sizes = output_configuration_specific.dimension_sizes; + if (local_output_dimension_sizes.empty()) + local_output_dimension_sizes.push_back(1); + + int_fastdiv current_stride(local_upsampling_sizes[0]); for(int i = 0; i < dimension_count; ++i) { - upsampling_sizes[i] = layer_derived->upsampling_sizes[i]; - input_sizes[i] = input_configuration_specific_list[0].dimension_sizes[i]; - output_sizes[i] = output_configuration_specific.dimension_sizes[i]; + upsampling_sizes[i] = local_upsampling_sizes[i]; + input_sizes[i] = local_input_dimension_sizes[i]; + output_sizes[i] = local_output_dimension_sizes[i]; strides[i] = current_stride; - current_stride = current_stride * static_cast(input_configuration_specific_list[0].dimension_sizes[i]); + current_stride = current_stride * input_sizes[i]; } forward_packed_config_count = upsampling_sizes[0]; for(int i = 0; i < dimension_count; ++i) forward_packed_config_count *= input_sizes[i]; - nonunit_window_x = (layer_derived->upsampling_sizes[0] > 1); + nonunit_window_x = (local_upsampling_sizes[0] > 1); } private: diff --git a/nnforge/cuda/upsampling_layer_testing_schema.cu b/nnforge/cuda/upsampling_layer_testing_schema.cu index 5b2a0c4..1fce7de 100644 --- a/nnforge/cuda/upsampling_layer_testing_schema.cu +++ b/nnforge/cuda/upsampling_layer_testing_schema.cu @@ -52,7 +52,10 @@ namespace nnforge switch (output_configuration_specific.dimension_sizes.size()) { - case 1: + case 0: + res = layer_tester_cuda::ptr(new upsampling_layer_tester_cuda<1>()); + break; + case 1: res = layer_tester_cuda::ptr(new upsampling_layer_tester_cuda<1>()); break; case 2: diff --git a/nnforge/cuda/upsampling_layer_updater_cuda.cuh b/nnforge/cuda/upsampling_layer_updater_cuda.cuh index 384392d..7941ca3 100644 --- a/nnforge/cuda/upsampling_layer_updater_cuda.cuh +++ b/nnforge/cuda/upsampling_layer_updater_cuda.cuh @@ -400,22 +400,32 @@ namespace nnforge feature_map_upsampling_size = layer_derived->feature_map_upsampling_size; entry_upsampling_size = layer_derived->entry_upsampling_size; - int_fastdiv current_stride(layer_derived->upsampling_sizes[0]); + std::vector local_upsampling_sizes = layer_derived->upsampling_sizes; + if (local_upsampling_sizes.empty()) + local_upsampling_sizes.push_back(1); + std::vector local_input_dimension_sizes = input_configuration_specific_list[0].dimension_sizes; + if (local_input_dimension_sizes.empty()) + local_input_dimension_sizes.push_back(1); + std::vector local_output_dimension_sizes = output_configuration_specific.dimension_sizes; + if (local_output_dimension_sizes.empty()) + local_output_dimension_sizes.push_back(1); + + int_fastdiv current_stride(local_upsampling_sizes[0]); for(int i = 0; i < dimension_count; ++i) { - upsampling_sizes[i] = layer_derived->upsampling_sizes[i]; - input_sizes[i] = input_configuration_specific_list[0].dimension_sizes[i]; - output_sizes[i] = output_configuration_specific.dimension_sizes[i]; + upsampling_sizes[i] = local_upsampling_sizes[i]; + input_sizes[i] = local_input_dimension_sizes[i]; + output_sizes[i] = local_output_dimension_sizes[i]; strides[i] = current_stride; - current_stride = current_stride * static_cast(input_configuration_specific_list[0].dimension_sizes[i]); + current_stride = current_stride * static_cast(local_input_dimension_sizes[i]); } forward_packed_config_count = upsampling_sizes[0]; for(int i = 0; i < dimension_count; ++i) forward_packed_config_count *= input_sizes[i]; - nonunit_window_x = (layer_derived->upsampling_sizes[0] > 1); + nonunit_window_x = (local_upsampling_sizes[0] > 1); } bool is_backward_data_dependent_on_input_buffer(unsigned int action_input_index, unsigned int data_input_index) const diff --git a/nnforge/cuda/upsampling_layer_updater_schema.cu b/nnforge/cuda/upsampling_layer_updater_schema.cu index e697f86..41de60c 100644 --- a/nnforge/cuda/upsampling_layer_updater_schema.cu +++ b/nnforge/cuda/upsampling_layer_updater_schema.cu @@ -53,6 +53,9 @@ namespace nnforge switch (output_configuration_specific.dimension_sizes.size()) { + case 0: + res = layer_updater_cuda::ptr(new upsampling_layer_updater_cuda<1>()); + break; case 1: res = layer_updater_cuda::ptr(new upsampling_layer_updater_cuda<1>()); break; diff --git a/nnforge/plain/upsampling_layer_tester_plain.cpp b/nnforge/plain/upsampling_layer_tester_plain.cpp index 72f7757..0c9de8b 100644 --- a/nnforge/plain/upsampling_layer_tester_plain.cpp +++ b/nnforge/plain/upsampling_layer_tester_plain.cpp @@ -53,6 +53,12 @@ namespace nnforge const layer_configuration_specific& output_configuration_specific, unsigned int entry_count) const { + std::vector input_dimension_sizes = input_configuration_specific_list[0].dimension_sizes; + if (input_dimension_sizes.empty()) + input_dimension_sizes.push_back(1); + std::vector output_dimension_sizes = output_configuration_specific.dimension_sizes; + if (output_dimension_sizes.empty()) + output_dimension_sizes.push_back(1); const float * const in_it_global = *input_buffers[0]; float * const out_it_global = *output_buffer; const unsigned int input_neuron_count = input_configuration_specific_list[0].get_neuron_count(); @@ -61,17 +67,19 @@ namespace nnforge const unsigned int output_neuron_count_per_feature_map = output_configuration_specific.get_neuron_count_per_feature_map(); nnforge_shared_ptr layer_derived = nnforge_dynamic_pointer_cast(layer_schema); std::vector upsampling_sizes = layer_derived->upsampling_sizes; + if (upsampling_sizes.empty()) + upsampling_sizes.push_back(1); const unsigned int feature_map_upsampling_size = layer_derived->feature_map_upsampling_size; upsampling_sizes.push_back(feature_map_upsampling_size); const unsigned int entry_upsampling_size = layer_derived->entry_upsampling_size; upsampling_sizes.push_back(entry_upsampling_size); const unsigned int upsampling_dimension_count = static_cast(upsampling_sizes.size()); - const unsigned int spatial_dimension_count = static_cast(output_configuration_specific.dimension_sizes.size()); + const unsigned int spatial_dimension_count = static_cast(output_dimension_sizes.size()); std::vector output_slices(upsampling_sizes.size()); output_slices[0] = 1; for(unsigned int i = 0; i < upsampling_dimension_count - 1; ++i) { - int dimension_size = (i < spatial_dimension_count) ? output_configuration_specific.dimension_sizes[i] : output_configuration_specific.feature_map_count; + int dimension_size = (i < spatial_dimension_count) ? output_dimension_sizes[i] : output_configuration_specific.feature_map_count; output_slices[i + 1] = output_slices[i] * dimension_size; } unsigned int upsampling_elem_count = 1; @@ -99,7 +107,7 @@ namespace nnforge } const int total_workload = (entry_count / entry_upsampling_size) * input_configuration_specific_list[0].feature_map_count; - const std::vector::const_iterator dimension_sizes_it = output_configuration_specific.dimension_sizes.begin(); + const std::vector::const_iterator dimension_sizes_it = input_dimension_sizes.begin(); const std::vector::const_iterator upsampling_sizes_it = upsampling_sizes.begin(); const std::vector::const_iterator output_slices_it = output_slices.begin(); const std::vector::const_iterator offset_list_it = offset_list.begin(); diff --git a/nnforge/plain/upsampling_layer_updater_plain.cpp b/nnforge/plain/upsampling_layer_updater_plain.cpp index 5ab0881..691c832 100644 --- a/nnforge/plain/upsampling_layer_updater_plain.cpp +++ b/nnforge/plain/upsampling_layer_updater_plain.cpp @@ -55,6 +55,12 @@ namespace nnforge const std::set& actions, unsigned int entry_count) const { + std::vector input_dimension_sizes = input_configuration_specific_list[0].dimension_sizes; + if (input_dimension_sizes.empty()) + input_dimension_sizes.push_back(1); + std::vector output_dimension_sizes = output_configuration_specific.dimension_sizes; + if (output_dimension_sizes.empty()) + output_dimension_sizes.push_back(1); const float * const in_it_global = *input_buffers[0]; float * const out_it_global = *output_buffer; const unsigned int input_neuron_count = input_configuration_specific_list[0].get_neuron_count(); @@ -63,17 +69,19 @@ namespace nnforge const unsigned int output_neuron_count_per_feature_map = output_configuration_specific.get_neuron_count_per_feature_map(); nnforge_shared_ptr layer_derived = nnforge_dynamic_pointer_cast(layer_schema); std::vector upsampling_sizes = layer_derived->upsampling_sizes; + if (upsampling_sizes.empty()) + upsampling_sizes.push_back(1); const unsigned int feature_map_upsampling_size = layer_derived->feature_map_upsampling_size; upsampling_sizes.push_back(feature_map_upsampling_size); const unsigned int entry_upsampling_size = layer_derived->entry_upsampling_size; upsampling_sizes.push_back(entry_upsampling_size); const unsigned int upsampling_dimension_count = static_cast(upsampling_sizes.size()); - const unsigned int spatial_dimension_count = static_cast(output_configuration_specific.dimension_sizes.size()); + const unsigned int spatial_dimension_count = static_cast(output_dimension_sizes.size()); std::vector output_slices(upsampling_sizes.size()); output_slices[0] = 1; for(unsigned int i = 0; i < upsampling_dimension_count - 1; ++i) { - int dimension_size = (i < spatial_dimension_count) ? output_configuration_specific.dimension_sizes[i] : output_configuration_specific.feature_map_count; + int dimension_size = (i < spatial_dimension_count) ? output_dimension_sizes[i] : output_configuration_specific.feature_map_count; output_slices[i + 1] = output_slices[i] * dimension_size; } unsigned int upsampling_elem_count = 1; @@ -101,7 +109,7 @@ namespace nnforge } const int total_workload = (entry_count / entry_upsampling_size) * input_configuration_specific_list[0].feature_map_count; - const std::vector::const_iterator dimension_sizes_it = output_configuration_specific.dimension_sizes.begin(); + const std::vector::const_iterator dimension_sizes_it = input_dimension_sizes.begin(); const std::vector::const_iterator upsampling_sizes_it = upsampling_sizes.begin(); const std::vector::const_iterator output_slices_it = output_slices.begin(); const std::vector::const_iterator offset_list_it = offset_list.begin(); @@ -163,6 +171,12 @@ namespace nnforge const std::set& actions, unsigned int entry_count) const { + std::vector input_dimension_sizes = input_configuration_specific_list[0].dimension_sizes; + if (input_dimension_sizes.empty()) + input_dimension_sizes.push_back(1); + std::vector output_dimension_sizes = output_configuration_specific.dimension_sizes; + if (output_dimension_sizes.empty()) + output_dimension_sizes.push_back(1); float * const in_err_it_global = *input_errors_buffer; const float * const out_err_it_global = *output_errors_buffer; const unsigned int input_neuron_count = input_configuration_specific_list[0].get_neuron_count(); @@ -174,14 +188,16 @@ namespace nnforge const unsigned int feature_map_upsampling_size = layer_derived->feature_map_upsampling_size; upsampling_sizes.push_back(feature_map_upsampling_size); const unsigned int entry_upsampling_size = layer_derived->entry_upsampling_size; + if (upsampling_sizes.empty()) + upsampling_sizes.push_back(1); upsampling_sizes.push_back(entry_upsampling_size); const unsigned int upsampling_dimension_count = static_cast(upsampling_sizes.size()); - const unsigned int spatial_dimension_count = static_cast(output_configuration_specific.dimension_sizes.size()); + const unsigned int spatial_dimension_count = static_cast(output_dimension_sizes.size()); std::vector output_slices(upsampling_sizes.size()); output_slices[0] = 1; for(unsigned int i = 0; i < upsampling_dimension_count - 1; ++i) { - int dimension_size = (i < spatial_dimension_count) ? output_configuration_specific.dimension_sizes[i] : output_configuration_specific.feature_map_count; + int dimension_size = (i < spatial_dimension_count) ? output_dimension_sizes[i] : output_configuration_specific.feature_map_count; output_slices[i + 1] = output_slices[i] * dimension_size; } unsigned int upsampling_elem_count = 1; @@ -209,7 +225,7 @@ namespace nnforge } const int total_workload = (entry_count / entry_upsampling_size) * input_configuration_specific_list[0].feature_map_count; - const std::vector::const_iterator dimension_sizes_it = output_configuration_specific.dimension_sizes.begin(); + const std::vector::const_iterator dimension_sizes_it = input_dimension_sizes.begin(); const std::vector::const_iterator upsampling_sizes_it = upsampling_sizes.begin(); const std::vector::const_iterator output_slices_it = output_slices.begin(); const std::vector::const_iterator offset_list_it = offset_list.begin(); diff --git a/nnforge/upsampling_layer.cpp b/nnforge/upsampling_layer.cpp index be78536..cf92d8d 100644 --- a/nnforge/upsampling_layer.cpp +++ b/nnforge/upsampling_layer.cpp @@ -41,9 +41,6 @@ namespace nnforge void upsampling_layer::check() { - if (upsampling_sizes.size() == 0) - throw neural_network_exception("upsampling sizes for average subsampling layer may not be empty"); - for(unsigned int i = 0; i < upsampling_sizes.size(); i++) { if (upsampling_sizes[i] == 0) @@ -204,10 +201,18 @@ namespace nnforge } if (feature_map_upsampling_size != 1) - ss << ", fm " << feature_map_upsampling_size; + { + if (!ss.str().empty()) + ss << ", "; + ss << "fm " << feature_map_upsampling_size; + } if (entry_upsampling_size != 1) - ss << ", samples " << entry_upsampling_size; + { + if (!ss.str().empty()) + ss << ", "; + ss << "samples " << entry_upsampling_size; + } res.push_back(ss.str());