1 // 2 // Copyright © 2017 Arm Ltd. All rights reserved. 3 // SPDX-License-Identifier: MIT 4 // 5 6 #include "NeonWorkloadFactoryHelper.hpp" 7 8 9 #include <armnnTestUtils/TensorHelpers.hpp> 10 11 #include <armnn/backends/TensorHandle.hpp> 12 #include <armnn/backends/WorkloadFactory.hpp> 13 14 #include <neon/NeonTimer.hpp> 15 #include <neon/NeonWorkloadFactory.hpp> 16 17 #include <backendsCommon/test/LayerTests.hpp> 18 #include <armnnTestUtils/TensorCopyUtils.hpp> 19 #include <armnnTestUtils/WorkloadTestUtils.hpp> 20 21 #include <doctest/doctest.h> 22 23 #include <cstdlib> 24 #include <algorithm> 25 26 using namespace armnn; 27 28 TEST_SUITE("NeonTimerInstrument") 29 { 30 31 TEST_CASE("NeonTimerGetName") 32 { 33 NeonTimer neonTimer; 34 CHECK_EQ(std::string(neonTimer.GetName()), "NeonKernelTimer"); 35 } 36 37 TEST_CASE("NeonTimerMeasure") 38 { 39 NeonWorkloadFactory workloadFactory = 40 NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager()); 41 42 unsigned int inputWidth = 2000u; 43 unsigned int inputHeight = 2000u; 44 unsigned int inputChannels = 1u; 45 unsigned int inputBatchSize = 1u; 46 47 float upperBound = 1.0f; 48 float lowerBound = -1.0f; 49 50 size_t inputSize = inputWidth * inputHeight * inputChannels * inputBatchSize; 51 std::vector<float> inputData(inputSize, 0.f); __anon0ef174230102()52 std::generate(inputData.begin(), inputData.end(), [](){ 53 return (static_cast<float>(rand()) / static_cast<float>(RAND_MAX / 3)) + 1.f; }); 54 55 unsigned int outputWidth = inputWidth; 56 unsigned int outputHeight = inputHeight; 57 unsigned int outputChannels = inputChannels; 58 unsigned int outputBatchSize = inputBatchSize; 59 60 armnn::TensorInfo inputTensorInfo({ inputBatchSize, inputChannels, inputHeight, inputWidth }, 61 armnn::DataType::Float32); 62 63 armnn::TensorInfo outputTensorInfo({ outputBatchSize, outputChannels, outputHeight, outputWidth }, 64 armnn::DataType::Float32); 65 66 ARMNN_NO_DEPRECATE_WARN_BEGIN 67 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo); 68 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo); 69 ARMNN_NO_DEPRECATE_WARN_END 70 71 // Setup bounded ReLu 72 armnn::ActivationQueueDescriptor descriptor; 73 armnn::WorkloadInfo workloadInfo; 74 AddInputToWorkload(descriptor, workloadInfo, inputTensorInfo, inputHandle.get()); 75 AddOutputToWorkload(descriptor, workloadInfo, outputTensorInfo, outputHandle.get()); 76 77 descriptor.m_Parameters.m_Function = armnn::ActivationFunction::BoundedReLu; 78 descriptor.m_Parameters.m_A = upperBound; 79 descriptor.m_Parameters.m_B = lowerBound; 80 81 std::unique_ptr<armnn::IWorkload> workload 82 = workloadFactory.CreateWorkload(LayerType::Activation, descriptor, workloadInfo); 83 84 inputHandle->Allocate(); 85 outputHandle->Allocate(); 86 87 CopyDataToITensorHandle(inputHandle.get(), inputData.data()); 88 89 NeonTimer neonTimer; 90 // Start the timer. 91 neonTimer.Start(); 92 // Execute the workload. 93 workload->Execute(); 94 // Stop the timer. 95 neonTimer.Stop(); 96 97 std::vector<Measurement> measurements = neonTimer.GetMeasurements(); 98 99 CHECK(measurements.size() <= 2); 100 if (measurements.size() > 1) 101 { 102 CHECK_EQ(measurements[0].m_Name, "NeonKernelTimer/0: NEFillBorderKernel"); 103 CHECK(measurements[0].m_Value > 0.0); 104 } 105 std::ostringstream oss_neon; 106 std::ostringstream oss_cpu; 107 oss_neon << "NeonKernelTimer/" << measurements.size()-1 << ": NEActivationLayerKernel"; 108 oss_cpu << "NeonKernelTimer/" << measurements.size()-1 << ": CpuActivationKernel"; 109 bool kernelCheck = ((measurements[measurements.size()-1].m_Name.find(oss_neon.str()) != std::string::npos) 110 || (measurements[measurements.size()-1].m_Name.find(oss_cpu.str()) != std::string::npos)); 111 CHECK(kernelCheck); 112 CHECK(measurements[measurements.size()-1].m_Value > 0.0); 113 } 114 115 } 116