-
Notifications
You must be signed in to change notification settings - Fork 268
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
use float32 for images, and validate #1329
Conversation
- Changes Containers for images to specify they should be float32 - call validate() when making schema in HDF5TableWriter
@kosack I added a test testing for all containers defined in I also changed three time ranges to two fields min / max to avoid needless non-scalar fields. |
Codecov Report
@@ Coverage Diff @@
## master #1329 +/- ##
==========================================
+ Coverage 90.92% 91.05% +0.13%
==========================================
Files 179 179
Lines 12164 12192 +28
==========================================
+ Hits 11060 11102 +42
+ Misses 1104 1090 -14
Continue to review full report at Codecov.
|
Thanks, this looks good. I'll just update the ImageExtractor then to produce the right data type |
I think to fix that it's just to change An alternative would be to down-sample it afterward, but that is slower and probably not a good idea. If we rely on any operations being on 64-bit versions, then the answer would change when we re-read DL1 data stored in 32-bits and re-compute things, which is not a good design. |
In TwoPassWindowSum I had to force the conversion (line 903), is this is still needed? I was getting an error if I didn't convert to 32 |
Do you recall what error you were getting? I don't see anything that would have forbidden 64-bits, in ctapipe at least (if it was in prototype, you have your own IO system, and may have defined it as 32 bits) |
@kosack I had to require an rtol of only I guess 1e-4 on waveforms is still plenty, but are you sure we don't want to use float64 internally? |
Ah yes, it is possible that was a ctapipe 0.7 issue....probably that conversion is not needed anymore. As soon as we merge this, I will try take it out to see if nothing happens (as I expect) |
Perhaps, or else we need to think about changing operations to minimize increasing floating point error, which normally you can ignore in 64 bits, but not in 32. |
The worry I have is that if we store a 64-bit version in the Container (and down-sample in the writer), then if we run the analysis without writing a DL1 file, we would have all operations in 64bits, but if we write and read, it woudl change to 32 bits, and thus would give different results. So no matter what, we should write 32-bits to the container in memory, so further algorithms don't expect a higher bit depth |
I'll try to improve the numerical stability of the extractor. |
When using This increases runtime from 430 µs to 450 µs in the test I did. This is acceptable I think, right? Should I push this? |
Sounds good, I say go ahead. Might want to add a comment why it is used, in case somebody changes it back later. |
I'm confused, what does using |
It's just that now that we've switched to 32-bit images, we have to worry more about numerical rounding error, so the way things are summed is important. Though it's not clear which algorithm the Numba version of np.sum uses, but I guess it's more stable based on @maxnoe's test. A naive sum (loop over and accumulate) is usually not the ideal way to do it. Though what we could do is leave extract_around_peak() in 64 bit to avoid this, and just always call it with image, peak = extract_around_peak()
image = image.astype("float32")
peak = peak.astype("float32") but then , each extractor must do that and there is some speed overhead |
you can see now, in 32bit, the tests fail, since the difference after error is around 1e-3, and the tolerance is 1e-7:
Or we just keep it with rtol=1e-4. as already implemented. It's up to yoy! @watsonjj you can decide, since you have to review this anyhow ;) |
I see. I'm surprised at the difference! |
It was so much more difficult back in the days of 32-bit (or even 16-bit!) computers and low-ram! using doubles used to have a large speed and memory impact, so we had to use 32-bit floats for everything, and always think about numerical stability. Anyhow, I think 1e-4 PE is still pretty reasonable, so maybe we don't do anything for now. |
@watsonjj numpy sum is only used for the image sum, not the weighted average. The numpy sum uses an algorithm optimized as a tradeoff between speed and minimizing floating point error, it reduced rounding errors. The other extreme would be to use |
see e.g. https://en.wikipedia.org/wiki/Kahan_summation_algorithm or https://code.activestate.com/recipes/393090/ I guess fsum is slow, and we don't really need that level of precision, so either stick with low-precision (assuming we don't add too many more sample), or use np.sum, which I assume uses something like the kahan algorithm [edit: see below] From the numpy manual:
|
I think an rtol of 1e-4 is still fine for our purpose. There was no particular reason I previously used 1e-7 |
We could also use numba.double to make the accumulator a double bevor assigning to the 32bit array |
@watsonjj why does the loop go over all samples and then do branching to check I replaced this with min / max before the loop and it's now twice as fast. |
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.
Great, works for me
they should be float32
So far doesn't change the computation of the images. Need to ensure ImageExtractor creates float32s.