-
Notifications
You must be signed in to change notification settings - Fork 10
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
gh-487: reorder alms in _generate_grf to glass ordering #533
base: main
Are you sure you want to change the base?
Conversation
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.
See #530 for the mypy failure.
glass/fields.py
Outdated
@@ -388,6 +388,8 @@ def _generate_grf( | |||
# sample real and imaginary parts, then view as complex number | |||
rng.standard_normal(n * (n + 1), np.float64, z.view(np.float64)) | |||
|
|||
z = np.asanyarray(healpix_to_glass_spectra(z)) |
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.
Should the functions return a numpy array instead?
Thanks for taking this on @Saransh-cpp! I think we crossed wires with two similar but separate things going on at the same time:
This switch is fully internal and there are no observable changes to anything from the outside. The way our After the change, our internal generation would keep The goal of this internal reordering is that we will be able to split everything up in blocks of After this internal reordering, we still need to send our |
Can you ask me again for a review once the science is worked out? I'm not fully sure what is going on here |
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.
@ntessore could you please take a look at this again and let me know if this is the right direction?
multalm
is definitely slower now because of the dynamic indexing. It would really benefit from using ragged arrays for accessing alms in a NumPy-like way, but we can discuss that in the JAX project. Just using plain NumPy arrays would eat up extra memory because of the matrix structure.
glass/fields.py
Outdated
n = len(bl) | ||
for d in range(n): | ||
indices = [] | ||
for m in range(d, n): | ||
# dynamically calculate indices | ||
index = m * (m + 1) // 2 + d | ||
indices.append(index) | ||
|
||
if indices: | ||
out[indices] *= bl[: len(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.
The function now assumes that the incoming alm
s are in the order -
[00, 10, 11, 20, 21, 22, 30, 31, 32, 33, ...]
Therefore, it now multiplies alm
with bl
in the following way -
bl := [1, 10, 100, 1000]
[0, 10, 20, 30] * bl → [0, 100, 2000, 30000]
[11, 21, 31] * bl[:3] → [11, 210, 3100]
[22, 32] * bl[:2] → [22, 320]
[33] * bl[:1] → [33]
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.
I don't think that's right: bl[0]
is to be multiplied with alm
where l=0
, so just alm[0:1]
. bl[1]
is to be multiplied with alm
where l=1
, so alm[1:3]
, and so on.
Long version of the loop:
stop = 0
for ell in range(n):
start, stop = stop, stop + ell + 1
alm[start : stop] *= bl[ell]
Short version of the loop:
for ell in range(n):
alm[ell * (ell + 1) // 2 : (ell + 1) * (ell + 2) // 2] *= bl[ell]
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.
Ah, I got the multiplication wrong! That's why I was confused about why we are switching to this order. Thanks for the correction!
glass/fields.py
Outdated
@@ -402,6 +410,8 @@ def _generate_grf( | |||
if j is not None: | |||
y[:, j] = z | |||
|
|||
alm = np.asanyarray(glass.glass_to_healpix_spectra(alm)) # type: ignore[arg-type] |
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.
IIRC, the alm
s should be converted back to healpix ordering before being passed into hp
functions. I have used the glass.glass_to_healpix_spectra
because it does the ordering in the same way.
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.
If it does the reordering in the same way, that's "by accident", and we should not bind ourselves to an unrelated function that happens to do the same thing.
For reordering the alm:
Have:
Want:
In the first array, the element with indices
def glass_to_healpix_alm(alm):
n = inv_triangle_number(alm.size) # we need that function back :)
ell = np.arange(n)
out = []
for m in ell:
out.append(alm[ell[m:] * (ell[m:] + 1) // 2 + m])
return np.concatenate(out)
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.
Thanks! Should I just revert #527 so that we don't use functions named for spectra
inside functions meant for alm
?
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.
Maybe we should add the private function back in, then make two helper functions with clear purpose (and error msg) instead of using it directly?
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.
Sounds good! I will wrap that up in another PR, which can be merged before this one to make everything cleaner.
We should really set a timeout on the examples test 😬 |
ee5d9d2
to
86b2101
Compare
inp = np.array([11, 22, 21, 33, 32, 31, 44, 43, 42, 41]) | ||
out = glass.fields._glass_to_healpix_alm(inp) | ||
np.testing.assert_array_equal( | ||
out, np.array([11, 22, 33, 44, 21, 32, 43, 31, 42, 41]) | ||
) |
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.
Let's make this more obvious
inp = np.array([11, 22, 21, 33, 32, 31, 44, 43, 42, 41]) | |
out = glass.fields._glass_to_healpix_alm(inp) | |
np.testing.assert_array_equal( | |
out, np.array([11, 22, 33, 44, 21, 32, 43, 31, 42, 41]) | |
) | |
inp = np.array([00, 10, 11, 20, 21, 22, 30, 31, 32, 33]) | |
out = glass.fields._glass_to_healpix_alm(inp) | |
np.testing.assert_array_equal( | |
out, np.array([00, 10, 20, 30, 11, 21, 31, 22, 32, 33]) | |
) |
Description
The PR reorder alms in
_generate_grf
to glass ordering before operating on them and then reorders it back to healpix before passing into the yield function.The code works but it is slowing down examples instead of making them faster. I think I am doing something wrong here. @ntessore could you look at this and point me in the right direction?
Fixes: #487
Changelog entry
Checks