Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes Memory Leak #231

Merged
merged 8 commits into from
Mar 14, 2020
Merged

Fixes Memory Leak #231

merged 8 commits into from
Mar 14, 2020

Conversation

leoarc
Copy link
Contributor

@leoarc leoarc commented Mar 10, 2020

Fixes #228
Before :

Selection_004

After :

Selection_006

All unused tensors inside the runPredict() are being disposed . Performance for multiple predictions has improved a lot. Running multiple predictions dosen't overflow memory now.

@leoarc
Copy link
Contributor Author

leoarc commented Mar 10, 2020

@Insiyaa @birm Please have a look at it and suggest necessary changes.

@birm birm added the bugfix label Mar 10, 2020
@birm birm self-requested a review March 10, 2020 02:19
let img2;
tf.tidy(()=>{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

img2 is hanging after tf.tidy

// normalized.mean().print(true); // Uncomment to check mean value.
// let min = img2.min();
// let max = img2.max();
// let normalized = img2.sub(min).div(max.sub(min));
} else {
// Pixel Standardization: scale pixel values to have a zero mean and unit variance.

tf.tidy(()=> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is normalized returned to

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to keep tf.tidy() from destroying the tensor it needs to be returned. normalized is being used afterwards so it doesn't need to be destroyed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The returned object has to be assigned

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am using tf.keep() instead of return. Does this solve the issue?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It still needs to be assigned, please refer the usage here: https://js.tensorflow.org/api/latest/#keep

@Insiyaa
Copy link
Contributor

Insiyaa commented Mar 10, 2020

The mobilenet example might help you with placing these calls. Please let me know if you are facing some issues.

@leoarc
Copy link
Contributor Author

leoarc commented Mar 10, 2020

@Insiyaa Tried fixing the issues . Let me know if they are ok .

@Insiyaa
Copy link
Contributor

Insiyaa commented Mar 10, 2020

You can enclose into tf.tidy starting from here till the end of the for block. On the predict call, remove await and make it dataSync(). This should help, the same changes are to be done for segment app.

@leoarc
Copy link
Contributor Author

leoarc commented Mar 10, 2020

On the predict call, remove await and make it dataSync().

This doesn't work . As given in the documentation here tf.dataSync() is used to download values from a tensor (which is used to store tensor to a js array link ) . I don't know what it is doing here but code runs fine if it is commented. So removing await in the predict call makes it return a promise to values and thus causes errors in the next steps.

@leoarc
Copy link
Contributor Author

leoarc commented Mar 10, 2020

@Insiyaa As you mentioned earlier , now I have assigned all the variables returned by tf.tidy().
Please review.

@Insiyaa
Copy link
Contributor

Insiyaa commented Mar 10, 2020

Oh yes, that is just a warmup run and we don't really need to get the results, so removing that line would do just good.
What I mean to suggest is that just one tf.tidy call enclosing everything is needed, this line being included or not depends on whether the values are obtained sync (i.e. - let values = model.predict(batched).dataSync(); goes inside the tidy call) or async (let it stay outside). Since the predictions happen patch-wise, I believe it should go about synchronously.

@leoarc
Copy link
Contributor Author

leoarc commented Mar 10, 2020

@Insiyaa So i started from the beginning. Now the for loop has only call to tf.tidy() . There is one other call to tf.tidy() here used to dispose the tf.zeros(..) tensor. Please review .

@@ -471,10 +473,11 @@ function runPredict(key) {
self.showProgress("Model loaded...");

// Warmup the model before using real data.
tf.tidy(()=>{
const warmupResult = model.predict(tf.zeros([1, image_size, image_size, input_channels]));
warmupResult.dataSync();
Copy link
Contributor

@Insiyaa Insiyaa Mar 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realise the line 478 isn't required to get the values, could you remove it?

@Insiyaa
Copy link
Contributor

Insiyaa commented Mar 11, 2020

That seems good, thank you! The same additions would go into segment.js. Also, could you squash the commits into one with a meaningful commit message :)

@birm
Copy link
Member

birm commented Mar 11, 2020

If you prefer not to mess with rebasing, we can squash when merging the PR itself.

@leoarc
Copy link
Contributor Author

leoarc commented Mar 12, 2020

So i am facing a problem. This line is returning a tensor which I am not being able to dispose . The documentation says tf.browser.toPixels returns a promise of type Uint8ClampedArray and not a tensor . So I am not able to do let x = await tf.toPixels(...) and x.dispose() . And I suppose this function has to be asynchronous .Any ideas ? @Insiyaa

@leoarc
Copy link
Contributor Author

leoarc commented Mar 14, 2020

@birm @Insiyaa Should we close this for now ? It still has the issue which I mentioned in the last comment . The issue has been mentioned here and though it is showing solved I think it isn't . Anyways it must be a internal leak . Please review.

@Insiyaa
Copy link
Contributor

Insiyaa commented Mar 14, 2020

In my view, all the required additions are done. You're right; there is probably some leak inside tf.browser.toPixels, we can keep track of it. Also, you might want to look into backends if it helps with this issue.
@birm would you like to suggest any changes?

Copy link
Member

@birm birm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not super picky on formatting now, so this seems fine. Thanks!

@birm birm merged commit f047436 into camicroscope:develop Mar 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants