/******************************************************************************* * * MIT License * * Copyright (c) 2019 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * *******************************************************************************/ #ifndef GUARD_CPU_BIAS_HPP #define GUARD_CPU_BIAS_HPP #include "test.hpp" #include #include #include #include #include #include #include #include #include "tensor_holder.hpp" #include #include template void cpu_bias_forward_impl(tensor& out, const tensor& bias) { assert(out.desc.GetNumDims() == NSpatialDim + 2 and bias.desc.GetNumDims() == NSpatialDim + 2); assert( bias.desc.GetLengths()[0] == 1 && bias.desc.GetLengths()[1] == out.desc.GetLengths()[1] && std::all_of(bias.desc.GetLengths().begin() + 2, bias.desc.GetLengths().end(), [](auto v) { return v == 1; })); out.par_for_each([&](auto out_n_id, auto out_k_id, auto... out_spatial_id_pack) { out(out_n_id, out_k_id, out_spatial_id_pack...) = double(out(out_n_id, out_k_id, out_spatial_id_pack...)) + double(bias.data[out_k_id]); }); } template void cpu_bias_backward_data_impl(const tensor& out, tensor& bias) { assert(out.desc.GetNumDims() == NSpatialDim + 2 and bias.desc.GetNumDims() == NSpatialDim + 2); assert( bias.desc.GetLengths()[0] == 1 && bias.desc.GetLengths()[1] == out.desc.GetLengths()[0] && std::all_of(bias.desc.GetLengths().begin() + 2, bias.desc.GetLengths().end(), [](auto v) { return v == 1; })); std::size_t out_n_len = out.desc.GetLengths()[0]; std::size_t out_k_len = out.desc.GetLengths()[1]; std::array out_spatial_len{}; std::copy_n(out.desc.GetLengths().begin() + 2, NSpatialDim, out_spatial_len.begin()); miopen::par_ford(out_k_len)([&](auto out_k_id) { auto ford_out_n_spatial = miopen::unpacker(miopen::prepender(miopen::ford, out_n_len))(out_spatial_len); double acc = 0; ford_out_n_spatial([&](auto out_n_id, auto... out_spatial_id_pack) { acc += double(out(out_n_id, out_k_id, out_spatial_id_pack...)); }); bias.data[out_k_id] = acc; }); } template void cpu_bias_forward(tensor& out, const tensor& bias) { switch(out.desc.GetNumDims()) { case 3: { cpu_bias_forward_impl<1>(out, bias); break; } case 4: { cpu_bias_forward_impl<2>(out, bias); break; } case 5: { cpu_bias_forward_impl<3>(out, bias); break; } case 6: { cpu_bias_forward_impl<4>(out, bias); break; } default: { MIOPEN_THROW("not belong to any case"); } } } template void cpu_bias_backward_data(const tensor& out, tensor& bias) { switch(out.desc.GetNumDims()) { case 3: { cpu_bias_backward_data_impl<1>(out, bias); break; } case 4: { cpu_bias_backward_data_impl<2>(out, bias); break; } case 5: { cpu_bias_backward_data_impl<3>(out, bias); break; } case 6: { cpu_bias_backward_data_impl<4>(out, bias); break; } default: { MIOPEN_THROW("not belong to any case"); } } } #endif