@@ -82,6 +82,100 @@ inline static mkldnn::inner_product_backward_weights::primitive_desc GetIPBwdWei
8282 }
8383}
8484
85+ class MKLDNNFullyConnectForward {
86+ std::shared_ptr<mkldnn::memory> data;
87+ std::shared_ptr<mkldnn::memory> weight;
88+ std::shared_ptr<mkldnn::memory> out;
89+ std::shared_ptr<mkldnn::memory> bias;
90+ std::shared_ptr<mkldnn::inner_product_forward> ipFwd;
91+
92+ public:
93+ mkldnn::inner_product_forward::primitive_desc ipFwd_pd;
94+
95+ MKLDNNFullyConnectForward (const FullyConnectedParam ¶m, bool is_train,
96+ const NDArray &data, const NDArray &weight,
97+ const NDArray *bias,
98+ const mkldnn::memory::desc &output)
99+ : ipFwd_pd(GetIPFwd(data, weight, bias, output, is_train)) {}
100+
101+ void SetNewMem (const mkldnn::memory &data, const mkldnn::memory &weight,
102+ const mkldnn::memory *bias, const mkldnn::memory &output) {
103+ if (this ->data == nullptr )
104+ this ->data = std::shared_ptr<mkldnn::memory>(new mkldnn::memory (
105+ ipFwd_pd.src_primitive_desc (), data.get_data_handle ()));
106+ else
107+ this ->data ->set_data_handle (data.get_data_handle ());
108+
109+ if (this ->weight == nullptr )
110+ this ->weight = std::shared_ptr<mkldnn::memory>(new mkldnn::memory (
111+ ipFwd_pd.weights_primitive_desc (), weight.get_data_handle ()));
112+ else
113+ this ->weight ->set_data_handle (weight.get_data_handle ());
114+
115+ if (this ->out == nullptr )
116+ this ->out = std::shared_ptr<mkldnn::memory>(new mkldnn::memory (
117+ ipFwd_pd.dst_primitive_desc (), output.get_data_handle ()));
118+ else
119+ this ->out ->set_data_handle (output.get_data_handle ());
120+
121+ if (bias != nullptr ) {
122+ if (this ->bias == nullptr )
123+ this ->bias = std::shared_ptr<mkldnn::memory>(new mkldnn::memory (
124+ ipFwd_pd.bias_primitive_desc (), bias->get_data_handle ()));
125+ else
126+ this ->bias ->set_data_handle (bias->get_data_handle ());
127+ if (this ->ipFwd == nullptr )
128+ this ->ipFwd = std::shared_ptr<mkldnn::inner_product_forward>(
129+ new mkldnn::inner_product_forward (
130+ ipFwd_pd, mkldnn::primitive::at (*this ->data ),
131+ mkldnn::primitive::at (*this ->weight ),
132+ mkldnn::primitive::at (*this ->bias ), *this ->out ));
133+ } else if (this ->ipFwd == nullptr ) {
134+ this ->ipFwd = std::shared_ptr<mkldnn::inner_product_forward>(
135+ new mkldnn::inner_product_forward (
136+ ipFwd_pd, mkldnn::primitive::at (*this ->data ),
137+ mkldnn::primitive::at (*this ->weight ), *this ->out ));
138+ }
139+ }
140+ const mkldnn::inner_product_forward &GetIpFwd () const {
141+ return *ipFwd;
142+ }
143+ };
144+
145+ typedef ParamOpSign<FullyConnectedParam> MKLDNNFullyconSignature;
146+
147+ static inline MKLDNNFullyConnectForward &GetFCFwd (
148+ const nnvm::NodeAttrs &attrs, const NDArray &data, const NDArray &weight,
149+ const NDArray *bias, const mkldnn::memory::desc &output,
150+ const bool is_train) {
151+ #if DMLC_CXX11_THREAD_LOCAL
152+ static thread_local std::unordered_map<MKLDNNFullyconSignature,
153+ MKLDNNFullyConnectForward, OpHash> fcFwds;
154+ #else
155+ static MX_THREAD_LOCAL std::unordered_map<MKLDNNFullyconSignature,
156+ MKLDNNFullyConnectForward, OpHash> fcFwds;
157+ #endif
158+ const FullyConnectedParam& param = nnvm::get<FullyConnectedParam>(attrs.parsed );
159+ MKLDNNFullyconSignature key (param);
160+ key.AddSign (data);
161+ key.AddSign (weight);
162+ key.AddSign (is_train);
163+
164+ if (bias)
165+ key.AddSign (*bias);
166+
167+ auto it = fcFwds.find (key);
168+ if (it == fcFwds.end ()) {
169+ MKLDNNFullyConnectForward fcFwd (param, is_train, data, weight, bias,
170+ output);
171+ auto ins_ret = fcFwds.insert (
172+ std::pair<MKLDNNFullyconSignature, MKLDNNFullyConnectForward>(key, fcFwd));
173+ CHECK (ins_ret.second );
174+ it = ins_ret.first ;
175+ }
176+ return it->second ;
177+ }
178+
85179void MKLDNNFCForward (const nnvm::NodeAttrs& attrs, const OpContext &ctx,
86180 const std::vector<NDArray> &in_data,
87181 const std::vector<OpReqType> &req,
@@ -112,21 +206,21 @@ void MKLDNNFCForward(const nnvm::NodeAttrs& attrs, const OpContext &ctx,
112206 out_md = mkldnn::memory::desc (out_dims, get_mkldnn_type (out_data[fullc::kOut ].dtype ()),
113207 mkldnn::memory::format::any);
114208 }
115-
116- mkldnn::inner_product_forward::primitive_desc ipFwd_pd = GetIPFwd ( data, weight,
117- param. no_bias ? nullptr : &in_data[fullc:: kBias ], out_md, ctx.is_train );
118- auto data_mem = data.GetMKLDNNDataReorder (ipFwd_pd.src_primitive_desc ());
119- auto weight_mem = weight.GetMKLDNNDataReorder (ipFwd_pd.weights_primitive_desc ());
209+ MKLDNNFullyConnectForward &FCFwd =
210+ GetFCFwd (attrs, data, weight, param. no_bias ? nullptr : &in_data[fullc:: kBias ] ,
211+ out_md, ctx.is_train );
212+ auto data_mem = data.GetMKLDNNDataReorder (FCFwd. ipFwd_pd .src_primitive_desc ());
213+ auto weight_mem = weight.GetMKLDNNDataReorder (FCFwd. ipFwd_pd .weights_primitive_desc ());
120214 auto out_mem = CreateMKLDNNMem (out_data[fullc::kOut ],
121- ipFwd_pd.dst_primitive_desc (), req[fullc::kOut ]);
122- if (param.no_bias ) {
123- MKLDNNStream::Get ()->RegisterPrim (mkldnn::inner_product_forward (
124- ipFwd_pd, *data_mem, *weight_mem, *out_mem.second ));
215+ FCFwd.ipFwd_pd .dst_primitive_desc (), req[fullc::kOut ], &data);
216+ if (!param.no_bias ) {
217+ auto bias_mem = in_data[fullc::kBias ].GetMKLDNNDataReorder (
218+ FCFwd.ipFwd_pd .bias_primitive_desc ());
219+ FCFwd.SetNewMem (*data_mem, *weight_mem, bias_mem, *out_mem.second );
125220 } else {
126- auto bias_mem = in_data[fullc::kBias ].GetMKLDNNDataReorder (ipFwd_pd.bias_primitive_desc ());
127- MKLDNNStream::Get ()->RegisterPrim (mkldnn::inner_product_forward (ipFwd_pd,
128- *data_mem, *weight_mem, *bias_mem, *out_mem.second ));
221+ FCFwd.SetNewMem (*data_mem, *weight_mem, nullptr , *out_mem.second );
129222 }
223+ MKLDNNStream::Get ()->RegisterPrim (FCFwd.GetIpFwd ());
130224 CommitOutput (out_data[fullc::kOut ], out_mem);
131225 MKLDNNStream::Get ()->Submit ();
132226}
0 commit comments