| 143 | } |
| 144 | |
| 145 | void BackwardConcatColumnTest(std::shared_ptr<singa::Device> dev) { |
| 146 | size_t a = 2u, b = 1u, c = 3u; |
| 147 | singa::LayerConf conf; |
| 148 | conf.set_type("singa_concat"); |
| 149 | conf.mutable_concat_conf()->set_axis(1); |
| 150 | singa::Concat layer; |
| 151 | layer.Setup({{a}, {b}}, conf); |
| 152 | layer.ToDevice(dev); |
| 153 | |
| 154 | singa::Tensor t1({c, a}, dev); |
| 155 | singa::Tensor t2({c, b}, dev); |
| 156 | t1.SetValue(1.0f); |
| 157 | t2.SetValue(2.0f); |
| 158 | layer.Forward(singa::kTrain, {t1, t2}); |
| 159 | |
| 160 | singa::Tensor t({c, a + b}, dev); |
| 161 | singa::Uniform(-1.f, 1.f, &t); |
| 162 | auto out = layer.Backward(singa::kTrain, {t}); |
| 163 | auto grads = out.first; |
| 164 | EXPECT_EQ(grads.size(), 2u); |
| 165 | |
| 166 | t.ToHost(); |
| 167 | const float* tptr = t.data<float>(); |
| 168 | |
| 169 | grads[0].ToHost(); |
| 170 | const float* outa = grads[0].data<float>(); |
| 171 | for (size_t i = 0; i < c; i++) |
| 172 | for (size_t j = 0; j < a; j++) |
| 173 | EXPECT_FLOAT_EQ(outa[i * a + j], tptr[i * (a + b) + j]); |
| 174 | grads[1].ToHost(); |
| 175 | const float* outb = grads[1].data<float>(); |
| 176 | for (size_t i = 0; i < c; i++) |
| 177 | for (size_t j = 0; j < b; j++) |
| 178 | EXPECT_FLOAT_EQ(outb[i * b + j], tptr[i * (a + b) + a + j]); |
| 179 | } |
| 180 | |
| 181 | TEST(Concat, BackwardConcatRowCpp) { |
| 182 | BackwardConcatRowTest(singa::defaultDevice); |