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

ENH: add callback that shows memory and cpu usage. #1024

Merged
merged 3 commits into from Jun 17, 2017

Conversation

aringh
Copy link
Member

@aringh aringh commented Jun 8, 2017

Add callback that prints memory and cpu usage. As in the code example in issue #1014

@aringh
Copy link
Member Author

aringh commented Jun 8, 2017

Travis CI seems to have crashed for not finding the package psutil, which is used in the callback to get memory and cpu states. Could @adler-j or @kohr-h have a look at that? Is it bad to build more dependencies into odl?

@kohr-h
Copy link
Member

kohr-h commented Jun 8, 2017

Travis CI seems to have crashed for not finding the package psutil, which is used in the callback to get memory and cpu states. Could @adler-j or @kohr-h have a look at that? Is it bad to build more dependencies into odl?

Yeah, I don't want to add dependencies for such a small thing. Usually when we have an optional dependency that is essential for some part (like pyfftw for fast FFTs) we add it to the extras_require list in setup.py.

Since that is not really the case here, I think the way to go is to import lazily in __call__ and print an error to the user that psutil should be installed (using conda or pip) if the import fails. That requirement should then also be mentioned in the class documentation.

Copy link
Member

@adler-j adler-j left a comment

Choose a reason for hiding this comment

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

Good addition! Just some minor stuff to do, approving.

def __call__(self, _):
"""Print the memory and CPU usage"""
if self.iter % self.step == 0:
print('CPU usage (% each core): {}'.format(
Copy link
Member

Choose a reason for hiding this comment

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

I would prefer an optional format string as is the case in some other callbacks. Also keeps it too one line by default.

Copy link
Member

Choose a reason for hiding this comment

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

Suggestion:

  • remove swap (not really needed)
  • use format strings for each resource separately, like fmt_cpu, fmt_mem, with sensible defaults
  • add flags print_cpu and print_mem to switch on/off

@@ -854,6 +856,52 @@ def __repr__(self):
self.logy)


class CallbackPrintMemory(SolverCallback):
Copy link
Member

Choose a reason for hiding this comment

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

It prints more than memory so perhaps some other name. CallbackPrintHardwareUse or something.

Copy link
Member

Choose a reason for hiding this comment

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

True, Usage it would be in any case.

@@ -13,6 +13,7 @@
from future import standard_library
standard_library.install_aliases()

import psutil
Copy link
Member

Choose a reason for hiding this comment

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

As discussed, Lazily import inside the call.

@aringh
Copy link
Member Author

aringh commented Jun 15, 2017

I am working on the updates. Where in the doc should the dependency be mentioned? I tried to check how it was done for ray transform (with astra) and FFT (with pyfftw), but I could not see a clear pattern...

Also updates in doc, parameters in init, and other things.
@aringh
Copy link
Member Author

aringh commented Jun 15, 2017

I think that all comments are addressed. However, as my previous comment indicates I was not sure of where in the doc to write about the requirements on psutil.

Copy link
Member

@adler-j adler-j left a comment

Choose a reason for hiding this comment

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

Some comments and an answer to the question

----------
step : positive int, optional
Number of iterations between output. Default: 1
print_cpu : bool, optional
Copy link
Member

Choose a reason for hiding this comment

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

Suggestion: scrap the "print_xyz" things and infer it from the fmt strings (perhaps with a rename), e.g.

swap, default is string but anything that evaluates to False (e.g. do a if swap:) means don't print.

Much more simple interface.

Copy link
Member

Choose a reason for hiding this comment

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

But you can keep the old names for the format string parameters, they're good. Add a sentence in the format string docs then that "An empty format string disables printing of XYZ usage".

Copy link
Member

Choose a reason for hiding this comment

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

Otherwise I agree.

Copy link
Member

Choose a reason for hiding this comment

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

I agree with this comment

Raises
------
ImportError
If the package ``psutil`` is not installed.
Copy link
Member

Choose a reason for hiding this comment

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

This is enough imo, no need to spam doc with info in this dependency. In 98% of cases people will get the error and run pip install psutil without even reading the doc.

Copy link
Member

@kohr-h kohr-h Jun 15, 2017

Choose a reason for hiding this comment

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

I'd write a sentence

This callback requires the ``psutil`` package.

in the class doc and just let the error propagate. No Raises section (that is intended for exceptions that we raise, not the system or a third-party package).

def __call__(self, _):
"""Print the memory and CPU usage"""

try:
Copy link
Member

Choose a reason for hiding this comment

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

I prefer propagating the error as is, I.e. no try catch

def __repr__(self):
"""Return ``repr(self)``."""
optargs = [('step', self.step, 1)]
inner_str = signature_string([], optargs)
Copy link
Member

Choose a reason for hiding this comment

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

Missing stuff here

Change inputs to init method, and a number of other minor things.
@aringh
Copy link
Member Author

aringh commented Jun 16, 2017

I hope this should do :-)

@aringh
Copy link
Member Author

aringh commented Jun 16, 2017

Related to this, in the debugging in #1014 we also use pympler to print new objects in memory. I created a callback for this as well in the same spirit as the callback in this PR. Is this of interest?

Copy link
Member

@kohr-h kohr-h left a comment

Choose a reason for hiding this comment

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

Looking good to me

@kohr-h
Copy link
Member

kohr-h commented Jun 16, 2017

Related to this, in the debugging in #1014 we also use pympler to print new objects in memory. I created a callback for this as well in the same spirit as the callback in this PR. Is this of interest?

That kind of functionality definitely useful, but I'm a bit skeptical as to whether that requires a separate callback. The pympler library has quite a bit more to offer, like tracking class instances, print all kinds of statistics, etc..
So there I think it would make more sense write an example that just uses CallbackApply with a user-defined function that prints the interesting stuff.

@adler-j adler-j merged commit 0273f14 into odlgroup:master Jun 17, 2017
@aringh aringh deleted the callback_print_memory branch July 10, 2017 09:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants