aboutsummaryrefslogtreecommitdiff
path: root/src/backends/cl/test/ICLTensorProxyTests.cpp
blob: 4ee0b10cfe14663dedc3e427b3addd9fdb80022c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//
// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include <arm_compute/runtime/CL/functions/CLActivationLayer.h>

#include <armnnTestUtils/TensorCopyUtils.hpp>

#include <cl/ClImportTensorHandle.hpp>
#include <cl/ClImportTensorHandleFactory.hpp>
#include <cl/ClTensorHandle.hpp>
#include <cl/ClTensorHandleFactory.hpp>
#include <cl/ICLTensorProxy.hpp>
#include <cl/test/ClContextControlFixture.hpp>
#include <cl/test/ClWorkloadFactoryHelper.hpp>

#include <doctest/doctest.h>

using namespace armnn;

TEST_SUITE("ICLTensorProxyTests")
{

TEST_CASE_FIXTURE(ClContextControlFixture, "ICLTensorProxyTest")
{
    ClTensorHandleFactory handleFactory =
        ClWorkloadFactoryHelper::GetTensorHandleFactory(ClWorkloadFactoryHelper::GetMemoryManager());

    TensorInfo info({ 1, 3, 4, 1 }, DataType::Float32);

    // create TensorHandle for memory import
    auto handle = handleFactory.CreateTensorHandle(info, true);

    std::vector<float> inputData
    {
        -5, -2, 1, 2,
        3, 10, -20, 8,
        0, -12, 7, -9
    };

    handle->Allocate();

    CopyDataToITensorHandle(handle.get(), inputData.data());

    // Get CLtensor
    arm_compute::CLTensor& tensor = PolymorphicDowncast<ClTensorHandle*>(handle.get())->GetTensor();
    ICLTensorProxy iclTensorProxy(&tensor);

    // Check that the ICLTensorProxy get correct information from the delegate tensor
    CHECK((iclTensorProxy.info() == tensor.info()));
    CHECK((iclTensorProxy.buffer() == tensor.buffer()));
    CHECK((iclTensorProxy.cl_buffer() == tensor.cl_buffer()));
    CHECK((iclTensorProxy.quantization().scale == tensor.quantization().scale));
    CHECK((iclTensorProxy.quantization().offset == tensor.quantization().offset));
}

TEST_CASE_FIXTURE(ClContextControlFixture, "ChangeICLTensorProxyExecutionTest")
{
    // Start execution with with copied tensor
    ClTensorHandleFactory handleFactory =
        ClWorkloadFactoryHelper::GetTensorHandleFactory(ClWorkloadFactoryHelper::GetMemoryManager());

    TensorInfo info({ 1, 3, 4, 1 }, DataType::Float32);
    unsigned int numElements = info.GetNumElements();

    // create TensorHandle for memory import
    auto handle = handleFactory.CreateTensorHandle(info, true);

    std::vector<float> inputData
    {
        -5, -2, 1, 2,
        3, 10, -20, 8,
        0, -12, 7, -9
    };

    std::vector<float> ExpectedOutput
    {
        0, 0, 1, 2,
        3, 10, 0, 8,
        0, 0, 7, 0
    };

    handle->Allocate();

    CopyDataToITensorHandle(handle.get(), inputData.data());

    // Get CLtensor
    arm_compute::CLTensor& tensor = PolymorphicDowncast<ClTensorHandle*>(handle.get())->GetTensor();

    // Set a proxy tensor to allocated tensor
    std::unique_ptr<ICLTensorProxy> iclTensorProxy;
    iclTensorProxy = std::make_unique<ICLTensorProxy>(&tensor);

    // Create and configure activation function
    const arm_compute::ActivationLayerInfo act_info(arm_compute::ActivationLayerInfo::ActivationFunction::RELU);
    arm_compute::CLActivationLayer act_func;
    act_func.configure(iclTensorProxy.get(), nullptr, act_info);

    act_func.run();
    arm_compute::CLScheduler::get().sync();

    std::vector<float> actualOutput(info.GetNumElements());

    CopyDataFromITensorHandle(actualOutput.data(), handle.get());

    // Validate result as expected output
    for(unsigned int i = 0; i < numElements; ++i)
    {
        CHECK((actualOutput[i] == ExpectedOutput[i]));
    }

    // Change to execute with imported tensor
    ClImportTensorHandleFactory importHandleFactory(static_cast<MemorySourceFlags>(MemorySource::Malloc),
                                              static_cast<MemorySourceFlags>(MemorySource::Malloc));
    // create TensorHandle for memory import
    auto importHandle = importHandleFactory.CreateTensorHandle(info);

    // Get CLtensor
    arm_compute::CLTensor& importTensor = PolymorphicDowncast<ClImportTensorHandle*>(importHandle.get())->GetTensor();

    // Allocate user memory
    const size_t totalBytes = importTensor.info()->total_size();
    const size_t alignment =
        arm_compute::CLKernelLibrary::get().get_device().getInfo<CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE>();
    size_t space = totalBytes + alignment + alignment;
    auto testData = std::make_unique<uint8_t[]>(space);
    void* alignedPtr = testData.get();
    CHECK(std::align(alignment, totalBytes, alignedPtr, space));

    // Import memory
    CHECK(importHandle->Import(alignedPtr, armnn::MemorySource::Malloc));

    // Input with negative values
    auto* typedPtr = reinterpret_cast<float*>(alignedPtr);
    std::fill_n(typedPtr, numElements, -5.0f);

    // Set the import Tensor to TensorProxy to change Tensor in the CLActivationLayer without calling configure function
    iclTensorProxy->set(&importTensor);

    // Execute function and sync
    act_func.run();
    arm_compute::CLScheduler::get().sync();

    // Validate result by checking that the output has no negative values
    for(unsigned int i = 0; i < numElements; ++i)
    {
        CHECK(typedPtr[i] == 0);
    }
}
}