| 58 | |
| 59 | protected: |
| 60 | bool testOnBackend(MNNForwardType type, const std::string &deviceName, int precision) { |
| 61 | const int h = 7, w = 7, size = h * w; |
| 62 | const float originInputData[] = {0.3100, 0.0156, 0.0765, 0.1872, 0.2949, 0.2949, 0.0052, 0.0455, 0.3000, |
| 63 | 0.1872, -0.1304, 0.2939, 0.2949, 0.2437, -0.0330, 0.0641, 0.2934, 0.0452, |
| 64 | -0.1621, 0.2534, 0.3948, 0.2203, -0.0665, 0.1727, 0.1119, -0.1570, 0.1260, |
| 65 | 0.3523, 0.2305, 0.1664, 0.1277, 0.4092, -0.1601, 0.0929, 0.1138, 0.2331, |
| 66 | 0.3501, 0.3382, 0.2309, 0.2175, 0.0826, -0.1567, 0.0320, 0.1205, -0.0566, |
| 67 | 0.1267, -0.0004, 0.2930, 0.2353}; |
| 68 | const float poolInputGradData[] = {1., 2., 3., 2., 3., 1., 3., 1., 2.}; |
| 69 | const float maxExpectedGrad[] = {1., 0., 0., 0., 2., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 2., |
| 70 | 0., 0., 0., 4., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 4., 0., 0., |
| 71 | 0., 0., 3., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 2., 0.}; |
| 72 | const float aveExpectedGrad[] = { |
| 73 | 0.111111, 0.111111, 0.333333, 0.222222, 0.555556, 0.333333, 0.333333, 0.111111, 0.111111, 0.333333, |
| 74 | 0.222222, 0.555556, 0.333333, 0.333333, 0.333333, 0.333333, 0.888889, 0.555556, 1.000000, 0.444444, |
| 75 | 0.444444, 0.222222, 0.222222, 0.555556, 0.333333, 0.444444, 0.111111, 0.111111, 0.555556, 0.555556, |
| 76 | 1.000000, 0.444444, 0.777778, 0.333333, 0.333333, 0.333333, 0.333333, 0.444444, 0.111111, 0.333333, |
| 77 | 0.222222, 0.222222, 0.333333, 0.333333, 0.444444, 0.111111, 0.333333, 0.222222, 0.222222}; |
| 78 | |
| 79 | auto poolInput = _Input({1, 1, h, w}, NCHW, halide_type_of<float>()); |
| 80 | auto poolInputConvert = _Convert(poolInput, NC4HW4); |
| 81 | auto maxPoolOut = _MaxPool(poolInputConvert, {3, 3}, {2, 2}); |
| 82 | auto avePoolOut = _AvePool(poolInputConvert, {3, 3}, {2, 2}); |
| 83 | auto poolOutDim = maxPoolOut->getInfo()->dim; |
| 84 | |
| 85 | int poolSize = 1; |
| 86 | for (auto length : poolOutDim) { |
| 87 | poolSize *= length; |
| 88 | } |
| 89 | |
| 90 | auto poolInputGrad = _Input(poolOutDim, NCHW, halide_type_of<float>()); |
| 91 | auto poolInputGradConvert = _Convert(poolInputGrad, NC4HW4); |
| 92 | |
| 93 | auto maxPoolOutputGrad = |
| 94 | _Convert(_PoolGrad(poolInputConvert, maxPoolOut, poolInputGradConvert, {3, 3}, {2, 2}, MAXPOOL), NCHW); |
| 95 | auto avePoolOutputGrad = |
| 96 | _Convert(_PoolGrad(poolInputConvert, avePoolOut, poolInputGradConvert, {3, 3}, {2, 2}, AVEPOOL), NCHW); |
| 97 | |
| 98 | const std::vector<int> outDim = {1, 1, h, w}; |
| 99 | auto maxpoolOutputGradDim = maxPoolOutputGrad->getInfo()->dim; |
| 100 | auto avepoolOutputGradDim = avePoolOutputGrad->getInfo()->dim; |
| 101 | if (!checkVector<int>(maxpoolOutputGradDim.data(), outDim.data(), 4, 0)) { |
| 102 | MNN_ERROR("MaxpoolGrad(%s) shape test failed!\n", deviceName.c_str()); |
| 103 | return false; |
| 104 | } |
| 105 | if (!checkVector<int>(avepoolOutputGradDim.data(), outDim.data(), 4, 0)) { |
| 106 | MNN_ERROR("AvepoolGrad(%s) shape test failed!\n", deviceName.c_str()); |
| 107 | return false; |
| 108 | } |
| 109 | |
| 110 | ::memcpy(poolInput->writeMap<float>(), (const float *)originInputData, size * sizeof(float)); |
| 111 | ::memcpy(poolInputGrad->writeMap<float>(), (const float *)poolInputGradData, poolSize * sizeof(float)); |
| 112 | auto compute = maxPoolOutputGrad->readMap<float>(); |
| 113 | float errorScale = precision <= MNN::BackendConfig::Precision_High ? 1 : 100; |
| 114 | if (!checkVectorByRelativeError<float>(compute, maxExpectedGrad, size, 0.001 * errorScale)) { |
| 115 | MNN_ERROR("MaxpoolGrad(%s) test failed!\n", deviceName.c_str()); |
| 116 | return false; |
| 117 | } |