cavis/libnd4j/tests_cpu/layers_tests/GraphTests.cpp

1639 lines
48 KiB
C++

/*******************************************************************************
* Copyright (c) 2015-2018 Skymind, Inc.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://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.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/
//
// @author raver119@gmail.com
//
#include "testlayers.h"
#include <flatbuffers/flatbuffers.h>
#include <graph/generated/node_generated.h>
#include <graph/generated/graph_generated.h>
#include <graph/Node.h>
#include <graph/Graph.h>
#include <graph/GraphUtils.h>
#include <array/NDArray.h>
#include <ops/declarable/DeclarableOp.h>
#include <ops/declarable/generic/parity_ops.cpp>
using namespace sd;
using namespace sd::graph;
class GraphTests : public testing::Test {
public:
/*
int cShape[] = {2, 2, 2, 2, 1, 0, 1, 99};
int fShape[] = {2, 2, 2, 1, 2, 0, 1, 102};
*/
GraphTests() {
//Environment::getInstance().setDebug(true);
//Environment::getInstance().setVerbose(true);
}
};
TEST_F(GraphTests, SingleInput1) {
auto graph = new Graph();
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0f);
graph->getVariableSpace()->putVariable(-1, x);
auto nodeA = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2});
auto nodeB = new Node(OpType_TRANSFORM_STRICT, transform::Cosine, 2, {1}, {3});
auto nodeC = new Node(OpType_TRANSFORM_SAME, transform::Abs, 3, {2}, {});
graph->addNode(nodeA);
graph->addNode(nodeB);
graph->addNode(nodeC);
ASSERT_EQ(1, graph->rootNodes());
ASSERT_EQ(3, graph->totalNodes());
GraphExecutioner::execute(graph);
ASSERT_TRUE(graph->getVariableSpace()->hasVariable(3));
auto node3 = graph->getVariableSpace()->getVariable(3)->getNDArray();
ASSERT_NEAR(0.4161468, node3->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
delete graph;
}
TEST_F(GraphTests, DoubleInput1) {
auto graph = new Graph();
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
auto y = NDArrayFactory::create_<float>('c', {5, 5});
y->assign(-1.0);
auto z = NDArrayFactory::create_<float>('c', {5, 5});
graph->getVariableSpace()->putVariable(-1, x);
graph->getVariableSpace()->putVariable(-2, y);
graph->getVariableSpace()->putVariable(-3, z);
auto nodeA = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {3});
auto nodeB = new Node(OpType_TRANSFORM_SAME, transform::Abs, 2, {-2}, {3});
auto nodeC = new Node(OpType_PAIRWISE, pairwise::Add, 3, {1, 2}, {-3});
graph->addNode(nodeA);
graph->addNode(nodeB);
graph->addNode(nodeC);
ASSERT_EQ(2, graph->rootNodes());
ASSERT_EQ(3, graph->totalNodes());
GraphExecutioner::execute(graph);
ASSERT_NEAR(3.0, z->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
delete graph;
}
TEST_F(GraphTests, SingleInput3) {
auto graph = new Graph();
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
auto v0 = NDArrayFactory::create_<float>('c', {5, 5});
auto v1 = NDArrayFactory::create_<float>('c', {5, 5});
graph->getVariableSpace()->putVariable(-1, x);
graph->getVariableSpace()->putVariable(-2, v0);
graph->getVariableSpace()->putVariable(-3, v1);
auto nodeA = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2, 3});
auto nodeB = new Node(OpType_TRANSFORM_FLOAT, transform::Sqrt, 2, {1}, {-2});
auto nodeC = new Node(OpType_TRANSFORM_SAME, transform::Ones, 3, {1}, {-3});
graph->addNode(nodeA);
graph->addNode(nodeB);
graph->addNode(nodeC);
ASSERT_EQ(1, graph->rootNodes());
ASSERT_EQ(3, graph->totalNodes());
GraphExecutioner::execute(graph);
ASSERT_NEAR(1.4142135, v0->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
ASSERT_NEAR(1.0, v1->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
delete graph;
}
TEST_F(GraphTests, SingleInput4) {
auto graph = new Graph();
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
auto v0 = NDArrayFactory::create_<float>('c', {5, 5});
auto v1 = NDArrayFactory::create_<float>('c', {5, 5});
graph->getVariableSpace()->putVariable(-1, x);
graph->getVariableSpace()->putVariable(-2, v0);
graph->getVariableSpace()->putVariable(-3, v1);
auto nodeA = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2});
auto nodeB = new Node(OpType_TRANSFORM_FLOAT, transform::Sqrt, 2, {1}, {3});
auto nodeC = new Node(OpType_TRANSFORM_SAME, transform::Neg, 3, {2}, {4, 5});
auto nodeS = new Node(OpType_TRANSFORM_SAME, transform::Ones, 4, {3}, {-2});
auto nodeE = new Node(OpType_TRANSFORM_SAME, transform::Identity, 5, {3}, {-3});
graph->addNode(nodeA);
graph->addNode(nodeB);
graph->addNode(nodeC);
graph->addNode(nodeS);
graph->addNode(nodeE);
ASSERT_EQ(1, graph->rootNodes());
ASSERT_EQ(5, graph->totalNodes());
GraphExecutioner::execute(graph);
ASSERT_NEAR(1.0, v0->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
ASSERT_NEAR(-1.4142135, v1->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
delete graph;
}
TEST_F(GraphTests, DoubleInput2) {
auto graph = new Graph();
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
auto y = NDArrayFactory::create_<float>('c', {5, 5});
y->assign(-1.0);
auto z0 = NDArrayFactory::create_<float>('c', {5, 5});
auto z1 = NDArrayFactory::create_<float>('c', {5, 5});
graph->getVariableSpace()->putVariable(-1, x);
graph->getVariableSpace()->putVariable(-2, y);
graph->getVariableSpace()->putVariable(-3, z0);
graph->getVariableSpace()->putVariable(-4, z1);
auto nodeA = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2});
auto nodeB = new Node(OpType_TRANSFORM_FLOAT, transform::Sqrt, 2, {1}, {3});
auto nodeC = new Node(OpType_TRANSFORM_SAME, transform::Neg, 3, {2}, {-3});
auto nodeT = new Node(OpType_TRANSFORM_SAME, transform::Abs, 11, {-2}, {12});
auto nodeU = new Node(OpType_TRANSFORM_FLOAT, transform::Sqrt, 12, {11}, {13});
auto nodeV = new Node(OpType_TRANSFORM_SAME, transform::Neg, 13, {12}, {-4});
graph->addNode(nodeA);
graph->addNode(nodeB);
graph->addNode(nodeC);
graph->addNode(nodeT);
graph->addNode(nodeU);
graph->addNode(nodeV);
ASSERT_EQ(2, graph->rootNodes());
ASSERT_EQ(6, graph->totalNodes());
GraphExecutioner::execute(graph);
ASSERT_NEAR(-1.4142135, z0->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
ASSERT_NEAR(-1.0, z1->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
delete graph;
}
TEST_F(GraphTests, DoubleInput3) {
auto graph = new Graph();
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
auto y = NDArrayFactory::create_<float>('c', {5, 5});
y->assign(-1.0);
auto z0 = NDArrayFactory::create_<float>('c', {5, 5});
auto z1 = NDArrayFactory::create_<float>('c', {5, 5});
auto w = NDArrayFactory::create_<float>('c', {5, 5});
graph->getVariableSpace()->putVariable(-1, x);
graph->getVariableSpace()->putVariable(-2, y);
graph->getVariableSpace()->putVariable(-3, z0);
graph->getVariableSpace()->putVariable(-4, z1);
graph->getVariableSpace()->putVariable(-5, w);
auto nodeA = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2});
auto nodeB = new Node(OpType_TRANSFORM_FLOAT, transform::Sqrt, 2, {1}, {3});
auto nodeC = new Node(OpType_TRANSFORM_SAME, transform::Neg, 3, {2}, {-3, 21});
auto nodeT = new Node(OpType_TRANSFORM_SAME, transform::Abs, 11, {-2}, {12});
auto nodeU = new Node(OpType_TRANSFORM_FLOAT, transform::Sqrt, 12, {11}, {13});
auto nodeV = new Node(OpType_TRANSFORM_SAME, transform::Neg, 13, {12}, {-4, 21});
auto nodeW = new Node(OpType_PAIRWISE, pairwise::Add, 21, {3, 13}, {22});
auto nodeZ = new Node(OpType_TRANSFORM_SAME, transform::Abs, 22, {21}, {-5});
graph->addNode(nodeA);
graph->addNode(nodeB);
graph->addNode(nodeC);
graph->addNode(nodeT);
graph->addNode(nodeU);
graph->addNode(nodeV);
graph->addNode(nodeW);
graph->addNode(nodeZ);
ASSERT_EQ(2, graph->rootNodes());
ASSERT_EQ(8, graph->totalNodes());
GraphExecutioner::execute(graph);
ASSERT_NEAR(-1.4142135, z0->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
ASSERT_NEAR(-1.0, z1->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
ASSERT_NEAR(2.4142135, w->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
delete graph;
}
TEST_F(GraphTests, QuadInput1) {
auto graph = new Graph();
auto x0 = NDArrayFactory::create_<float>('c', {5, 5});
x0->assign(0.0);
auto x1 = NDArrayFactory::create_<float>('c', {5, 5});
x1->assign(-1.0);
auto x2 = NDArrayFactory::create_<float>('c', {5, 5});
x2->assign(-2.0);
auto x3 = NDArrayFactory::create_<float>('c', {5, 5});
x3->assign(-3.0);
auto z = NDArrayFactory::create_<float>('c', {5, 5});
z->assign(119.0);
graph->getVariableSpace()->putVariable(-1, x0);
graph->getVariableSpace()->putVariable(-2, x1);
graph->getVariableSpace()->putVariable(-3, x2);
graph->getVariableSpace()->putVariable(-4, x3);
graph->getVariableSpace()->putVariable(-5, z);
auto nodeA = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {11});
auto nodeB = new Node(OpType_TRANSFORM_SAME, transform::Abs, 2, {-2}, {11});
auto nodeC = new Node(OpType_TRANSFORM_SAME, transform::Abs, 3, {-3}, {21});
auto nodeD = new Node(OpType_TRANSFORM_SAME, transform::Abs, 4, {-4}, {21});
auto nodeP1 = new Node(OpType_PAIRWISE, pairwise::Add, 11, {1, 2}, {31});
auto nodeP2 = new Node(OpType_PAIRWISE, pairwise::Add, 21, {3, 4}, {31});
auto nodeZ = new Node(OpType_PAIRWISE, pairwise::Add, 31, {11, 21}, {-5});
graph->addNode(nodeA);
graph->addNode(nodeB);
graph->addNode(nodeC);
graph->addNode(nodeD);
graph->addNode(nodeP1);
graph->addNode(nodeP2);
graph->addNode(nodeZ);
ASSERT_EQ(4, graph->rootNodes());
ASSERT_EQ(7, graph->totalNodes());
GraphExecutioner::execute(graph);
ASSERT_NEAR(6.0, z->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
delete graph;
}
TEST_F(GraphTests, InternalBranching1) {
auto graph = new Graph();
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(0.0);
auto z = NDArrayFactory::create_<float>('c', {5, 5});
graph->getVariableSpace()->putVariable(-1, x);
graph->getVariableSpace()->putVariable(-2, z);
// 1.0
auto nodeA = new Node(OpType_TRANSFORM_SAME, transform::Ones, 1, {-1}, {11, 21});
// -1
auto nodeK = new Node(OpType_TRANSFORM_SAME, transform::Neg, 11, {1}, {12});
// 2.0
auto nodeL = new Node(OpType_TRANSFORM_SAME, transform::OneMinus, 12, {11}, {31});
// -1
auto nodeR = new Node(OpType_TRANSFORM_SAME, transform::Neg, 21, {1}, {22});
// 1
auto nodeS = new Node(OpType_TRANSFORM_SAME, transform::Neg, 22, {21}, {31});
// 1.0
auto nodeZ = new Node(OpType_PAIRWISE, pairwise::Add, 31, {12, 22}, {-2});
graph->addNode(nodeA);
graph->addNode(nodeK);
graph->addNode(nodeL);
graph->addNode(nodeR);
graph->addNode(nodeS);
graph->addNode(nodeZ);
ASSERT_EQ(1, graph->rootNodes());
ASSERT_EQ(6, graph->totalNodes());
GraphExecutioner::execute(graph);
ASSERT_EQ(3, nodeZ->getLayer());
ASSERT_NEAR(3.0, z->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
delete graph;
}
TEST_F(GraphTests, ReductionsTest1) {
auto graph = new Graph();
auto x = NDArrayFactory::create_<float>('c', {5, 5});
for (int r = 0; r < x->rows(); r++) {
for (int c = 0; c < x->columns(); c++) {
x->p(r, c, -c);
}
}
auto z = NDArrayFactory::create_<float>('c', {5});
graph->getVariableSpace()->putVariable(-1, x);
graph->getVariableSpace()->putVariable(-2, z);
// sd::graph::Node::Node(OpType opType, int opNum, int id, std::initializer_list<int> input, std::initializer_list<int> output, std::initializer_list<int> dimensions, float scalar, std::initializer_list<double> tArgs, std::initializer_list<int> iArgs) {
auto nodeA = new Node(OpType_REDUCE_FLOAT, reduce::Mean, 1, {-1}, {2}, {1}, {});
auto nodeB = new Node(OpType_TRANSFORM_SAME, transform::Abs, 2, {1}, {-2});
graph->addNode(nodeA);
graph->addNode(nodeB);
ASSERT_EQ(1, graph->rootNodes());
ASSERT_EQ(2, graph->totalNodes());
GraphExecutioner::execute(graph);
ASSERT_NEAR(2.0, z->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
delete graph;
}
TEST_F(GraphTests, IndexReductionsTest1) {
auto graph = new Graph();
auto x = NDArrayFactory::create_<float>('c', {5, 5});
for (int r = 0; r < x->rows(); r++) {
for (int c = 0; c < x->columns(); c++) {
x->p(r, c, -c);
}
}
auto z = NDArrayFactory::create_<Nd4jLong>('c', {5, 1});
auto axis = NDArrayFactory::create_<Nd4jLong>('c', {1}, {1});
graph->getVariableSpace()->putVariable(-1, x);
graph->getVariableSpace()->putVariable(-2, z);
//graph->getVariableSpace()->putVariable(-3, axis);
auto nodeA = new Node(OpType_INDEX_REDUCE, indexreduce::IndexMin, 1, {-1}, {2}, {1});
auto nodeB = new Node(OpType_TRANSFORM_SAME, transform::Abs, 2, {1}, {-2});
graph->addNode(nodeA);
graph->addNode(nodeB);
ASSERT_EQ(1, graph->rootNodes());
ASSERT_EQ(2, graph->totalNodes());
GraphExecutioner::execute(graph);
ASSERT_NEAR(4.0, z->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
delete graph;
delete axis;
}
#if 0
TEST_F(GraphTests, AutoOutput1) {
auto graph = new Graph();
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
graph->getVariableSpace()->putVariable(-1, x);
auto nodeA = new Node(OpType_TRANSFORM_FLOAT, 0, 1, {-1}, {2});
auto nodeB = new Node(OpType_TRANSFORM_FLOAT, 35, 2, {1}, {});
graph->addNode(nodeA);
graph->addNode(nodeB);
ASSERT_EQ(1, graph->rootNodes());
ASSERT_EQ(2, graph->totalNodes());
graph->buildGraph();
ASSERT_TRUE(graph->getVariableSpace()->getVariable(2) != nullptr);
GraphExecutioner::execute(graph);
auto outputs = graph->fetchOutputs();
ASSERT_EQ(1, outputs->size());
ASSERT_TRUE(outputs->at(0) != nullptr);
ASSERT_NEAR(-1.0, outputs->at(0)->getNDArray()->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
delete outputs;
delete graph;
}
TEST_F(GraphTests, AutoOutput2) {
auto graph = new Graph();
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
graph->getVariableSpace()->putVariable(-1, x);
auto nodeA = new Node(OpType_TRANSFORM_SAME, 0, 1, {-1}, {2, 3, -1});
auto nodeB = new Node(OpType_TRANSFORM_SAME, 35, 2, {1}, {});
auto nodeC = new Node(OpType_TRANSFORM_SAME, 6, 3, {1}, {});
graph->addNode(nodeA);
graph->addNode(nodeB);
graph->addNode(nodeC);
ASSERT_EQ(1, graph->rootNodes());
ASSERT_EQ(3, graph->totalNodes());
graph->buildGraph();
ASSERT_TRUE(graph->getVariableSpace()->getVariable(-1) != nullptr);
ASSERT_TRUE(graph->getVariableSpace()->getVariable(2) != nullptr);
ASSERT_TRUE(graph->getVariableSpace()->getVariable(3) != nullptr);
GraphExecutioner::execute(graph);
auto outputs = graph->fetchOutputs();
ASSERT_EQ(2, outputs->size());
ASSERT_TRUE(outputs->at(0) != nullptr);
ASSERT_NEAR(-1.0, outputs->at(0)->getNDArray()->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
ASSERT_NEAR(-2.0, outputs->at(1)->getNDArray()->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
delete graph;
delete outputs;
}
#endif
TEST_F(GraphTests, BroadcastTest1) {
auto graph = new Graph();
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(0.f);
auto y = NDArrayFactory::create_<float>('c', {1, 5});
for (int e = 0; e < y->columns(); e++) {
y->p(e, (float)e+1);
}
auto z = NDArrayFactory::create_<float>('c', {5, 5});
graph->getVariableSpace()->putVariable(-1, x);
graph->getVariableSpace()->putVariable(-2, y);
graph->getVariableSpace()->putVariable(-3, z);
auto nodeA = new Node(OpType_BROADCAST, broadcast::Subtract, 1, {-1, -2}, {2}, {1});
auto nodeB = new Node(OpType_TRANSFORM_SAME, transform::Neg, 2, {1}, {-3});
graph->addNode(nodeA);
graph->addNode(nodeB);
GraphExecutioner::execute(graph);
ASSERT_NEAR(3.0, z->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
delete graph;
}
TEST_F(GraphTests, ScalarTest1) {
auto graph = new Graph();
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
auto z = NDArrayFactory::create_<float>('c', {5, 5});
graph->getVariableSpace()->putVariable(-1, x);
graph->getVariableSpace()->putVariable(-2, z);
auto nodeA = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2});
auto nodeB = new Node(OpType_TRANSFORM_FLOAT, transform::Sqrt, 2, {1}, {3});
auto nodeE = new Node(OpType_SCALAR, scalar::Add, 3, {2}, {-2}, {}, 1.3f);
graph->addNode(nodeA);
graph->addNode(nodeB);
graph->addNode(nodeE);
ASSERT_EQ(1, graph->rootNodes());
ASSERT_EQ(3, graph->totalNodes());
GraphExecutioner::execute(graph);
ASSERT_NEAR(2.714213, z->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
delete graph;
}
TEST_F(GraphTests, SymbolicLookupTest1) {
auto graph = new Graph();
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
auto z = NDArrayFactory::create_<float>('c', {5, 5});
auto vX = new Variable(x);
auto vZ = new Variable(z);
std::string a("alpha");
std::string o("omega");
vX->setName(&a);
vZ->setName(&o);
graph->getVariableSpace()->putVariable(-1, vX);
graph->getVariableSpace()->putVariable(-2, vZ);
auto nodeA = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2});
auto nodeB = new Node(OpType_TRANSFORM_FLOAT, transform::Sqrt, 2, {1}, {-2});
std::string p("phi");
std::string t("theta");
nodeA->setName(&p);
nodeB->setName(&t);
graph->addNode(nodeA);
graph->addNode(nodeB);
auto rX = graph->getVariableSpace()->getVariable(&a);
auto rZ = graph->getVariableSpace()->getVariable(&o);
std::string om("omicron");
ASSERT_TRUE(rX->getNDArray() == vX->getNDArray());
ASSERT_TRUE(rZ->getNDArray() == vZ->getNDArray());
ASSERT_FALSE(graph->getVariableSpace()->hasVariable(&om));
ASSERT_TRUE(graph->getVariableSpace()->hasVariable(1));
ASSERT_TRUE(graph->getVariableSpace()->hasVariable(2));
GraphExecutioner::execute(graph);
ASSERT_TRUE(graph->getVariableSpace()->hasVariable(&p));
ASSERT_TRUE(graph->getVariableSpace()->hasVariable(&t));
ASSERT_NEAR(1.4142135, z->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
delete graph;
}
TEST_F(GraphTests, OutputValidation1) {
auto graph = new Graph();
graph->getExecutorConfiguration()->_outputMode = OutputMode_EXPLICIT;
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
auto z = NDArrayFactory::create_<float>('c', {5, 5});
auto vX = new Variable(x);
auto vZ = new Variable(z);
std::string a("alpha");
std::string o("omega");
vX->setName(&a);
vZ->setName(&o);
graph->getVariableSpace()->putVariable(-1, vX);
graph->getVariableSpace()->putVariable(-2, vZ);
auto nodeA = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2});
auto nodeB = new Node(OpType_TRANSFORM_FLOAT, transform::Sqrt, 2, {1}, {-2});
graph->addNode(nodeA);
graph->addNode(nodeB);
auto outputs = graph->fetchOutputs();
ASSERT_EQ(0, outputs->size());
delete graph;
delete outputs;
}
TEST_F(GraphTests, OutputValidation2) {
auto graph = new Graph();
graph->getExecutorConfiguration()->_outputMode = OutputMode_EXPLICIT;
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
auto z = NDArrayFactory::create_<float>('c', {5, 5});
auto vX = new Variable(x);
auto vZ = new Variable(z);
std::string a("alpha");
std::string o("omega");
vX->setName(&a);
vZ->setName(&o);
graph->getVariableSpace()->putVariable(-1, vX);
graph->getVariableSpace()->putVariable(-2, vZ);
auto nodeA = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2});
auto nodeB = new Node(OpType_TRANSFORM_FLOAT, transform::Sqrt, 2, {1}, {-2});
graph->addNode(nodeA);
graph->addNode(nodeB);
graph->addOutput(-2);
GraphExecutioner::execute(graph);
auto outputs = graph->fetchOutputs();
ASSERT_EQ(1, outputs->size());
ASSERT_NEAR(1.4142135, outputs->at(0)->getNDArray()->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
delete graph;
delete outputs;
}
TEST_F(GraphTests, OutputValidation3) {
auto graph = new Graph();
graph->getExecutorConfiguration()->_outputMode = OutputMode_IMPLICIT;
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
auto z = NDArrayFactory::create_<float>('c', {5, 5});
auto vX = new Variable(x);
auto vZ = new Variable(z);
std::string a("alpha");
std::string o("omega");
vX->setName(&a);
vZ->setName(&o);
graph->getVariableSpace()->putVariable(-1, vX);
graph->getVariableSpace()->putVariable(-2, vZ);
auto nodeA = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2});
auto nodeB = new Node(OpType_TRANSFORM_FLOAT, transform::Sqrt, 2, {1}, {});
graph->addNode(nodeA);
graph->addNode(nodeB);
GraphExecutioner::execute(graph);
auto outputs = graph->fetchOutputs();
ASSERT_EQ(1, outputs->size());
ASSERT_NEAR(1.4142135, outputs->at(0)->getNDArray()->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
delete graph;
delete outputs;
}
TEST_F(GraphTests, OutputValidation4) {
auto graph = new Graph();
graph->getExecutorConfiguration()->_outputMode = OutputMode_EXPLICIT_AND_IMPLICIT;
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
auto z = NDArrayFactory::create_<float>('c', {5, 5});
auto vX = new Variable(x);
auto vZ = new Variable(z);
std::string a("alpha");
std::string o("omega");
vX->setName(&a);
vZ->setName(&o);
graph->getVariableSpace()->putVariable(-1, vX);
graph->getVariableSpace()->putVariable(-2, vZ);
auto nodeA = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2});
auto nodeB = new Node(OpType_TRANSFORM_FLOAT, transform::Sqrt, 2, {1}, {-2});
graph->addOutput(-1);
// not a typo. we want this value only once
graph->addOutput(-1);
graph->addNode(nodeA);
graph->addNode(nodeB);
GraphExecutioner::execute(graph);
auto outputs = graph->fetchOutputs();
ASSERT_EQ(2, outputs->size());
ASSERT_NEAR(1.4142135, outputs->at(1)->getNDArray()->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
delete graph;
delete outputs;
}
TEST_F(GraphTests, OutputValidation5) {
auto graph = new Graph();
graph->getExecutorConfiguration()->_outputMode = OutputMode_VARIABLE_SPACE;
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
auto z = NDArrayFactory::create_<float>('c', {5, 5});
auto vX = new Variable(x);
auto vZ = new Variable(z);
std::string a("alpha");
std::string o("omega");
vX->setName(&a);
vZ->setName(&o);
graph->getVariableSpace()->putVariable(-1, vX);
graph->getVariableSpace()->putVariable(-2, vZ);
auto nodeA = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2});
auto nodeB = new Node(OpType_TRANSFORM_SAME, transform::Sqrt, 2, {1}, {-2});
graph->addOutput(-1);
graph->addNode(nodeA);
graph->addNode(nodeB);
GraphExecutioner::execute(graph);
auto outputs = graph->fetchOutputs();
ASSERT_EQ(4, outputs->size());
delete graph;
delete outputs;
}
TEST_F(GraphTests, OutputValidation6) {
auto graph = new Graph();
graph->getExecutorConfiguration()->_outputMode = OutputMode_VARIABLE_SPACE;
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
auto z = NDArrayFactory::create_<float>('c', {5, 5});
auto vX = new Variable(x);
auto vZ = new Variable(z);
std::string a("alpha");
std::string o("omega");
vX->setName(&a);
vZ->setName(&o);
graph->getVariableSpace()->putVariable(-1, vX);
graph->getVariableSpace()->putVariable(-2, vZ);
auto nodeA = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2});
auto nodeB = new Node(OpType_TRANSFORM_FLOAT, transform::Sqrt, 2, {1}, {});
//graph->addOutput(-1);
graph->addNode(nodeA);
graph->addNode(nodeB);
GraphExecutioner::execute(graph);
auto outputs = graph->fetchOutputs();
// nd4j_printf("Returned variables: \n", "");
// for (int e = 0; e < outputs->size(); e++) {
// printf("%i, ", outputs->at(e)->id());
// }
// printf("\n");
ASSERT_EQ(4, outputs->size());
//ASSERT_NEAR(1.4142135, graph->fetchOutputs()->at(1)->getNDArray()->reduceNumber(reduce::Mean).e<float>(0), 1e-5);
delete graph;
delete outputs;
}
TEST_F(GraphTests, TestMultiOutput1) {
sd::ops::testop2i2o op1;
auto graph = new Graph();
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
auto y = NDArrayFactory::create_<float>('c', {5, 5});
y->assign(-3.0);
graph->getVariableSpace()->putVariable(-1, x);
graph->getVariableSpace()->putVariable(-2, y);
// Abs
auto nodeA0 = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {11});
nodeA0->markInplace(false);
auto nodeB0 = new Node(OpType_TRANSFORM_SAME, transform::Abs, 2, {-2}, {11});
nodeB0->markInplace(false);
auto op = sd::ops::OpRegistrator::getInstance().getOperation("testop2i2o");
// this op will add 1.0 to first input, and 2.0 for second input
auto nodeT = new Node(op, 11, {1, 2}, {21, 31}, {}, 0.0f);
nodeT->setName("TestOp2i2o");
nodeT->markInplace(false);
// this op will subtract this value from 1.0
auto nodeX = new Node(OpType_TRANSFORM_SAME, transform::OneMinus, 21);
nodeX->markInplace(false);
nodeX->pickInput(11, 0);
// this op will subtract this value from 1.0
auto nodeY = new Node(OpType_TRANSFORM_SAME, transform::OneMinus, 31);
nodeY->markInplace(false);
nodeY->pickInput(11, 1);
graph->addNode(nodeA0);
graph->addNode(nodeB0);
graph->addNode(nodeT);
graph->addNode(nodeX);
graph->addNode(nodeY);
std::pair<int, int> pair0(11,0);
std::pair<int, int> pair1(11,1);
ASSERT_TRUE(graph->getVariableSpace()->hasVariable(pair0));
ASSERT_TRUE(graph->getVariableSpace()->hasVariable(pair1));
Nd4jStatus status = GraphExecutioner::execute(graph);
ASSERT_EQ(ND4J_STATUS_OK, status);
ASSERT_NEAR(-2.0f, graph->getVariableSpace()->getVariable(21)->getNDArray()->meanNumber().e<float>(0), 1e-5);
ASSERT_NEAR(-4.0f, graph->getVariableSpace()->getVariable(31)->getNDArray()->meanNumber().e<float>(0), 1e-5);
delete graph;
}
TEST_F(GraphTests, TestDivergentNode1) {
auto op = sd::ops::OpRegistrator::getInstance().getOperation("Switch");
auto nodeY = new Node(op, 1);
ASSERT_TRUE(nodeY->isDivergencePoint());
ASSERT_TRUE(nodeY->isActive());
delete nodeY;
}
TEST_F(GraphTests, MemoryEstimationTest1) {
Graph graph;
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
graph.getVariableSpace()->putVariable(-1, x);
auto nodeA0 = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2});
auto nodeA1 = new Node(OpType_TRANSFORM_SAME, transform::Abs, 2, {1}, {});
nodeA1->markInplace(false);
graph.addNode(nodeA0);
graph.addNode(nodeA1);
ASSERT_EQ(2, graph.totalNodes());
ASSERT_EQ(1, graph.rootNodes());
auto memReq = graph.estimateRequiredMemory();
ASSERT_EQ(25 * x->sizeOfT(), memReq);
}
TEST_F(GraphTests, MemoryEstimationTest2) {
Graph graph;
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
graph.getVariableSpace()->putVariable(-1, x);
auto nodeA0 = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2});
auto nodeA1 = new Node(OpType_TRANSFORM_SAME, transform::Abs, 2, {1}, {});
//nodeA1->markInplace(false);
graph.addNode(nodeA0);
graph.addNode(nodeA1);
ASSERT_EQ(2, graph.totalNodes());
ASSERT_EQ(1, graph.rootNodes());
auto memReq = graph.estimateRequiredMemory();
ASSERT_EQ(0, memReq);
}
TEST_F(GraphTests, MemoryEstimationTest3) {
Graph graph;
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
graph.getVariableSpace()->putVariable(-1, x);
auto nodeA0 = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2});
auto nodeA1 = new Node(OpType_TRANSFORM_SAME, transform::Abs, 2, {1}, {3});
auto nodeA2 = new Node(OpType_REDUCE_FLOAT, reduce::Mean, 3, {2}, {}, {});
nodeA1->markInplace(false);
graph.addNode(nodeA0);
graph.addNode(nodeA1);
graph.addNode(nodeA2);
ASSERT_EQ(3, graph.totalNodes());
ASSERT_EQ(1, graph.rootNodes());
auto memReq = graph.estimateRequiredMemory();
ASSERT_EQ(26 * x->sizeOfT(), memReq);
}
TEST_F(GraphTests, MemoryEstimationTest4) {
Graph graph;
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
graph.getVariableSpace()->putVariable(-1, x);
auto nodeA0 = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2});
auto nodeA1 = new Node(OpType_TRANSFORM_SAME, transform::Abs, 2, {1}, {3});
auto nodeA2 = new Node(OpType_REDUCE_FLOAT, reduce::Mean, 3, {2}, {}, {1});
nodeA1->markInplace(false);
graph.addNode(nodeA0);
graph.addNode(nodeA1);
graph.addNode(nodeA2);
ASSERT_EQ(3, graph.totalNodes());
ASSERT_EQ(1, graph.rootNodes());
auto memReq = graph.estimateRequiredMemory();
ASSERT_EQ(30 * x->sizeOfT(), memReq);
}
TEST_F(GraphTests, MemoryEstimationTest5) {
Graph graph;
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-2.0);
graph.getVariableSpace()->putVariable(-1, x);
sd::ops::testcustom op;
auto nodeA0 = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2});
auto nodeA1 = new Node(OpType_TRANSFORM_SAME, transform::Abs, 2, {1}, {3});
auto nodeA2 = new Node(&op, 3, {2}, {}, {});
nodeA1->markInplace(false);
graph.addNode(nodeA0);
graph.addNode(nodeA1);
graph.addNode(nodeA2);
graph.buildGraph();
ASSERT_EQ(3, graph.totalNodes());
ASSERT_EQ(1, graph.rootNodes());
auto memReq = graph.estimateRequiredMemory();
ASSERT_EQ((25 + 100) * x->sizeOfT(), memReq);
}
TEST_F(GraphTests, TestGraphInGraph_1) {
// this one is external graph
Graph graphA;
// and this ons is embedded
Graph graphB;
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-5.0);
auto modifier = NDArrayFactory::create_<float>('c', {5, 5});
modifier->assign(3.0);
graphA.getVariableSpace()->putVariable(-1, x);
graphB.getVariableSpace()->putVariable(-2, modifier);
// this is placeholder variable
graphB.getVariableSpace()->putVariable(-1, new Variable(true));
// abs, result is 5
auto nodeA0 = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2});
// 1-, result -4
auto nodeA1 = new Node(OpType_TRANSFORM_SAME, transform::OneMinus, 2, {1}, {3});
// graph should return 12: abs(3.0 x -4)
auto nodeA2 = new Node(OpType_GRAPH, -1, 3, {2}, {4});
// 1 - 12 = -11
auto nodeA3 = new Node(OpType_TRANSFORM_SAME, transform::OneMinus, 4, {3}, {});
nodeA2->setGraph(&graphB);
graphA.addNode(nodeA0);
graphA.addNode(nodeA1);
graphA.addNode(nodeA2);
graphA.addNode(nodeA3);
// this is going to be PWT
auto nodeB0 = new Node(OpType_PAIRWISE, pairwise::Multiply, 1, {-1, -2}, {2});
auto nodeB1 = new Node(OpType_TRANSFORM_SAME, transform::Abs, 2, {1}, {});
graphB.addNode(nodeB0);
graphB.addNode(nodeB1);
graphB.buildGraph();
graphA.buildGraph();
ASSERT_EQ(0, nodeA0->getLayer());
ASSERT_EQ(1, nodeA1->getLayer());
ASSERT_EQ(2, nodeA2->getLayer());
ASSERT_EQ(3, nodeA3->getLayer());
ASSERT_EQ(0, nodeB0->getLayer());
ASSERT_EQ(1, nodeB1->getLayer());
Nd4jStatus status = GraphExecutioner::execute(&graphA);
ASSERT_EQ(ND4J_STATUS_OK, status);
float m = graphA.getVariableSpace()->getVariable(4)->getNDArray()->meanNumber().e<float>(0);
//nd4j_printf("OpResult: %f\n", m);
ASSERT_NEAR(-11.0, m, 1e-5);
}
// test for symbolic lookup
TEST_F(GraphTests, TestGraphInGraph_2) {
// this one is external graph
Graph graphA;
// and this ons is embedded
Graph graphB;
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-5.0);
auto modifier = NDArrayFactory::create_<float>('c', {5, 5});
modifier->assign(3.0);
std::string nameA1("_nodeA1");
graphA.getVariableSpace()->putVariable(-1, x);
graphB.getVariableSpace()->putVariable(-2, modifier);
// this is placeholder variable
auto placeHolder = new Variable(true);
placeHolder->setName(&nameA1);
graphB.getVariableSpace()->putVariable(-1, placeHolder);
// abs, result is 5
auto nodeA0 = new Node(OpType_TRANSFORM_SAME, transform::Abs, 1, {-1}, {2});
// 1-, result -4
auto nodeA1 = new Node(OpType_TRANSFORM_SAME, transform::OneMinus, 2, {1}, {3});
nodeA1->setName(nameA1);
// graph should return 12: abs(3.0 x -4)
auto nodeA2 = new Node(OpType_GRAPH, -1, 3, {2}, {4});
// 1 - 12 = -11
auto nodeA3 = new Node(OpType_TRANSFORM_SAME, transform::OneMinus, 4, {3}, {});
nodeA2->setGraph(&graphB);
graphA.addNode(nodeA0);
graphA.addNode(nodeA1);
graphA.addNode(nodeA2);
graphA.addNode(nodeA3);
// this is going to be PWT
auto nodeB0 = new Node(OpType_PAIRWISE, pairwise::Multiply, 1, {-1, -2}, {2});
auto nodeB1 = new Node(OpType_TRANSFORM_SAME, transform::Abs, 2, {1}, {});
graphB.addNode(nodeB0);
graphB.addNode(nodeB1);
graphB.buildGraph();
graphA.buildGraph();
ASSERT_EQ(0, nodeA0->getLayer());
ASSERT_EQ(1, nodeA1->getLayer());
ASSERT_EQ(2, nodeA2->getLayer());
ASSERT_EQ(3, nodeA3->getLayer());
ASSERT_EQ(0, nodeB0->getLayer());
ASSERT_EQ(1, nodeB1->getLayer());
Nd4jStatus status = GraphExecutioner::execute(&graphA);
ASSERT_EQ(ND4J_STATUS_OK, status);
float m = graphA.getVariableSpace()->getVariable(4)->getNDArray()->meanNumber().e<float>(0);
//nd4j_printf("OpResult: %f\n", m);
ASSERT_NEAR(-11.0, m, 1e-5);
}
#if 0
TEST_F(GraphTests, Test_Clone_1) {
auto exp = NDArrayFactory::create<float>('c', {3});
exp.assign(3.0);
auto graph = GraphExecutioner::importFromFlatBuffers("./resources/reduce_dim_false.fb");
auto variableSpace = graph->getVariableSpace();
//graph->buildGraph();
auto clone = graph->clone();
Nd4jStatus statusOriginal = GraphExecutioner::execute(graph);
ASSERT_EQ(ND4J_STATUS_OK, statusOriginal);
ASSERT_TRUE(variableSpace->hasVariable(3));
Nd4jStatus statusClone = GraphExecutioner::execute(clone);
ASSERT_EQ(ND4J_STATUS_OK, statusClone);
ASSERT_TRUE(variableSpace->hasVariable(3));
auto z0 = variableSpace->getVariable(3)->getNDArray();
auto z1 = clone->getVariableSpace()->getVariable(3)->getNDArray();
ASSERT_TRUE(exp.isSameShape(z0));
ASSERT_TRUE(exp.equalsTo(z0));
ASSERT_TRUE(exp.isSameShape(z1));
ASSERT_TRUE(exp.equalsTo(z1));
delete graph;
delete clone;
}
TEST_F(GraphTests, Test_Clone_2) {
auto exp = NDArrayFactory::create<float>('c', {3});
exp.assign(3.0);
auto graph = GraphExecutioner::importFromFlatBuffers("./resources/reduce_dim_false.fb");
auto variableSpace = graph->getVariableSpace();
graph->buildGraph();
auto clone = graph->clone();
Nd4jStatus statusOriginal = GraphExecutioner::execute(graph);
ASSERT_EQ(ND4J_STATUS_OK, statusOriginal);
ASSERT_TRUE(variableSpace->hasVariable(3));
Nd4jStatus statusClone = GraphExecutioner::execute(clone);
ASSERT_EQ(ND4J_STATUS_OK, statusClone);
ASSERT_TRUE(variableSpace->hasVariable(3));
auto z0 = variableSpace->getVariable(3)->getNDArray();
auto z1 = clone->getVariableSpace()->getVariable(3)->getNDArray();
ASSERT_TRUE(exp.isSameShape(z0));
ASSERT_TRUE(exp.equalsTo(z0));
ASSERT_TRUE(exp.isSameShape(z1));
ASSERT_TRUE(exp.equalsTo(z1));
delete graph;
delete clone;
}
TEST_F(GraphTests, Test_Dtype_Conversion_1) {
/*auto expD = NDArrayFactory::create<double>('c', {3}, {3.0, 3.0, 3.0});
auto expF = NDArrayFactory::create<float>('c', {3}, {3.0, 3.0, 3.0});
auto graph = GraphExecutioner::importFromFlatBuffers("./resources/reduce_dim_false.fb");
graph->buildGraph();
auto gd = graph->template asT<double>();
auto gf = gd->template asT<float>();
// checking float graph
Nd4jStatus statusF = GraphExecutioner::execute(gf);
ASSERT_EQ(ND4J_STATUS_OK, statusF);
ASSERT_TRUE(gf->getVariableSpace()->hasVariable(3));
ASSERT_TRUE(gf->getVariableSpace()->hasVariable(3));
auto z1 = gf->getVariableSpace()->getVariable(3)->getNDArray();
ASSERT_TRUE(expF.isSameShape(z1));
ASSERT_TRUE(expF.equalsTo(z1));
// checking double graph
Nd4jStatus statusD = GraphExecutioner<double>::execute(gd);
ASSERT_EQ(ND4J_STATUS_OK, statusD);
ASSERT_TRUE(gd->getVariableSpace()->hasVariable(3));
auto z2 = gd->getVariableSpace()->getVariable(3)->getNDArray();
ASSERT_TRUE(expD.isSameShape(z2));
ASSERT_TRUE(expD.equalsTo(z2));
delete graph;
delete gd;
delete gf;
*/
}
TEST_F(GraphTests, Test_Dtype_Conversion_2) {
/*
NDArray<float> expF('c', {5, 4}, {0.32454616f, -0.06604697f, 0.22593613f, 0.43166467f, -0.18320604f, 0.00102305f, -0.06963076f, 0.25266643f, 0.07568010f, -0.03009197f, 0.07805517f, 0.33180334f, -0.06220427f, 0.07249600f, -0.06726961f, -0.22998397f, -0.06343779f, 0.07384885f, -0.06891008f, -0.23745790f});
NDArray<double> expD('c', {5, 4}, {0.32454616f, -0.06604697f, 0.22593613f, 0.43166467f, -0.18320604f, 0.00102305f, -0.06963076f, 0.25266643f, 0.07568010f, -0.03009197f, 0.07805517f, 0.33180334f, -0.06220427f, 0.07249600f, -0.06726961f, -0.22998397f, -0.06343779f, 0.07384885f, -0.06891008f, -0.23745790f});
auto graph = GraphExecutioner::importFromFlatBuffers("./resources/ae_00.fb");
graph->buildGraph();
auto gd = graph->template asT<double>();
auto gf = gd->template asT<float>();
// checking float
auto resultF = GraphExecutioner::execute(gf);
ASSERT_EQ(ND4J_STATUS_OK, resultF);
ASSERT_TRUE(gf->getVariableSpace()->hasVariable(18));
auto zF = gf->getVariableSpace()->getVariable(18)->getNDArray();
ASSERT_TRUE(expF.isSameShape(zF));
ASSERT_TRUE(expF.equalsTo(zF));
// checking double
auto resultD = GraphExecutioner<double>::execute(gd);
ASSERT_EQ(ND4J_STATUS_OK, resultD);
ASSERT_TRUE(gd->getVariableSpace()->hasVariable(18));
auto zD = gd->getVariableSpace()->getVariable(18)->getNDArray();
ASSERT_TRUE(expD.isSameShape(zD));
ASSERT_TRUE(expD.equalsTo(zD));
delete graph;
delete gd;
delete gf;
*/
}
TEST_F(GraphTests, Test_Hash_Function_1) {
/*
auto graph0 = GraphExecutioner::importFromFlatBuffers("./resources/ae_00.fb");
auto graph1 = GraphExecutioner::importFromFlatBuffers("./resources/ae_00.fb");
auto graph2 = GraphExecutioner::importFromFlatBuffers("./resources/conv_0.fb");
ASSERT_EQ(graph0->hashCode(), graph1->hashCode());
ASSERT_NE(0L, graph1->hashCode());
ASSERT_NE(graph0->hashCode(), graph2->hashCode());
auto graph0D = graph0->template asT<double>();
auto graph1D = graph1->template asT<double>();
ASSERT_NE(graph0->hashCode(), graph0D->hashCode());
ASSERT_EQ(graph0D->hashCode(), graph1D->hashCode());
delete graph0;
delete graph1;
delete graph2;
delete graph0D;
delete graph1D;
*/
}
TEST_F(GraphTests, OpListTest_1) {
auto graph = GraphExecutioner::importFromFlatBuffers("./resources/ae_00.fb"); ;
ASSERT_TRUE(graph != nullptr);
std::vector<OpDescriptor> ops = graph->getOperations();
ASSERT_TRUE(ops.size() == 11);
GraphUtils::filterOperations(ops);
ASSERT_TRUE(ops.size() == 7);
std::string exp(" -g \"-DSD_OPS_LIST='-DOP_rank=true -DOP_range=true -DOP_subtract=true -DOP_permute=true -DOP_matmul=true -DOP_biasadd=true -DOP_TRANSFORM{15}=true '\"");
std::string out = GraphUtils::makeCommandLine(ops);
// nd4j_printf("EXP: >%s<\n", exp.c_str());
// nd4j_printf("OUT: >%s<\n", out.c_str());
ASSERT_EQ(exp, out);
delete graph;
}
////////////////////////////////////////////////////////////////////////////////
TEST_F(GraphTests, OpListTest_2) {
auto graph0 = GraphExecutioner::importFromFlatBuffers("./resources/ae_00.fb");
auto graph1 = GraphExecutioner::importFromFlatBuffers("./resources/tensor_slice.fb");
ASSERT_TRUE(graph0 != nullptr);
ASSERT_TRUE(graph1 != nullptr);
std::vector<OpDescriptor> ops = graph0->getOperations();
std::vector<OpDescriptor> ops1 = graph1->getOperations();
std::copy ( ops1.begin(), ops1.end(), std::back_inserter(ops));
ASSERT_TRUE(ops.size() == 13);
GraphUtils::filterOperations(ops);
std::string exp = " -g \"-DSD_OPS_LIST='-DOP_rank=true -DOP_range=true -DOP_subtract=true -DOP_permute=true -DOP_matmul=true -DOP_biasadd=true -DOP_TRANSFORM{15}=true -DOP_strided_slice=true -DOP_ACCUMULATION{1}=true '\"";
ASSERT_TRUE(ops.size() == 9);
ASSERT_EQ(exp, GraphUtils::makeCommandLine(ops));
delete graph0;
delete graph1;
}
////////////////////////////////////////////////////////////////////////////////
TEST_F(GraphTests, OpListTest_3) {
auto graph = GraphExecutioner::importFromFlatBuffers("./resources/ae_00.fb"); ;
ASSERT_TRUE(graph != nullptr);
std::vector<OpDescriptor> ops = graph->getOperations();
std::vector<OpDescriptor> ops2(ops);
std::copy(ops.begin(), ops.end(), std::back_inserter(ops2));
ASSERT_TRUE(ops.size() == 11);
ASSERT_TRUE(ops2.size() == 2 * ops.size());
GraphUtils::filterOperations(ops2);
GraphUtils::filterOperations(ops);
ASSERT_TRUE(ops.size() == ops2.size());
ASSERT_TRUE(ops.size() == 7);
ASSERT_TRUE(GraphUtils::makeCommandLine(ops) == GraphUtils::makeCommandLine(ops2));
delete graph;
}
////////////////////////////////////////////////////////////////////////////////
TEST_F(GraphTests, OpListTest_4) {
auto graph = GraphExecutioner::importFromFlatBuffers("./resources/conv_0.fb"); ;
ASSERT_TRUE(graph != nullptr);
std::vector<OpDescriptor> ops = graph->getOperations();
std::vector<OpDescriptor> ops2(ops);
std::copy(ops.begin(), ops.end(), std::back_inserter(ops2));
// nd4j_printf("Total ops before %i\n", ops.size());
ASSERT_TRUE(ops.size() == 6);
ASSERT_TRUE(ops2.size() == 2 * ops.size());
GraphUtils::filterOperations(ops2);
GraphUtils::filterOperations(ops);
ASSERT_TRUE(ops.size() == ops2.size());
ASSERT_TRUE(ops.size() == 5);
ASSERT_TRUE(GraphUtils::makeCommandLine(ops) == GraphUtils::makeCommandLine(ops2));
delete graph;
}
TEST_F(GraphTests, Test_Inplace_Execution_1) {
auto exp = NDArrayFactory::create<float>('c', {5, 4}, {0.32454616f, -0.06604697f, 0.22593613f, 0.43166467f, -0.18320604f, 0.00102305f, -0.06963076f, 0.25266643f, 0.07568010f, -0.03009197f, 0.07805517f, 0.33180334f, -0.06220427f, 0.07249600f, -0.06726961f, -0.22998397f, -0.06343779f, 0.07384885f, -0.06891008f, -0.23745790f});
auto graph = GraphExecutioner::importFromFlatBuffers("./resources/ae_00.fb");
// graph->printOut();
graph->tagInplaceNodes();
ASSERT_FALSE(graph->nodeById(8)->isInplace());
ASSERT_TRUE(graph->nodeById(9)->isInplace());
ASSERT_TRUE(graph->nodeById(10)->isInplace());
ASSERT_FALSE(graph->nodeById(11)->isInplace());
ASSERT_FALSE(graph->nodeById(12)->isInplace());
ASSERT_TRUE(graph->nodeById(17)->isInplace());
ASSERT_TRUE(graph->nodeById(18)->isInplace());
auto status = GraphExecutioner::execute(graph, graph->getVariableSpace());
ASSERT_EQ(Status::OK(), status);
auto z = graph->getVariableSpace()->getVariable(18)->getNDArray();
ASSERT_TRUE(exp.isSameShape(z));
ASSERT_TRUE(exp.equalsTo(z));
auto z_17 = graph->getVariableSpace()->getVariable(17)->getNDArray();
ASSERT_TRUE(z_17 == z);
delete graph;
}
TEST_F(GraphTests, Test_Inplace_Execution_2) {
Graph graphA;
auto x = NDArrayFactory::create_<float>('c', {5, 5});
x->assign(-5.0);
graphA.getVariableSpace()->putVariable(-1, x);
// abs, result is 5
auto nodeA0 = new Node(OpType_TRANSFORM_SAME, 0, 1, {-1}, {});
// 1-, result -4
auto nodeA1 = new Node(OpType_TRANSFORM_SAME, 35, 2, {1}, {});
// graph should return 4: abs(-4)
auto nodeA2 = new Node(OpType_TRANSFORM_SAME, 0, 3, {2}, {});
// graph should return 1 - 4 = -3
auto nodeA21 = new Node(OpType_TRANSFORM_SAME, 35, 5, {3}, {});
// 1 - -4 = 3
auto nodeA3 = new Node(OpType_TRANSFORM_SAME, 35, 4, {2}, {});
// same abs = 3
auto nodeA31 = new Node(OpType_TRANSFORM_SAME, 35, 6, {4}, {});
graphA.addNode(nodeA0);
graphA.addNode(nodeA1);
graphA.addNode(nodeA2);
graphA.addNode(nodeA3);
graphA.addNode(nodeA21);
graphA.addNode(nodeA31);
graphA.buildGraph();
graphA.tagInplaceNodes();
// nodes have 1 output
ASSERT_TRUE(graphA.nodeById(1)->isInplace());
ASSERT_TRUE(graphA.nodeById(2)->isInplace());
// this 2 nodes share same input: node 2, so they can't be inplace
ASSERT_FALSE(graphA.nodeById(3)->isInplace());
ASSERT_FALSE(graphA.nodeById(4)->isInplace());
// these 2 ops are standalone, so they can be run inplace
ASSERT_TRUE(graphA.nodeById(5)->isInplace());
ASSERT_TRUE(graphA.nodeById(6)->isInplace());
}
#endif
TEST_F(GraphTests, Test_Inplace_Outputs_1) {
auto x = NDArrayFactory::create<float>('c', {2, 3}, {1.f, 2.f, 3.f, 4.f, 5.f, 6.f});
auto exp = NDArrayFactory::create<float>('c', {6}, {1.f, 2.f, 3.f, 4.f, 5.f, 6.f});
auto z = NDArrayFactory::create<float>('c', {2, 3});
sd::ops::test_output_reshape op;
auto result = op.execute({&x}, {&z}, {}, {}, {});
ASSERT_EQ(Status::OK(), result);
ASSERT_TRUE(exp.isSameShape(z));
ASSERT_TRUE(exp.equalsTo(z));
}
TEST_F(GraphTests, Test_Inplace_Outputs_2) {
#ifndef __APPLE_OS__
// we dont want testing this on apple. due to try/catch
auto x = NDArrayFactory::create<float>('c', {2, 3}, {1.f, 2.f, 3.f, 4.f, 5.f, 6.f});
auto exp = NDArrayFactory::create<float>('c', {6}, {1.f, 2.f, 3.f, 4.f, 5.f, 6.f});
auto z = NDArrayFactory::create<float>('c', {3, 3});
bool failed = false;
sd::ops::test_output_reshape op;
try {
op.execute({&x}, {&z}, {}, {}, {});
} catch (const std::runtime_error& e) {
failed = true;
}
ASSERT_TRUE(failed);
#endif
}
/*
TEST_F(GraphTests, Test_Minifier_1) {
// run preprocessor to produce single header
// if all ok - return value is 0, if error - non-zero value will be returned
std::string input("../include/ops/ops.h"); //declarable/CustomOperations.h");
ASSERT_EQ(0, GraphUtils::runPreprocessor(input.c_str(), "libnd4j_mini.hpp"));
// remove file from filesystem
#ifdef __linux__
ASSERT_EQ(0, unlink("libnd4j_mini.hpp"));
#endif
}
*/
TEST_F(GraphTests, Test_Minifier_2) {
// run preprocessor to produce single header
// if all ok - return value is 0, if error - non-zero value will be returned
ASSERT_EQ(0, GraphUtils::runPreprocessor("../include/ops/specials.h", "libnd4j_mini2.hpp"));
// remove file from filesystem
#ifdef __linux__
ASSERT_EQ(0, unlink("libnd4j_mini2.hpp"));
#endif
}
TEST_F(GraphTests, Test_Minifier_3) {
// run preprocessor to produce single header
// if all ok - return value is 0, if error - non-zero value will be returned
#ifdef __linux__
ASSERT_EQ(0x100, GraphUtils::runPreprocessor("/include/ops/ops.h", "libnd4j_mini3.hpp"));
#endif
// remove file from filesystem
//ASSERT_EQ(0, unlink("libnd4j_mini3.hpp"));
}