Skip to content

Commit bb6559a

Browse files
authored
Changes in the mayFreeIoBlobs criterion. (#1126)
First off all, it was rewritten as function to simplify understanding. But this is not the main change. The main is that `!IsRecurrentMode() || IsLastSequencePos()` subcriteron is combined with others using `and` instead of `or`. As a result, the inputs of an incomplete recurrent layer will not be dropped until the recurrent processing completes. Found when monitoring allocations: each call of `runOnce` inside recursion was allocating output blob. Signed-off-by: slon872 <[email protected]>
1 parent 763026f commit bb6559a

File tree

2 files changed

+46
-16
lines changed

2 files changed

+46
-16
lines changed

NeoML/include/NeoML/Dnn/Dnn.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ struct CDnnLayerLink final {
125125

126126
//------------------------------------------------------------------------------------------------------------
127127

128-
// CBaseLayer is the base class for all layers with which the network can function.
129-
// Each layer has a string name that should be unique in the network. Each layer may have
128+
// CBaseLayer is the base class for all layers with which the network can function.
129+
// Each layer has a string name that should be unique in the network. Each layer may have
130130
// one or several inputs and one or several outputs.
131131
class NEOML_API CBaseLayer : public virtual IObject {
132132
public:
@@ -138,7 +138,7 @@ class NEOML_API CBaseLayer : public virtual IObject {
138138
// The current network (described by a CDnn class) to which the layer belongs
139139
// While a layer is connected to a network, you may not change its basic configuration,
140140
// such as its name, the list of inputs, the size of a convolution window, etc.
141-
// While a layer belongs to a network, only the settings like input blob size
141+
// While a layer belongs to a network, only the settings like input blob size
142142
// or function coefficients (for example, during training) may be changed
143143
const CDnn* GetDnn() const { return dnn; }
144144
CDnn* GetDnn() { return dnn; }
@@ -181,7 +181,7 @@ class NEOML_API CBaseLayer : public virtual IObject {
181181
void EnableLearning();
182182
bool IsLearningEnabled() const { return isLearningEnabled; }
183183

184-
// Base learning rate (the learning strategy may change
184+
// Base learning rate (the learning strategy may change
185185
// the relative learning rates inside the network, but the base rate stays the same)
186186
float GetBaseLearningRate() const { return baseLearningRate; }
187187
void SetBaseLearningRate( float rate ) { baseLearningRate = rate; }
@@ -198,11 +198,11 @@ class NEOML_API CBaseLayer : public virtual IObject {
198198

199199
// Begins processing a new sequence
200200
// The method is overloaded for the composite layer and the backward link layer
201-
virtual void RestartSequence() {}
201+
virtual void RestartSequence() {}
202202

203203
void Serialize(CArchive& archive) override;
204204

205-
// Indicates that backpropagation should be performed for the layer
205+
// Indicates that backpropagation should be performed for the layer
206206
// even if there are no trainable layers before it
207207
bool GetBackwardForced() const { return isBackwardForced; }
208208
void SetBackwardForced(bool forced);
@@ -432,6 +432,7 @@ class NEOML_API CBaseLayer : public virtual IObject {
432432
void reshape();
433433
void setInputDesc(int i);
434434
void runOnce();
435+
bool mayFreeIoBlobs() const;
435436
void recheckBackwardNeeded();
436437
void backwardRunAndLearnOnce();
437438
void transferDiffBlob( CDnnBlob* diffBlob, int outputNum );

NeoML/src/Dnn/BaseLayer.cpp

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ void CBaseLayer::reshape()
405405
CArray<CBlobDesc> prevInputDescs;
406406
inputDescs.MoveTo( prevInputDescs );
407407
inputDescs.SetSize(inputs.Size());
408-
408+
409409
// Call the input layers reshape recursively, reset the input blobs
410410
for( int i = 0; i < GetInputCount(); ++i ) {
411411
GetInputLayer(i)->reshape();
@@ -420,7 +420,7 @@ void CBaseLayer::reshape()
420420

421421
if(!forcedReshape) {
422422
for(int i = 0; i < inputBlobs.Size(); i++) {
423-
forcedReshape = forcedReshape
423+
forcedReshape = forcedReshape
424424
|| !inputDescs[i].HasEqualDimensions(prevInputDescs[i]);
425425
}
426426
}
@@ -529,11 +529,7 @@ void CBaseLayer::runOnce()
529529
inputBlobs[i] = prevLayerOutput;
530530
}
531531

532-
const bool mayFreeIoBlobs = GetDnn()->isReuseMemoryMode
533-
&& ( !GetDnn()->isBackwardPerformed || !GetDnn()->IsRecurrentMode() || GetDnn()->IsLastSequencePos()
534-
|| ( ( blobsNeededForBackward & TInputBlobs ) == 0 && ( !isInPlace || ( blobsNeededForBackward & TOutputBlobs ) == 0 ) ) );
535-
536-
if( mayFreeIoBlobs ) {
532+
if( mayFreeIoBlobs() ) {
537533
for( int i = 0; i < inputBlobs.Size(); ++i ) {
538534
CBaseLayer* inputLayer = GetInputLayer( i );
539535
const int outputNumber = inputs[i].OutputNumber;
@@ -564,6 +560,39 @@ void CBaseLayer::runOnce()
564560
}
565561
}
566562

563+
// Checks if output blobs of input layers can be discarded.
564+
bool CBaseLayer::mayFreeIoBlobs() const
565+
{
566+
assert( dnn != nullptr );
567+
568+
if( !dnn->isReuseMemoryMode ) {
569+
// Memory reuse turned off.
570+
return false;
571+
}
572+
573+
if( dnn->IsRecurrentMode() && !dnn->IsLastSequencePos() ) {
574+
// Recurrent layer processing is incomplete.
575+
return false;
576+
}
577+
578+
if( !dnn->isBackwardPerformed ) {
579+
// Inference mode, intermediate data is not required.
580+
return true;
581+
}
582+
583+
if( (blobsNeededForBackward & TInputBlobs) != 0 ) {
584+
// Input blobs are required for back propagation.
585+
return false;
586+
}
587+
588+
if( isInPlace && (blobsNeededForBackward & TOutputBlobs) != 0 ) {
589+
// Output blobs are required for back propagation and they are the same as input.
590+
return false;
591+
}
592+
593+
return true;
594+
}
595+
567596
// Recalculates the isBackwardNeeded flag; recursively checks the inputs
568597
void CBaseLayer::recheckBackwardNeeded()
569598
{
@@ -625,7 +654,7 @@ void CBaseLayer::backwardRunAndLearnOnce()
625654
}
626655
}
627656

628-
// Perform one step of error backward propagation:
657+
// Perform one step of error backward propagation:
629658
// calculate the input error from the output one
630659
BackwardOnce();
631660
}
@@ -647,7 +676,7 @@ void CBaseLayer::backwardRunAndLearnOnce()
647676
paramDiffBlobs.DeleteAll();
648677
}
649678
}
650-
679+
651680
outputDiffBlobs.DeleteAll();
652681

653682
if( IsBackwardPerformed() ) {
@@ -681,7 +710,7 @@ void CBaseLayer::backwardRunAndLearnOnce()
681710
}
682711

683712
// Handles the notification that output diff is ready for a given output
684-
// If that is the last output diff necessary for learning,
713+
// If that is the last output diff necessary for learning,
685714
// backpropagation and learning are started for this layer
686715
void CBaseLayer::transferDiffBlob( CDnnBlob* diffBlob, int outputNum )
687716
{

0 commit comments

Comments
 (0)