-
Notifications
You must be signed in to change notification settings - Fork 15
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
Make Atoms() faster via caches #224
Conversation
Caching the method on |
When cached, change in the dataframe is preserved. Therefore, use separate if statements to ensure that the qwargs are stores (Fixes failing test)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good! I made a small commit to fix the failing tests for the Atom
class.
Can you also add the benchmarking you have locally as part of the unittests for the Atoms
class?
Edit: I had to make more than one commit to fix this ;)
This is done using `get_initial_magnetic_moments()`
Thanks for the fix! I will look into how to best do a benchmark as a test case in a system-independent way, probably it's sufficient to time two runs and assert the second time is much faster. I've attached the profile for this problem at the end here. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
@sudarsan-surendralal Can you have another look? I can't reproduce the test failure outside of the CI. |
Pull Request Test Coverage Report for Build 1056610704
💛 - Coveralls |
@pmrv The tests should work now. I also took the liberty to extend your benchmarks a bit. We seem to consistently get a 15x speedup which is awesome. But I can't seem to get a 100x speedup you found in your benchmarks. |
I think my benchmark last time was a more elaborate example creating the atoms via |
@@ -349,15 +353,12 @@ def add_element( | |||
self.dataframe = self.dataframe.append(parent_element_data_series) | |||
else: | |||
self.dataframe.loc[new_element] = parent_element_data_series | |||
if len(qwargs) != 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what broke the tests before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes but not only this. The recent commit b278013 also helped fix the tests
The tests were failing on mac, so I decreased the expected speedup to 10. Otherwise this looks pretty good! I'll still want to understand what is different now to the original changes, but after that I think we can merge this. |
Is there something wrong in the way the speedup is computed (on mac)? In both last cases the threshold was only slightly missed... |
Weird, I changed it to 10, because it ~14 before… :S |
That is what I meant with both last cases. And in both cases it was only slightly below. Therefore, I asked if there is an error on computing the time difference on Mac 😆 |
Yep, I see that now. I'll try to figure it out. |
Suddenly the speed up test worked for a factor x10 on macOS. I still don't know what's going on, but I've made it hopefully more robust by averaging the times and then checking instead of checking in every iteration. |
On my local machine speed ups are in the range x30-40 now, hope that works on CI as well. |
Since the timings are sub-seconds, using ints breaks ;)
The merge commit earlier messed up the tests, so I removed it again via a rebase. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Taking the average of the speedup is definitely a better idea. LGTM!
Fixes #48.
Looking at benchmarks I found that almost all time creating a new
Atoms
object is spent on either i) reading the periodic table from a csv file and ii) loading mendeleev objects from element strings.I think it's reasonable to assume that during the lifetime of a pyiron process neither the periodic table changes on disk nor is the mendeleev database updated and therefore cache both on the module level (i.e. even multiple instances of
Atoms
andPeriodicTable
share one cache). In my benchmark that gives a factor 100 speed up.Caching
convert_element
has some technical nits with it:Atoms
objects, sinceAtoms
has a self-rolled cache like that already; I think we can remove it now, but I want to double check with you)Atom
some kind of singleton.Atoms.species
, in the cached case this would not be called. However all call sites ofconvert_element
also callset_species
later in the code path, so nothing is lost. It's still messy to rely on this, but I feel this is a separate refactor.pyiron_atomistics/pyiron_atomistics/atomistics/structure/atoms.py
Line 661 in e69d6df