| 107 | #endif // USE_CUDA |
| 108 | |
| 109 | void BackwardConcatRowTest(std::shared_ptr<singa::Device> dev) { |
| 110 | size_t a = 2u, b = 1u, c = 3u; |
| 111 | singa::LayerConf conf; |
| 112 | conf.set_type("singa_concat"); |
| 113 | conf.mutable_concat_conf()->set_axis(0); |
| 114 | singa::Concat layer; |
| 115 | layer.Setup({{c}, {c}}, conf); |
| 116 | layer.ToDevice(dev); |
| 117 | |
| 118 | singa::Tensor t1({a, c}, dev); |
| 119 | singa::Tensor t2({b, c}, dev); |
| 120 | t1.SetValue(1.0f); |
| 121 | t2.SetValue(2.0f); |
| 122 | layer.Forward(singa::kTrain, {t1, t2}); |
| 123 | |
| 124 | singa::Tensor t({a + b, c}, dev); |
| 125 | singa::Uniform(-1.f, 1.f, &t); |
| 126 | auto out = layer.Backward(singa::kTrain, {t}); |
| 127 | auto grads = out.first; |
| 128 | EXPECT_EQ(grads.size(), 2u); |
| 129 | |
| 130 | t.ToHost(); |
| 131 | const float* tptr = t.data<float>(); |
| 132 | |
| 133 | grads[0].ToHost(); |
| 134 | const float* outa = grads[0].data<float>(); |
| 135 | for (size_t i = 0; i < a; i++) |
| 136 | for (size_t j = 0; j < c; j++) |
| 137 | EXPECT_FLOAT_EQ(outa[i * c + j], tptr[i * c + j]); |
| 138 | grads[1].ToHost(); |
| 139 | const float* outb = grads[1].data<float>(); |
| 140 | for (size_t i = 0; i < b; i++) |
| 141 | for (size_t j = 0; j < c; j++) |
| 142 | EXPECT_FLOAT_EQ(outb[i * c + j], tptr[(i + a) * c + j]); |
| 143 | } |
| 144 | |
| 145 | void BackwardConcatColumnTest(std::shared_ptr<singa::Device> dev) { |
| 146 | size_t a = 2u, b = 1u, c = 3u; |