// Copyright 2018 Xiaomi, Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "mace/core/operator.h" #include "mace/ops/ops_test_util.h" namespace mace { namespace ops { namespace test { class SoftmaxOpTest : public OpsTestBase {}; namespace { template void Simple() { // Construct graph OpsTestNet net; // Add input data net.AddInputFromArray("Input", {1, 1, 2, 4}, {1, 1, 1, 1, 1, 2, 3, 4}); if (D == DeviceType::CPU) { net.TransformDataFormat("Input", NHWC, "InputNCHW", NCHW); OpDefBuilder("Softmax", "SoftmaxTest") .Input("InputNCHW") .Output("OutputNCHW") .Finalize(net.NewOperatorDef()); // Run net.RunOp(D); net.TransformDataFormat("OutputNCHW", NCHW, "Output", NHWC); } else if (D == DeviceType::OPENCL) { BufferToImage(&net, "Input", "InputImage", kernels::BufferType::IN_OUT_CHANNEL); OpDefBuilder("Softmax", "SoftmaxTest") .Input("InputImage") .Output("OutputImage") .Finalize(net.NewOperatorDef()); // Run net.RunOp(D); // Transfer output ImageToBuffer(&net, "OutputImage", "Output", kernels::BufferType::IN_OUT_CHANNEL); } else { MACE_NOT_IMPLEMENTED; } auto expected = CreateTensor( {1, 1, 2, 4}, {0.25, 0.25, 0.25, 0.25, 0.0320586, 0.08714432, 0.23688282, 0.64391426}); ExpectTensorNear(*expected, *net.GetOutput("Output"), 1e-5); } } // namespace TEST_F(SoftmaxOpTest, CPUSimple) { Simple(); } TEST_F(SoftmaxOpTest, OPENCLSimple) { Simple(); } namespace { template void Complex(const std::vector &logits_shape) { // Construct graph OpsTestNet net; // Add input data net.AddRandomInput("Input", logits_shape); net.TransformDataFormat("Input", NHWC, "InputNCHW", NCHW); OpDefBuilder("Softmax", "SoftmaxTest") .Input("InputNCHW") .Output("OutputNCHW") .Finalize(net.NewOperatorDef()); // Run on cpu net.RunOp(); net.TransformDataFormat("OutputNCHW", NCHW, "Output", NHWC); Tensor expected; expected.Copy(*net.GetOutput("Output")); BufferToImage(&net, "Input", "InputImage", kernels::BufferType::IN_OUT_CHANNEL); OpDefBuilder("Softmax", "SoftmaxTest") .Input("InputImage") .Output("OutputImage") .Finalize(net.NewOperatorDef()); // Run on gpu net.RunOp(D); // Transfer output ImageToBuffer(&net, "OutputImage", "OPENCLOutput", kernels::BufferType::IN_OUT_CHANNEL); ExpectTensorNear(expected, *net.GetOutput("OPENCLOutput"), 1e-5); } } // namespace TEST_F(SoftmaxOpTest, OPENCLAligned) { Complex({1, 256, 256, 3}); Complex({1, 128, 128, 16}); } TEST_F(SoftmaxOpTest, OPENCLMulBatchAligned) { Complex({5, 64, 64, 3}); Complex({8, 128, 128, 8}); } TEST_F(SoftmaxOpTest, OPENCLUnAligned) { Complex({1, 113, 107, 13}); Complex({5, 211, 107, 1}); } } // namespace test } // namespace ops } // namespace mace