-
Notifications
You must be signed in to change notification settings - Fork 667
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
[WIP] Cythonizes GROParser & GROReader very minimally #2227
Conversation
In your email you said
The code does not seem to run on the CI (AppVeyor fails) but taking for a moment that you got your changes to build locally, it is interesting that the simplest approach of just wrapping the code in cython does not change much. Do you know where the Python code spends most of its time, i.e., what is the performance bottleneck? Did you profile the Python GRO parser (e.g. with line_profiler) to find out? This will give you a better idea of what needs optimizing. (Also, eventually the PR needs to build on the CI and we need to figure out if we can move the cython code to the lib module - might be tricky for parsers because code in lib is supposed to be independent of MDAnalysis things such as topologies and AtomGroups. But first explore and see if there are some obvious ways to speed up the parser.) |
@Fenil3510 , I remembered that a while ago PR #1862 was started with the goal to leverage the chemfiles python interface for some trajectory formats. They don't support all formats but a a fair number, at least as coordinate "Readers/Writers". Not sure if they can be used as topology "parsers", too. chemfiles contains a GRO reader/writer (written in C/C++ but apparently based on VMD's molfile plugin). I don't know how seamlessly chemfiles can interact with MDAnalysis. We didn't have this in our project description, partly because the PR stalled, partly because it is complicated enough to understand MDAnalysis and we don't necessarily want you to having to spend time learning another library that we ourselves know little about. However, I feel that this should be mentioned so that you have a better idea of what else is going on in MDAnalysis, as potentially related to your project. If you or anyone else has opinions, please discuss them here. |
Thanks for the suggestions @orbeckst. Yes, I just wrapped the code in Cython. I'll see why tests are failing. I'll look into line_profiler to find out what's to be done to speed it better. |
@orbeckst I think the problem with adopting C++/C for reading ascii is it then becomes very hard (for python devs) to patch. Currently our stuff bends over backwards to read everything because we can patch it. @Fenil3510 I think this might be a good place to get ideas for how to do quick ascii i/o: http://wesmckinney.com/blog/speeding-up-pandass-file-parsers-with-cython/ Then obviously finding the corresponding cython code in the pandas repo (if they still use Cython). |
Hey, chemfiles dev here! So PR #1862 have stalled a bit, but I just finished the release of version 0.9 of chemfiles so I'll try to back to it. It was basically working, just needed a bit of documentation. It might take a bit of time as I am currently writing my thesis ...
It should be easy to convert from chemfiles Topology class to MDAnalysis version. Current version of #1862 only uses the coordinates and throw away the topology, but I could update it to include chemfiles as a topology reader.
We actually have our own implementation of GRO format, not based on VMD molfiles. It lives here: https://github.com/chemfiles/chemfiles/blob/master/src/formats/GRO.cpp.
We try to write readable and easy to modify C++ code in chemfiles, and modern C++ is closer to Python than old school C. But there is always a barrier to overcome when contributing to a project in a different language. |
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.
The other obvious thing that can be done is cython -a c_GROParser.pyx
and look for the yellow lines in the html output for expensive Python overhead calls.
One of us will probably do that eventually when reviewing the PR since it is so straightforward.
+1 to at least check this; |
Codecov Report
@@ Coverage Diff @@
## develop #2227 +/- ##
===========================================
+ Coverage 89.3% 89.65% +0.34%
===========================================
Files 156 172 +16
Lines 19407 21414 +2007
Branches 2783 2779 -4
===========================================
+ Hits 17332 19198 +1866
- Misses 1473 1620 +147
+ Partials 602 596 -6
Continue to review full report at Codecov.
|
@tylerjereddy @orbeckst. I profiled the code of GROParser line by line and checked what takes the most time. It was obviously the looping part, so I thought to make the for loop cythonized. I read here that cythons access to numpy array is much faster for indexing than the regular array. I made the changes accordingly, but I get an improvement of only 40ms on average, ie. actual average time reduces from 710 to 640ms. I still have to dig into |
cdef np.ndarray[np.int32_t] resids | ||
cdef np.ndarray[object] resnames | ||
cdef np.ndarray[object] names | ||
cdef np.ndarray[np.int32_t] indices |
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.
better to use typed memoryviews here vs. the old buffer syntax
# 1) find large changes in index, (ie non sequential blocks) | ||
diff = np.diff(wraps) != 1 | ||
# 2) make array of where 0-blocks start | ||
starts = np.hstack([wraps[0], wraps[1:][diff]]) |
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.
starts
is initialized here without prior type declaration
@tylerjereddy numpy functions |
You can use constructs like |
NumPy also has a C API |
@tylerjereddy , I see. I will change it to
I'd be grateful for any suggestions. |
The current cythonization is in the |
@orbeckst as you said
I was wondering what is the reason to move cython code to |
When you look at
I was expressing the desire to do the same thing for parsers but also expressed that I kind of doubted that this could be done easily. In short: Moving GROParser to |
@orbeckst thankyou for the information. Yes, the intermediate Python file can be removed I believe, I had kept it to play safe. Now that I've familiarized with Cython modules, looks like it shouldn't cause an issue, I'll make the changes soon. |
Had some tests failing in |
Hmm, test fails due to a numpy merge here. Some changes in pickling. |
cdef object[:] resnames | ||
cdef object[:] names | ||
cdef int[:] indices | ||
cdef long long[:] starts |
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.
pretty sure we just need ints here too
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.
Travis was failing with int
and expecting it to be long long
as I remember. I'll double check.
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.
np.where
returns a np.int64 but mac integer is 32-bit as the same issure here, I've type-casted the arrays inplace with np.int32
and works with int
now.
@Fenil3510 don't worry about those failures. What are loading times like with these changes? |
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.
@Fenil3510 don't worry about those failures. What are loading times like with these changes?
The current cythonization is in the GROParser ie. parse function to be specific. Profiling the parse function separately gives an improvement of 2.5 - 3x on any file (files tested 2MB to 17 MB). But the overall reading from mda.Universe()
shows a very less gain. This is because parsing takes 6% of the total time. So this is surely not the bottleneck. I chose GROParser for getting started. I will be looking into GROReader for some time and probably find out the bottleneck. Haven't had time to profile it further. I'll be doing this over a couple of days.
cdef object[:] resnames | ||
cdef object[:] names | ||
cdef int[:] indices | ||
cdef long long[:] starts |
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.
Travis was failing with int
and expecting it to be long long
as I remember. I'll double check.
@Fenil3510 could you please benchmark the parser on its own and full universe creation with the GRO files in the vesicle data set https://www.mdanalysis.org/MDAnalysisData/vesicles.html ?
and from MDAnalyisData.datasets import fetch_vesicle_lib
dataset = fetch_vesicle_lib()
grofiles = dataset.structure # should be 3 GRO files These are fairly big systems (see |
@orbeckst sorry for the delay, have my exams running parallelly.
Working on cythonizing the readers will definitely help increase gains. |
@Fenil3510 many thanks, very useful and encouraging! Good luck with your exams! |
Sure, I will start working on this after May 9th. |
I merged current develop, hopefully the tests will all pass then. (Apologies – it made the diff noisy.) |
I've been busy lately, I'll get back on this pretty soon. |
Not sure why the old numpy test (NUMPY_VERSION=1.10.4) fails, Job #1030.5
I am restarting the job... maybe it's a conda glitch??? |
Looks like an issue with Travis's Numpy version. All other PR's are failing the same test. |
Codecov Report
@@ Coverage Diff @@
## develop #2227 +/- ##
===========================================
- Coverage 89.66% 89.65% -0.02%
===========================================
Files 172 172
Lines 21398 21414 +16
Branches 2785 2779 -6
===========================================
+ Hits 19186 19198 +12
- Misses 1616 1620 +4
Partials 596 596
Continue to review full report at Codecov.
|
I'd need some help here. I declared static types in GROReader( |
Hey Fenil
Thanks for sticking with this. I think it might be the reader isn’t getting registered when the module imports... can you import mdanalysis and check mda._READERS (or whatever that dict is called....)
…
On Jun 17, 2019 at 15:21, <Fenil Suchak ***@***.***)> wrote:
I'd need some help here. I used types in GROReader for some variables and converted it into Cython file(This method worked with GROParser). But too many tests are failing for this commit, while I can build the universe with MDAnalysis.datasets with this commit and gains 3-4x gains but tests are failing as I can't access position method of Atom class which is weird. I'm unable to trace the exact reason for this, any help would be much appreciated.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub (#2227?email_source=notifications&email_token=ACGSGB74DXFXM5SXWRIRLYTP26MWJA5CNFSM4HBZWWKKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODX3KKEY#issuecomment-502703379), or mute the thread (https://github.com/notifications/unsubscribe-auth/ACGSGBY6QEPGCNXKIBLD5QDP26MWJANCNFSM4HBZWWKA).
|
@@ -116,6 +116,10 @@ | |||
from ..core import flags | |||
from ..exceptions import NoDataError | |||
from ..lib import util | |||
cimport cython | |||
@cython.boundscheck(False) # Deactivate bounds checking |
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.
these decorators aren't doing what you are expecting here, they won't apply to the whole file. I think they're probably just modifying the Timestep object.
You probably need to decorate the class method directly
@Fenil3510 the reader class wasn't getting added to |
Yeah, it's failing silently even though there is an except statement to raise |
hey @Fenil3510 I played around with writing a Cython XYZReader function here: https://gist.github.com/richardjgowers/dbec308c364aae8b9ca84e8e22171823 There's no error checking (this would need to be added!) but it seems to go pretty fast if you want some ideas. |
Changes made in this Pull Request:
PR Checklist