Replies: 28 comments 2 replies
-
Yes this is an excellent solution I think. I knew I changed the name to avoid possible (if unlikely) trademark issues. Also this toolbox is readily accessible via Matlab, although I haven't added examples yet, so I don't want to make people this is just for Python users. |
Beta Was this translation helpful? Give feedback.
-
Dear scivision, I put some more thought in the way the data storing could be improved. Currently, the reading of a complete a Multi-GNSS RINEX file with 24h@30s takes more than 5 minutes with georinex using all 4 cores of my i7-7800. Our software NAPEOS(FORTRAN) needs 2 seconds to do this on only 1 core. Compared to this difference, my original proposal will only give a minor speed boost. The main issue I see with georinex, is the fact that you are storing every single epoch in an xarray dataset. xarray is very powerful, but writing it is comparably slow. Neither xarray.concat nor xarray.merge should be used more often than necessary. In my humble opinion they should not be used here at all. I propose to use an intermediate data structure to store all the data first and then convert this structure at once into an xarray. In NAPEOS we use linked lists: We allocate an array with one linked list per satellite. These linked lists are then appended for every epoch. Every element of the linked lists holds the time epoch and the respective signals as they are listed in the header. When reading, we assume that every new epoch comes later in time than the previous and can be simply appended to the end of the list. This gives a huge speed advantage. (It actually checks that it is the last epoch and finds the correct location in case it is not, but I have never seen this logical triggering) I understand that this might end up in a quite a fundamental change in your software, but all users will thank you for saving them time. Just contact me in case you have any questions. Best Regards |
Beta Was this translation helpful? Give feedback.
-
Thanks Volker. Line profiling shows that per-epoch time conversion is penalized almost as much (within factor of 2) by the Numpy text=>ndarray conversion as xarray.concat I suspect Numpy can be very much more efficient if the text is converted all at once, or at least in larger blocks--this "should" take place at C-like speeds when Numpy is given a big block of text to crunch. When I think to why I created this package, it was because even some leading scientists were processing the RINEX ASCII over and over taking enormous amounts of time. The idea of this program was to do one-time conversions to NetCDF4/HDF5 and then work with that data. When I showed them the enormous speed boosts of working with hemisphere-wide GNSS networks over days of time, they were sold and can do much better science now with HDF5 one-time conversion of RINEX. So yes having a 2-core-second conversion of a 24 hour file vs. 20 core-minutes for the same file is important in general, even if it's for a one-time conversion, when you have millions of files to convert, and growing rapidly. Should the idea instead be to add HDF5 output to NAPEOS if not already there? The idea being to be able to do tomographic processing of data, scaling from thousands to millions of receivers at a time (out of core processing, done from the HDF5 files). To speed this up a lot more (beyond 10's of percent here and there) may require more advanced measures like Cython. |
Beta Was this translation helpful? Give feedback.
-
I have the feeling we are not yet talking about the same. I'll try to clarify: In your last answer you mentioned the use of numpy.genfromtext. In fact I am skeptical that this is the optimal method to read the data. However there is a reason why I did not bring it up yet: My profiler shows that numpy.genfromtext is not the part were georinex looses the most time. For large RINEX files (multiple MBs) like the ones I am using, more than 90% of the time is lost with concat/merging. So I focused on the latter. In general, I think the use of NetCDF4/HDF5 for GNSS data is a very good idea. The output of georinex is very easy and quick to access. However, I think the way you are creating it, by running concat/merge every iteration, is not optimal. Above you said:
This is a right thing to do and it is how the georinex output looks like, but is is not the way it works internally. In fact, you are doing an epoch-by-epoch conversion to NetCDF4/HDF5. |
Beta Was this translation helpful? Give feedback.
-
Do you have a public example of a large RINEX file you'd like to benchmark?
This could be even faster and significantly cleaner/simpler to implement than the linked lists. By one-time I actually meant off-line, that is, convert say 10,000 RINEX files before the human actually works with them. I don't care as much about RINEX 2 files as our large experimental data is all RINEX 3, so RINEX 2 is only for legacy data we didn't bother converting previously |
Beta Was this translation helpful? Give feedback.
-
Dear scivision, About public RINEX data: This command will get you the data of one of our best stations (Cebreros, Spain). Note: These files are all Hatanaka compressed and gunziped. wget ftp://gssc.esa.int/gnss/data/daily/2018/200/CEBR00ESP_R_20182000000_01D_30S_MO.crx.gz Like I said before, reading this file NAPEOS completely takes a few seconds. Georinex takes 1.6 minutes to read only GPS. About Rinex2: About your code: |
Beta Was this translation helpful? Give feedback.
-
OK, checkout the latest release v1.6.1. It is more than 10x faster overall by preallocating Numpy array and only at the very end, after the big loop is done xarray.Dataset is created. |
Beta Was this translation helpful? Give feedback.
-
Hey, I am glad to see that you could make some use of my advice. I can confirm the significant speed boost of the software. Good Job! As discussed, it is all about the intermediate data structure to avoid any concat or merge. I see you decided to go straight for a preallocated numpy array, without a list. Telling by your comments in the code, I understand that you are already aware of the issues of the allocation:
Both issues can be avoided, if you put the data into a (linked list) and allocate the numpy array based on counters. Thanks for this update. You are saving all users a lot of time! |
Beta Was this translation helpful? Give feedback.
-
Yes I felt that doing a fully-allocated Numpy array was simpler to debug, and that lists probably would not be faster than this, although lists would be better for memory somewhat. With regard to obstime2, this is taking only 10 milliseconds or so, and the operating system caches this file so it's not a significant penalty, less than 1% |
Beta Was this translation helpful? Give feedback.
-
In the latest version obstime2 takes much longer than 10 ms. In my case it is 600 ms (will1190.zip 24@30s). This is now significant, since the total processing time dropped to 4.5sec. Besides, I am a bit confused with the new Talk to you soon! |
Beta Was this translation helpful? Give feedback.
-
I had to read/discard using _skip because when using TextIO streams (for seamless streaming of ZIP/Z/GZ/Hatanaka) seeking doesn't work, you just have to read and discard it seems. I did not microoptimize the skipping. Yes I am still thinking about lists during looping instead of the preallocation that necessitates reading the file twice, since that's now expensive as you note. |
Beta Was this translation helpful? Give feedback.
-
preallocation without reading the file twice is enabled in v1.6.6. Setting There are measures that can be added for extremely large files (e.g. 50 Hz) that would make the preallocation smarter (reduce RAM usage) if this becomes an issue. |
Beta Was this translation helpful? Give feedback.
-
Thanks again for focusing on the speed boasting. Your smart allocation concept is interesting. |
Beta Was this translation helpful? Give feedback.
-
Great, v1.6.7 attempts to reduce RAM usage by reading a few dozen lines of data to better estimate needed RAM. It will also automatically shut fast=False if it can't detect properly (mangled, non-standard file). |
Beta Was this translation helpful? Give feedback.
-
Hey, is there a reason why you only implemented this for RINEX2 and not for RINEX3? |
Beta Was this translation helpful? Give feedback.
-
@VOMAY just a lack of time to do so, waiting for someone to ask 👍 |
Beta Was this translation helpful? Give feedback.
-
I am bumping up a really old issue here but as @VOMAY mentioned, the reading speeds are relatively quite slow, and this thread highlights the changes incorporated for a speed up for RINEX2. Here is my improvement for RINEX3. (it does achieve the same speedup you observe in RINEX2) https://github.com/anand-satnav/georinex/tree/citius I cannot make a pull request since there are a few things I changed which breaks compatibility. I mainly did it for personal use in my research.
A measurement must be unique to a satellite system. A GPS L1C measurement is not the same as a GLONASS L1C measurement. The user may want to separate the two data sets for independent analysis and processing. I could go into further details but I think it deserves a separate thread. Also indexing/re-indexing operations are faster as integers rather than a string, but that will only make a difference in very large data-sets (>1GiB)
I chose to defer the Dataset creation and merge operations to the very end rather than merge as you iterate the file. This is a huge time saving as each xarray.Dataset merge operation is pretty expensive and you will be better off with merging a complete block of measurement rather than merging each measurement epoch-wise. I can have another discussion related to more enhancements, improvements and new features if you guys are interested. I believe this software has potential to do a lot more than what it can currently and I would be happy to help. |
Beta Was this translation helpful? Give feedback.
-
Thanks @anand-satnav for your input. I cannot speak for @scivision , but I appreciate your input a lot. I know a lot of people, who would like to use this tool, but are waiting for a quicker RINEX3 implementation. I am in close contact with the IGS infrastructure working group and was told RINEX2 is not around for much longer. |
Beta Was this translation helpful? Give feedback.
-
@VOMAY good to hear that it will be useful. Give my variant a try and let me know if that is alright. |
Beta Was this translation helpful? Give feedback.
-
@anand-satnav I dislike how you handle data variables names. Why would you use a hyphen in a variable name. calling >>> obs.E-C1C
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/xxx/opt/anaconda3/envs/ana/lib/python3.7/site-packages/xarray/core/common.py", line 179, in __getattr__
(type(self).__name__, name))
AttributeError: 'Dataset' object has no attribute 'E' True, C1C for GPS, GAL and GLO are all signals different. But splitting them in georinex them won't reduce this confusion, only add more data variable names. Splitting the PRN in constellation letter and the integer value and storing them separately is an option. I have seen it in various GNSS softwares. Storing the PRNs as integers is helpful for filtering them with mathematical operations, e.g. There is one thing I miss, which neither of your implementations allows: A compact way to slice the dataset by constellation. Eind = obs.sv.to_index().str.startswith('E') # returns a simple Numpy Boolean 1-D array
Edata = obs.isel(sv=Eind) # any combination of other indices at same time or before/after also possible This works of course, but the command is to long for such a simple command. Can we have an easy method to do this? |
Beta Was this translation helpful? Give feedback.
-
@VOMAY Great to hear you tired it out and happy with the speed. Hmm , splitting constellation letter from sv-no is an idea I can try. Maybe add it in as another co-ordinate. That can solve both your problems, slicing the dataset by constellation and number of data variable names. Will implement, benchmark and update you |
Beta Was this translation helpful? Give feedback.
-
I looked into my orbit comparison plotting tool, which is organized in a pandas DataFrame. It's multi-indexed as follows: |
Beta Was this translation helpful? Give feedback.
-
@scivision May I ask you again to look into this? I think @anand-satnav made great progress here already. |
Beta Was this translation helpful? Give feedback.
-
I see anand is still working on the citrus branch. I may have time at year-end to look at this and at least make it an optional module e.g. |
Beta Was this translation helpful? Give feedback.
-
Dear @anand-satnav, dear @scivision Best Regards |
Beta Was this translation helpful? Give feedback.
-
@scivision I really didn't write citius branch to be compatible with the existing obs3. I have broken a lot of functionality. Just needed it for my use. Need to repair all that . I think its better to branch out a new one from the existing obs3 and implement my changes. Dunno. @VOMAY |
Beta Was this translation helpful? Give feedback.
-
Yes after refactoring obs2 previously, I also saw that sticking with lists and dicts until closer to the end also generally gave noticeably better performance. I think I originally came into the task biased by earlier work with large homogeneous datasets that are a natural fit for ndarray, whereas Rinex processing in Python is heterogeneous enough in some senses to be faster and better memory-wise in native Python datatypes Thanks! |
Beta Was this translation helpful? Give feedback.
-
What do you guys think of this: #59 |
Beta Was this translation helpful? Give feedback.
-
Dear scivision,
I ran a profiler on georinex (why did you change the name), while reading a 24h@30s Multi-GNSS Rinex 3 (LEICA GR25) file and found that the xarray.merge is responsible for >90% of the time consumption. This is not a surprise, but annoying nonetheless. I checked the code and saw that you are using xarray.concat instead of xarray.merge for single constellation cases. So I made a test:
As you can see, reading GPS+Galileo at once takes about 50% longer than doing them one after another. This shows that concat is substantially quicker than merge. So here is my proposal:
Create one xarray dataset for each constellation and merge them only once at the very end. I am optimistic that this will allow at least 50% of time savings. Probably even quicker would be to use one xarray dataset per satellite and again merge them only once!
Best Regards
Volker
Beta Was this translation helpful? Give feedback.
All reactions