Skip to content

Commit af2e882

Browse files
committed
[Layer] Modify Layer for mixed type
fc, conv2d, softmax, pooling layers are modified for mxied type. It supports In/Out tensors as 32/16 float type, also for weights. Signed-off-by: Jiho Chu <jiho.chu@samsung.com>
1 parent 98ad0b9 commit af2e882

File tree

5 files changed

+135
-15
lines changed

5 files changed

+135
-15
lines changed

nntrainer/layers/common_properties.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1398,10 +1398,12 @@ class PropsUserData final : public Property<void *> {
13981398
/**
13991399
* @brief LossScale property, loss is scaled by this value
14001400
*
1401+
* @note It is uesed to enable/disable loss scale,
1402+
* and '0.0f' means disable.
14011403
*/
14021404
class LossScale : public nntrainer::Property<float> {
14031405
public:
1404-
LossScale(float value = 1.0f);
1406+
LossScale(float value = 0.0f);
14051407
static constexpr const char *key = "loss_scale"; /**< unique key to access */
14061408
using prop_tag = float_prop_tag; /**< property type */
14071409
};

nntrainer/layers/conv2d_layer.cpp

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,16 @@ static void col2im(const Tensor &col_matrix, const TensorDim &kdim,
117117
if (image.getDataType() == nntrainer::Tdatatype::FP32) {
118118
float val;
119119
apply_data(&val);
120-
} else if (image.getDataType() == nntrainer::Tdatatype::FP16) {
120+
}
121+
#ifdef ENABLE_FP16
122+
else if (image.getDataType() == nntrainer::Tdatatype::FP16) {
121123
_FP16 val;
122124
apply_data(&val);
123125
}
126+
#endif
127+
else {
128+
throw std::runtime_error("Not supported datatype");
129+
}
124130
}
125131

126132
/**
@@ -254,10 +260,16 @@ static void im2col(const Tensor &in, const TensorDim &kdim,
254260
if (out.getDataType() == nntrainer::Tdatatype::FP32) {
255261
float *out_data = out.getData<float>();
256262
apply_data(out_data);
257-
} else if (out.getDataType() == nntrainer::Tdatatype::FP16) {
263+
}
264+
#ifdef ENABLE_FP16
265+
else if (out.getDataType() == nntrainer::Tdatatype::FP16) {
258266
_FP16 *out_data = out.getData<_FP16>();
259267
apply_data(out_data);
260268
}
269+
#endif
270+
else {
271+
throw std::runtime_error("Not supported datatype");
272+
}
261273
}
262274

263275
} // namespace
@@ -355,7 +367,14 @@ void Conv2DLayer::forwarding(RunLayerContext &context, bool training) {
355367
Tensor &input_ = context.getInput(SINGLE_INOUT_IDX);
356368
Tensor &hidden_ = context.getOutput(SINGLE_INOUT_IDX);
357369

358-
Tensor &filter_kernel = context.getWeight(wt_idx[ConvParams::weight]);
370+
Tensor &filter_kernel_ = context.getWeight(wt_idx[ConvParams::weight]);
371+
372+
Tensor filter_kernel;
373+
if (filter_kernel_.getDataType() != input_.getDataType()) {
374+
filter_kernel = filter_kernel_.clone(input_.getDataType());
375+
} else {
376+
filter_kernel = filter_kernel_;
377+
}
359378

360379
/** Calculate Convolution 2D
361380
*
@@ -431,12 +450,21 @@ void Conv2DLayer::forwarding(RunLayerContext &context, bool training) {
431450
filter_kernel.reshape(filter_dim);
432451
if (auto &disable_bias = std::get<props::DisableBias>(*layer_impl_props);
433452
disable_bias.empty() || disable_bias.get() == false) {
434-
Tensor &bias_kernel = context.getWeight(wt_idx[ConvParams::bias]);
453+
Tensor &bias_kernel_ = context.getWeight(wt_idx[ConvParams::bias]);
454+
Tensor bias_kernel;
455+
if (bias_kernel_.getDataType() != hidden_.getDataType()) {
456+
bias_kernel = bias_kernel_.clone(hidden_.getDataType());
457+
} else {
458+
bias_kernel = bias_kernel_;
459+
}
460+
435461
status = hidden_.add_i(bias_kernel);
436462
if (status != ML_ERROR_NONE) {
437463
throw std::invalid_argument("[Conv2D] adding bias failed");
438464
}
439465
}
466+
//export_to_file(input_, std::string("debug/var/") + input_.getName() + ".var");
467+
//export_to_file(hidden_, std::string("debug/var/") + hidden_.getName() + ".var");
440468
}
441469

442470
void Conv2DLayer::calcDerivative(RunLayerContext &context) {
@@ -447,7 +475,14 @@ void Conv2DLayer::calcDerivative(RunLayerContext &context) {
447475

448476
const Tensor &derivative = context.getIncomingDerivative(SINGLE_INOUT_IDX);
449477
Tensor &input_derivative = context.getOutgoingDerivative(SINGLE_INOUT_IDX);
450-
Tensor &filter_kernel = context.getWeight(wt_idx[ConvParams::weight]);
478+
Tensor &filter_kernel_ = context.getWeight(wt_idx[ConvParams::weight]);
479+
480+
Tensor filter_kernel;
481+
if (filter_kernel_.getDataType() != input_derivative.getDataType()) {
482+
filter_kernel = filter_kernel_.clone(input_derivative.getDataType());
483+
} else {
484+
filter_kernel = filter_kernel_;
485+
}
451486

452487
TensorDim filter_dim = filter_kernel.getDim();
453488
TensorDim filter_dim_squeezed{filter_kernel.batch(),
@@ -495,7 +530,14 @@ void Conv2DLayer::calcGradient(RunLayerContext &context) {
495530
const Tensor &derivative = context.getIncomingDerivative(SINGLE_INOUT_IDX);
496531
Tensor &input_ = context.getInput(SINGLE_INOUT_IDX);
497532

498-
Tensor &delK = context.getWeightGrad(wt_idx[ConvParams::weight]);
533+
Tensor &delK_ = context.getWeightGrad(wt_idx[ConvParams::weight]);
534+
Tensor delK;
535+
if (delK.getDataType() != input_.getDataType()) {
536+
delK = delK_.clone(input_.getDataType());
537+
} else {
538+
delK = delK_;
539+
}
540+
499541
delK.setZero();
500542

501543
TensorDim filter_dim = delK.getDim();
@@ -577,9 +619,17 @@ void Conv2DLayer::calcGradient(RunLayerContext &context) {
577619
delK.reshape(filter_dim);
578620
if (auto &disable_bias = std::get<props::DisableBias>(*layer_impl_props);
579621
disable_bias.empty() || disable_bias.get() == false) {
580-
Tensor &delBias = context.getWeightGrad(wt_idx[ConvParams::bias]);
622+
Tensor &delBias_ = context.getWeightGrad(wt_idx[ConvParams::bias]);
623+
Tensor delBias;
624+
if (delBias_.getDataType() != derivative.getDataType()) {
625+
delBias = delBias_.clone(derivative.getDataType());
626+
} else {
627+
delBias = delBias_;
628+
}
581629
derivative.sum({0, 2, 3}, delBias);
630+
delBias_.copyData(delBias);
582631
}
632+
delK_.copyData(delK);
583633
}
584634

585635
void Conv2DLayer::exportTo(Exporter &exporter,

nntrainer/layers/fc_layer.cpp

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,17 @@ void FullyConnectedLayer::setProperty(const std::vector<std::string> &values) {
116116
}
117117

118118
void FullyConnectedLayer::forwarding(RunLayerContext &context, bool training) {
119-
Tensor &weight = context.getWeight(weight_idx[FCParams::weight]);
119+
Tensor &weight_ = context.getWeight(weight_idx[FCParams::weight]);
120120
Tensor &hidden_ = context.getOutput(SINGLE_INOUT_IDX);
121121
Tensor &input_ = context.getInput(SINGLE_INOUT_IDX);
122122

123+
Tensor weight;
124+
if (weight.getDataType() != input_.getDataType()) {
125+
weight = weight_.clone(input_.getDataType());
126+
} else {
127+
weight = weight_;
128+
}
129+
123130
if (weight.getDataType() == nntrainer::Tdatatype::QINT4 ||
124131
weight.getDataType() == nntrainer::Tdatatype::QINT8) {
125132
Tdatatype dtype = input_.getDataType();
@@ -141,7 +148,13 @@ void FullyConnectedLayer::forwarding(RunLayerContext &context, bool training) {
141148
if (auto &disable_bias = std::get<props::DisableBias>(*layer_impl_props);
142149
disable_bias.empty() || disable_bias.get() == false) {
143150
Tensor &bias = context.getWeight(weight_idx[FCParams::bias]);
144-
hidden_.add_i(bias);
151+
Tensor b;
152+
if (bias.getDataType() != input_.getDataType()) {
153+
b = bias.clone(input_.getDataType());
154+
} else {
155+
b = bias;
156+
}
157+
hidden_.add_i(b);
145158
}
146159
}
147160

@@ -187,23 +200,44 @@ void FullyConnectedLayer::incremental_forwarding(RunLayerContext &context,
187200
}
188201

189202
void FullyConnectedLayer::calcDerivative(RunLayerContext &context) {
190-
Tensor &weight = context.getWeight(weight_idx[FCParams::weight]);
203+
Tensor &weight_ = context.getWeight(weight_idx[FCParams::weight]);
191204

192205
const Tensor &derivative_ = context.getIncomingDerivative(SINGLE_INOUT_IDX);
193206
Tensor &ret_ = context.getOutgoingDerivative(SINGLE_INOUT_IDX);
194207

208+
Tensor weight;
209+
if (weight_.getDataType() != derivative_.getDataType()) {
210+
weight = weight_.clone(derivative_.getDataType());
211+
} else {
212+
weight = weight_;
213+
}
214+
195215
ret_.dot_deriv_wrt_1(weight, derivative_, false, false);
196216
}
197217

198218
void FullyConnectedLayer::calcGradient(RunLayerContext &context) {
199-
Tensor &djdw = context.getWeightGrad(weight_idx[FCParams::weight]);
219+
Tensor &djdw_ = context.getWeightGrad(weight_idx[FCParams::weight]);
200220

201221
const Tensor &derivative_ = context.getIncomingDerivative(SINGLE_INOUT_IDX);
202222
Tensor &input_ = context.getInput(SINGLE_INOUT_IDX);
203223

224+
Tensor djdw;
225+
if (djdw_.getDataType() != derivative_.getDataType()) {
226+
djdw = djdw_.clone(derivative_.getDataType());
227+
} else {
228+
djdw = djdw_;
229+
}
230+
204231
if (auto &disable_bias = std::get<props::DisableBias>(*layer_impl_props);
205232
disable_bias.empty() || disable_bias.get() == false) {
206-
Tensor &djdb = context.getWeightGrad(weight_idx[FCParams::bias]);
233+
Tensor &djdb_ = context.getWeightGrad(weight_idx[FCParams::bias]);
234+
235+
Tensor djdb;
236+
if (djdb_.getDataType() != input_.getDataType()) {
237+
djdb = djdb_.clone(input_.getDataType());
238+
} else {
239+
djdb = djdb_;
240+
}
207241

208242
if (context.isGradientFirstAccess(weight_idx[FCParams::bias])) {
209243
derivative_.sum({0, 1, 2}, djdb);
@@ -212,11 +246,13 @@ void FullyConnectedLayer::calcGradient(RunLayerContext &context) {
212246
Tensor t = derivative_.sum({0, 1, 2});
213247
djdb.add_i(t);
214248
}
249+
djdb_.copyData(djdb);
215250
}
216251

217252
input_.dot_deriv_wrt_2(
218253
djdw, derivative_, false, false,
219254
!context.isGradientFirstAccess(weight_idx[FCParams::weight]));
255+
djdw_.copyData(djdw);
220256
}
221257

222258
} /* namespace nntrainer */

nntrainer/layers/loss/cross_entropy_softmax_loss_layer.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ void CrossEntropySoftmaxLossLayer::forwarding(RunLayerContext &context,
2929
Tensor &hidden_ = context.getOutput(SINGLE_INOUT_IDX);
3030
Tensor &y = context.getInput(SINGLE_INOUT_IDX);
3131

32+
//export_to_file(y, std::string("debug/var/") + y.getName() + ".var");
33+
3234
// fill the output
3335
auto out_type = hidden_.getDataType();
3436
if (out_type == ml::train::TensorDim::DataType::FP32) {
@@ -93,7 +95,8 @@ void CrossEntropySoftmaxLossLayer::calcDerivative(RunLayerContext &context) {
9395
"Error when calculating loss");
9496
}
9597

96-
ret_derivative.multiply_i(loss_scale);
98+
if (loss_scale != 0.0f)
99+
ret_derivative.multiply_i(loss_scale);
97100
}
98101

99102
} // namespace nntrainer

nntrainer/layers/pooling2d_layer.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ void Pooling2DLayer::forwarding(RunLayerContext &context, bool training) {
155155
} else {
156156
forwarding_job(0, in_dim.batch(), 0, nullptr);
157157
}
158+
159+
//export_to_file(input_, std::string("debug/var/") + input_.getName() + ".var");
160+
//export_to_file(hidden_, std::string("debug/var/") + hidden_.getName() + ".var");
158161
}
159162

160163
void Pooling2DLayer::calcDerivative(RunLayerContext &context) {
@@ -258,21 +261,33 @@ void Pooling2DLayer::calcDerivative(RunLayerContext &context) {
258261
case props::PoolingTypeInfo::Enum::max:
259262
if (in_dim.getDataType() == ml::train::TensorDim::DataType::FP32)
260263
apply_max(result.getData<float>());
264+
#ifdef ENABLE_FP16
261265
else if (in_dim.getDataType() == ml::train::TensorDim::DataType::FP16)
262266
apply_max(result.getData<_FP16>());
267+
#endif
268+
else
269+
throw std::runtime_error("Not supported datatype");
263270
break;
264271
case props::PoolingTypeInfo::Enum::global_average:
265272
case props::PoolingTypeInfo::Enum::average:
266273
if (in_dim.getDataType() == ml::train::TensorDim::DataType::FP32)
267274
apply_average(result.getData<float>());
275+
#ifdef ENABLE_FP16
268276
else if (in_dim.getDataType() == ml::train::TensorDim::DataType::FP16)
269277
apply_average(result.getData<_FP16>());
278+
#endif
279+
else
280+
throw std::runtime_error("Not supported datatype");
270281
break;
271282
case props::PoolingTypeInfo::Enum::global_max:
272283
if (in_dim.getDataType() == ml::train::TensorDim::DataType::FP32)
273284
apply_global_max(result.getData<float>());
285+
#ifdef ENABLE_FP16
274286
else if (in_dim.getDataType() == ml::train::TensorDim::DataType::FP16)
275287
apply_global_max(result.getData<_FP16>());
288+
#endif
289+
else
290+
throw std::runtime_error("Not supported datatype");
276291
break;
277292
default:
278293
throw std::runtime_error("Error: Unknown Pooling Type");
@@ -320,7 +335,9 @@ void Pooling2DLayer::pooling2d(Tensor &in, bool training, Tensor &output,
320335
* @return result value of pooling
321336
*/
322337
PoolFunc<float>::Type pool_fn_fp32;
338+
#ifdef ENABLE_FP16
323339
PoolFunc<_FP16>::Type pool_fn_fp16;
340+
#endif
324341

325342
unsigned int max_idx_count = 0;
326343

@@ -411,16 +428,22 @@ void Pooling2DLayer::pooling2d(Tensor &in, bool training, Tensor &output,
411428
switch (pooling_type) {
412429
case props::PoolingTypeInfo::Enum::max:
413430
pool_fn_fp32 = pool_fn_max;
431+
#ifdef ENABLE_FP16
414432
pool_fn_fp16 = pool_fn_max;
433+
#endif
415434
break;
416435
case props::PoolingTypeInfo::Enum::global_max:
417436
pool_fn_fp32 = pool_fn_global_max;
437+
#ifdef ENABLE_FP16
418438
pool_fn_fp16 = pool_fn_global_max;
439+
#endif
419440
break;
420441
case props::PoolingTypeInfo::Enum::global_average:
421442
case props::PoolingTypeInfo::Enum::average:
422443
pool_fn_fp32 = pool_fn_average;
444+
#ifdef ENABLE_FP16
423445
pool_fn_fp16 = pool_fn_average;
446+
#endif
424447
break;
425448
case props::PoolingTypeInfo::Enum::unknown:
426449
default:
@@ -446,7 +469,9 @@ void Pooling2DLayer::pooling2d(Tensor &in, bool training, Tensor &output,
446469
}
447470
}
448471
}
449-
} else if (in.getDataType() == ml::train::TensorDim::DataType::FP16) {
472+
}
473+
#ifdef ENABLE_FP16
474+
else if (in.getDataType() == ml::train::TensorDim::DataType::FP16) {
450475
const _FP16 *in_data = in.getData<_FP16>();
451476
_FP16 *out_data = output.getData<_FP16>();
452477

@@ -465,6 +490,10 @@ void Pooling2DLayer::pooling2d(Tensor &in, bool training, Tensor &output,
465490
}
466491
}
467492
}
493+
#endif
494+
else {
495+
throw std::runtime_error("Not supported datatype");
496+
}
468497
}
469498

470499
void Pooling2DLayer::setBatch(RunLayerContext &context, unsigned int batch) {

0 commit comments

Comments
 (0)