blob: 974bf5a0ad2cf4866967fe35a72365851f996d83 [file] [log] [blame]
/************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#include "../src/model/layer/slice.h"
#include "gtest/gtest.h"
using singa::Shape;
TEST(Slice, Setup) {
singa::LayerConf conf;
conf.set_type("singa_slice");
auto slice_conf = conf.mutable_slice_conf();
slice_conf->set_axis(1);
slice_conf->add_slice_point(2);
singa::Slice layer;
layer.Setup({3u}, conf);
auto s1 = layer.GetOutputSampleShape(0);
EXPECT_EQ(s1[0], 2u);
auto s2 = layer.GetOutputSampleShape(1);
EXPECT_EQ(s2[0], 1u);
}
void ForwardSliceRowTest(std::shared_ptr<singa::Device> dev) {
size_t a = 2u, b = 1u, c = 3u;
singa::LayerConf conf;
conf.set_type("singa_slice");
auto slice_conf = conf.mutable_slice_conf();
slice_conf->set_axis(0);
slice_conf->add_slice_point(a);
singa::Slice layer;
layer.Setup({c}, conf);
layer.ToDevice(dev);
singa::Tensor t({a + b, c}, dev);
singa::Uniform(-1.f, 1.f, &t);
auto grads = layer.Forward(singa::kTrain, {t});
EXPECT_EQ(grads.size(), 2u);
t.ToHost();
const float* tptr = t.data<float>();
grads[0].ToHost();
const float* outa = grads[0].data<float>();
for (size_t i = 0; i < a; i++)
for (size_t j = 0; j < c; j++)
EXPECT_FLOAT_EQ(outa[i * c + j], tptr[i * c + j]);
grads[1].ToHost();
const float* outb = grads[1].data<float>();
for (size_t i = 0; i < b; i++)
for (size_t j = 0; j < c; j++)
EXPECT_FLOAT_EQ(outb[i * c + j], tptr[(i + a) * c + j]);
}
void ForwardSliceColumnTest(std::shared_ptr<singa::Device> dev) {
size_t a = 2u, b = 1u, c = 3u;
singa::LayerConf conf;
conf.set_type("singa_slice");
auto slice_conf = conf.mutable_slice_conf();
slice_conf->set_axis(1);
slice_conf->add_slice_point(a);
singa::Slice layer;
layer.Setup({a + b}, conf);
layer.ToDevice(dev);
singa::Tensor t({c, a + b}, dev);
singa::Uniform(-1.f, 1.f, &t);
auto out = layer.Forward(singa::kTrain, {t});
EXPECT_EQ(out.size(), 2u);
t.ToHost();
const float* tptr = t.data<float>();
out[0].ToHost();
const float* outa = out[0].data<float>();
for (size_t i = 0; i < c; i++)
for (size_t j = 0; j < a; j++)
EXPECT_FLOAT_EQ(outa[i * a + j], tptr[i * (a + b) + j]);
out[1].ToHost();
const float* outb = out[1].data<float>();
for (size_t i = 0; i < c; i++)
for (size_t j = 0; j < b; j++)
EXPECT_FLOAT_EQ(outb[i * b + j], tptr[i * (a + b) + a + j]);
}
TEST(Slice, ForwardSliceRowCpp) { ForwardSliceRowTest(singa::defaultDevice); }
TEST(Slice, ForwardSliceColumn) {
ForwardSliceColumnTest(singa::defaultDevice);
}
#ifdef USE_CUDA
TEST(Slice, ForwardSliceRowCuda) {
ForwardSliceRowTest(std::make_shared<singa::CudaGPU>());
}
TEST(Slice, ForwardSliceColumnCuda) {
ForwardSliceColumnTest(std::make_shared<singa::CudaGPU>());
}
#endif // USE_CUDA
void BackwardSliceRowTest(std::shared_ptr<singa::Device> dev) {
size_t a = 2u, b = 1u, c = 3u;
singa::LayerConf conf;
conf.set_type("singa_slice");
auto slice_conf = conf.mutable_slice_conf();
slice_conf->set_axis(0);
slice_conf->add_slice_point(2);
singa::Slice layer;
layer.Setup({c}, conf);
layer.ToDevice(dev);
singa::Tensor t1({a, c}, dev);
singa::Tensor t2({b, c}, dev);
t1.SetValue(1.0f);
t2.SetValue(2.0f);
auto out = layer.Backward(singa::kTrain, {t1, t2});
auto grad = out.first[0];
grad.ToHost();
const float* outptr = grad.data<float>();
for (size_t i = 0; i < a; i++) {
for (size_t j = 0; j < c; j++) EXPECT_FLOAT_EQ(outptr[i * c + j], 1.0f);
}
for (size_t i = a; i < a + b; i++) {
for (size_t j = 0; j < c; j++) EXPECT_FLOAT_EQ(outptr[i * c + j], 2.0f);
}
}
void BackwardSliceColumnTest(std::shared_ptr<singa::Device> dev) {
size_t a = 2u, b = 1u, c = 3u;
singa::LayerConf conf;
conf.set_type("singa_slice");
auto slice_conf = conf.mutable_slice_conf();
slice_conf->set_axis(1);
slice_conf->add_slice_point(2);
singa::Slice layer;
layer.Setup({a + b}, conf);
layer.ToDevice(dev);
singa::Tensor t1({c, a}, dev);
singa::Tensor t2({c, b}, dev);
t1.SetValue(1.0f);
t2.SetValue(2.0f);
auto out = layer.Backward(singa::kTrain, {t1, t2});
auto grad = out.first[0];
grad.ToHost();
const float* outptr = grad.data<float>();
for (size_t i = 0; i < c; i++) {
for (size_t j = 0; j < a; j++)
EXPECT_FLOAT_EQ(outptr[i * (a + b) + j], 1.0f);
}
for (size_t i = 0; i < c; i++) {
for (size_t j = a; j < a + b; j++)
EXPECT_FLOAT_EQ(outptr[i * (a + b) + j], 2.0f);
}
}
TEST(Slice, BackwardSliceRowCpp) { BackwardSliceRowTest(singa::defaultDevice); }
TEST(Slice, BackwardSliceColumn) {
BackwardSliceColumnTest(singa::defaultDevice);
}
#ifdef USE_CUDA
TEST(Slice, BackwardSliceRowCuda) {
BackwardSliceRowTest(std::make_shared<singa::CudaGPU>());
}
TEST(Slice, BackwardSliceColumnCuda) {
BackwardSliceColumnTest(std::make_shared<singa::CudaGPU>());
}
#endif // USE_CUDA