提交 90d5be74 编写于 作者: T tensor-tang

add mkldnn fc forward

上级 94b172a7
......@@ -13,6 +13,7 @@ See the License for the specific language governing permissions and
limitations under the License. */
#include "MkldnnFcLayer.h"
#include "paddle/utils/Stat.h"
namespace paddle {
......@@ -20,11 +21,82 @@ REGISTER_LAYER(mkldnn_fc, MkldnnFcLayer);
bool MkldnnFcLayer::init(const LayerMap& layerMap,
const ParameterMap& parameterMap) {
return MkldnnLayer::init(layerMap, parameterMap);
if (!MkldnnLayer::init(layerMap, parameterMap)) {
return false;
}
CHECK_EQ(inputLayers_.size(), 1) << "Only support one input layer yet!";
CHECK_EQ(inputLayers_.size(), parameters_.size());
CHECK(!parameters_[0]->isSparse()) << "Do not support sparse yet";
// output size, cat not be changed
oc_ = getSize();
oh_ = 1;
ow_ = 1;
// input size can not change in FC
iLayerSize_ = inputLayers_[0]->getSize();
CHECK_EQ(parameters_[0]->getSize(), iLayerSize_ * oc_);
// create weight
weight_ =
std::unique_ptr<Weight>(new Weight(oc_, iLayerSize_, parameters_[0], 0));
// create biases
if (biasParameter_.get() != NULL) {
biases_ = std::unique_ptr<Weight>(new Weight(1, oc_, biasParameter_));
}
return true;
}
void MkldnnFcLayer::reshape() {
const Argument& input = getInput(0);
int batchSize = input.getBatchSize();
if (bs_ == batchSize) {
return;
}
bs_ = batchSize;
ih_ = input.getFrameHeight();
iw_ = input.getFrameWidth();
if (ih_ == 0) {
ih_ = 1;
}
if (iw_ == 0) {
iw_ = 1;
}
CHECK_EQ(iLayerSize_, inputLayers_[0]->getSize());
ic_ = iLayerSize_ / (ih_ * iw_);
CHECK_EQ(size_t(ic_ * ih_ * iw_), iLayerSize_) << "not divisible";
CHECK_EQ(size_t(oc_), getSize());
// reset output
output_.setFrameHeight(oh_);
output_.setFrameWidth(ow_);
resetOutput(bs_, oc_);
}
void MkldnnFcLayer::forward(PassType passType) {}
void MkldnnFcLayer::forward(PassType passType) {
Layer::forward(passType);
reshape();
void MkldnnFcLayer::backward(const UpdateCallback& callback) {}
{
REGISTER_TIMER_INFO("mkldnn_FwdTimer", getName().c_str());
real* input = getInputValue(0)->getData();
real* output = getOutputValue()->getData();
real* wgt = weight_->getW()->getData();
bool hasBias = biases_ && biases_->getW();
real* bias = hasBias ? biases_->getW()->getData() : NULL;
mkldnnForwardFC(bs_, ic_, ih_, iw_, input, oc_, output, wgt, bias);
}
/* activation */ {
REGISTER_TIMER_INFO("FwActTimer", getName().c_str());
forwardActivation();
}
}
void MkldnnFcLayer::backward(const UpdateCallback& callback) {
; // bool hasBias = biases_ && biases_->getWGrad();
}
} // namespace paddle
......@@ -26,6 +26,13 @@ namespace paddle {
*/
class MkldnnFcLayer : public MkldnnLayer {
protected:
// input layer size, can not be change after init
size_t iLayerSize_; // == ic * ih * iw
// fc weight and bias
std::unique_ptr<Weight> weight_;
std::unique_ptr<Weight> biases_;
public:
explicit MkldnnFcLayer(const LayerConfig& config) : MkldnnLayer(config) {}
......@@ -34,6 +41,8 @@ public:
bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) override;
void reshape();
void forward(PassType passType) override;
void backward(const UpdateCallback& callback) override;
......
/* Copyright (c) 2017 PaddlePaddle Authors. All Rights Reserve.
Licensed 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 "MkldnnLayer.h"
// using namespace mkldnn; // NOLINT
using mem = mkldnn::memory; // NOLINT
typedef mem::format format;
typedef mkldnn::inner_product_forward fc_fwd;
typedef mkldnn::inner_product_backward_weights fc_bwdWgt;
typedef mkldnn::inner_product_backward_data fc_bwdData;
namespace paddle {
bool MkldnnLayer::init(const LayerMap& layerMap,
const ParameterMap& parameterMap) {
CHECK(FLAGS_use_mkldnn) << "MkldnnLayers only support use_mkldnn."
<< "Please set WITH_MKLDNN=ON";
// TODO(TJ): deivecId
return Layer::init(layerMap, parameterMap);
}
void MkldnnLayer::resetForwardFC(int bs,
int ic,
int ih,
int iw,
real* botData,
int oc,
real* topData,
real* wgtData,
real* biasData) {
bool hasSpatial = ih == 1 && iw == 1 ? false : true;
engine_ = CpuEngine::Instance().getEngine();
mem::desc botMD = hasSpatial ? createMD({bs, ic, ih, iw}, format::nchw)
: createMD({bs, ic}, format::nc);
mem::desc wgtMD = hasSpatial ? createMD({oc, ic, ih, iw}, format::oihw)
: createMD({oc, ic}, format::oi);
mem::desc biasMD = biasData != NULL ? createMD({oc}, format::x)
: createMD({}, format::format_undef);
mem::desc topMD = createMD({bs, oc}, format::nc);
mkldnn::prop_kind pk = mkldnn::prop_kind::forward;
fc_fwd::desc fwdDesc = biasData != NULL
? fc_fwd::desc(pk, botMD, wgtMD, biasMD, topMD)
: fc_fwd::desc(pk, botMD, wgtMD, topMD);
fc_fwd::primitive_desc fwdPD = fc_fwd::primitive_desc(fwdDesc, engine_);
mem bot = mem(mem::primitive_desc(botMD, engine_), botData);
mem wgt = mem(mem::primitive_desc(wgtMD, engine_), wgtData);
mem top = mem(mem::primitive_desc(topMD, engine_), topData);
if (biasData != NULL) {
mem bias = mem(mem::primitive_desc(biasMD, engine_), biasData);
fwd_.reset(new fc_fwd(fwdPD, bot, wgt, bias, top));
} else {
fwd_.reset(new fc_fwd(fwdPD, bot, wgt, top));
}
pipelineFwd_.clear();
pipelineFwd_.push_back(*fwd_);
}
void MkldnnLayer::mkldnnForwardFC(int bs,
int ic,
int ih,
int iw,
real* botData,
int oc,
real* topData,
real* wgtData,
real* biasData) {
// if input size changed, reset it
resetForwardFC(bs, ic, ih, iw, botData, oc, topData, wgtData, biasData);
// just forward
// update botdata
stream_->submit(pipelineFwd_);
}
mem::desc MkldnnLayer::createMD(mem::dims dims,
mem::format fmt,
mem::data_type type) {
// TODO(TJ): isFmtSuppoted(fmt)
return mem::desc(dims, type, fmt);
}
} // namespace paddle
......@@ -29,20 +29,65 @@ typedef std::shared_ptr<MkldnnLayer> MkldnnLayerPtr;
*
*/
class MkldnnLayer : public Layer {
protected:
// batch size
int bs_;
// input image channel, height and width
int ic_, ih_, iw_;
// output image channel, height and width
int oc_, oh_, ow_;
// mkldnn engine, stream and primivtives
mkldnn::engine engine_;
std::shared_ptr<MkldnnStream> stream_;
std::shared_ptr<mkldnn::primitive> fwd_;
std::vector<mkldnn::primitive> pipelineFwd_;
std::vector<mkldnn::primitive> pipelineBwd_;
public:
explicit MkldnnLayer(const LayerConfig& config) : Layer(config) {}
explicit MkldnnLayer(const LayerConfig& config)
: Layer(config),
bs_(0),
ic_(0),
ih_(0),
iw_(0),
oc_(0),
oh_(0),
ow_(0),
engine_(mkldnn::engine::cpu, 0),
stream_(nullptr) {}
~MkldnnLayer() {}
virtual bool init(const LayerMap& layerMap,
const ParameterMap& parameterMap) {
CHECK(FLAGS_use_mkldnn) << "MkldnnLayers only support use_mkldnn."
<< "Please set WITH_MKLDNN=ON";
// TODO(TJ): deivecId
return Layer::init(layerMap, parameterMap);
}
virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap);
void resetForwardFC(int bs,
int ic,
int ih,
int iw,
real* botData,
int oc,
real* topData,
real* wgtData,
real* biasData);
void mkldnnForwardFC(int bs,
int ic,
int ih,
int iw,
real* botData,
int oc,
real* topData,
real* wgtData,
real* biasData);
void resetOutput(size_t height, size_t width) { ; }
// TODO(TJ): move to MkldnnMatrix
// create memory desc
inline mkldnn::memory::desc createMD(
mkldnn::memory::dims dims,
mkldnn::memory::format fmt,
mkldnn::memory::data_type type = mkldnn::memory::data_type::f32);
};
} // namespace paddle
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册