blob: 481d9913b4c088537a9fab180bd4061ab7d004ae [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.
*
*************************************************************/
#ifndef SINGA_NEURALNET_CONNECTION_LAYER_H_
#define SINGA_NEURALNET_CONNECTION_LAYER_H_
#include <string>
#include <unordered_map>
#include <vector>
#include "singa/comm/socket.h"
#include "singa/neuralnet/layer.h"
namespace singa {
/**
* Used inside SplitLayer and SliceLayer to locate the out-going connection
* index given the Layer pointer.
*/
class Layer2Index {
public:
int Get(const Layer* layer) {
if (layer2idx_.find(layer) == layer2idx_.end()) {
int idx = layer2idx_.size();
layer2idx_[layer] = idx;
}
return layer2idx_[layer];
}
private:
std::unordered_map<const Layer*, int> layer2idx_;
};
class BridgeLayer : public ConnectionLayer {
public:
void set_ready(bool a) { ready_ = a; }
bool ready() const { return ready_; }
// Bind the layer with dealer instance by worker at runtime
void MakePaired(Layer* pair, int grp_id, Dealer* dealer,
std::unordered_map<std::string, Layer*>* name2bridge);
// Send blobs to other workers due to model partitions
void SendBlobs(bool handle_data);
// Receive blobs from other workers due to model partitions;
void ReceiveBlobs(bool handle_data);
protected:
//!< true if received grad from BridgeDstLayer
bool ready_ = false;
int group_id_ = 0;
Layer* pair_ = nullptr;
Dealer* dealer_ = nullptr;
std::unordered_map<std::string, Layer*>* name2bridge_ = nullptr;
};
/**
* For sending data to layer on other threads which may resident on other nodes
* due to layer/data partition.
*/
class BridgeSrcLayer : public BridgeLayer {
public:
void Setup(const LayerProto& conf, const vector<Layer*>& srclayers) override;
void ComputeFeature(int flag, const vector<Layer*>& srclayers) override;
void ComputeGradient(int flag, const vector<Layer*>& srclayers) override;
};
/**
* For recv data from layer on other threads which may resident on other nodes
* due to layer/data partiton
*/
class BridgeDstLayer : public BridgeLayer {
public:
void Setup(const LayerProto& conf, const vector<Layer*>& srclayers) override;
void ComputeFeature(int flag, const vector<Layer*>& srclayers) override;
void ComputeGradient(int flag, const vector<Layer*>& srclayers) override;
};
/**
* Connect multiple (src) layers with a single (dst) layer.
*
* It concates feature Blobs (i.e., matrix) of src layers on one dimension.
* The concated feature Blob will be fed into the dst layer.
*/
class ConcateLayer : public ConnectionLayer {
public:
void Setup(const LayerProto& proto, const vector<Layer*>& srclayers) override;
void ComputeFeature(int flag, const vector<Layer*>& srclayers) override;
void ComputeGradient(int flag, const vector<Layer*>& srclayers) override;
private:
int num_concates_ = 0;
int concate_dim_ = 0;
};
/**
* Connect a single (src) layer with multiple (dst) layers.
*
* It slices the feature Blob (i.e., matrix) of the src layer on one dimension.
* The sliced feature Blobs will be fed into dst layers.
*/
class SliceLayer : public ConnectionLayer {
public:
~SliceLayer();
void Setup(const LayerProto& proto, const vector<Layer*>& srclayers) override;
void ComputeFeature(int flag, const vector<Layer*>& srclayers) override;
void ComputeGradient(int flag, const vector<Layer*>& srclayers) override;
const std::string ToString(bool debug, int flag) override;
const Blob<float>& data(const Layer* from) override;
const Blob<float>& grad(const Layer* from) override;
Blob<float>* mutable_data(const Layer* from) override;
Blob<float>* mutable_grad(const Layer* from) override;
private:
int num_slices_ = 0;
int slice_dim_ = 0;
Layer2Index layer_idx_;
};
/**
* Connect a single (src) layer with multiple dst layers.
*
* It replicates the feature Blob of the src layer.
* Each replicated feature Blob will be fed into one dst layer.
* It aggregates gradients set by all dst layers and set it to the src layer.
*/
class SplitLayer : public ConnectionLayer {
public:
~SplitLayer();
void Setup(const LayerProto& proto, const vector<Layer*>& srclayers) override;
void ComputeFeature(int flag, const vector<Layer*>& srclayers) override;
void ComputeGradient(int flag, const vector<Layer*>& srclayers) override;
const std::string ToString(bool debug, int flag) override;
const Blob<float>& grad(const Layer* from) override;
Blob<float>* mutable_grad(const Layer* from) override;
private:
int num_splits_ = 0;
Layer2Index layer_idx_;
};
/**
* Dummy layer for RNN models, which provides input for other layers.
*
* Particularly, it is used in the test phase of RNN models to connect other
* layers and avoid cycles in the neural net config.
*/
class RNNDummyLayer : public ConnectionLayer {
public:
void Setup(const LayerProto& proto, const vector<Layer*>& srclayers) override;
void ComputeFeature(int flag, const vector<Layer*>& srclayers) override;
void ComputeGradient(int flag, const vector<Layer*>& srclayers) {
LOG(FATAL) << "Not implemented";
}
const string srclayer(int step) const {
if (step > 0)
return dynamic_src_;
else
return "";
}
private:
string dynamic_src_;
float low_, high_;
bool integer_;
Layer* srclayer_;
};
} // namespace singa
#endif // SINGA_NEURALNET_CONNECTION_LAYER_H_