Skip to content
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

Add the capability to do adjoint transforms #633

Draft
wants to merge 14 commits into
base: master
Choose a base branch
from
Draft

Conversation

mreineck
Copy link
Collaborator

This is a first outline how I propose to add adjoint transforms; it is mainly meant as a basis for discussions and measurements. The computation of the actual adjoint is completely untested yet, but the standard functionality should still be OK, as far as my tests show.

@ahbarnett, @DiamonDinoia please let me know your thoughts on this one!

@mreineck
Copy link
Collaborator Author

Just to be clear: at this point, there is no interface support for the new functioality. I just want to show which kind of impact the new feature has on the existing implementation.

@mreineck
Copy link
Collaborator Author

I've added the C and Python interfaces, as well as basic Python unit tests.

@mreineck
Copy link
Collaborator Author

Test failures seem to be "near misses" in adjoint type 3 transforms. No idea why that direction should be less accurate, and why it only happens in some of the tests.
This needs more investigation, but the approach seems to work well in principle.

@mreineck
Copy link
Collaborator Author

mreineck commented Feb 19, 2025

Implements #571 and #566 (on CPU).

…s. Perhaps 1e-6 is just a bit too close to the machine epsilon for single precision
@mreineck
Copy link
Collaborator Author

I think this is ready for "technical" review. If there is agreement that the change is desirable, I can try to

  • provide more language-specific interfaces
  • document the new function

Copy link
Collaborator Author

@mreineck mreineck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a few explanatory comments

@@ -20,7 +20,7 @@
strt = time.time()

#plan
plan = fp.Plan(1,(N,),dtype='single')
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is unrelated to the PR, but without it, CI simply fails. I don't know why this hasn't caused issues so far.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems because we removed the conversion for real dtypes in https://github.com/flatironinstitute/finufft/pull/606/files

@@ -34,7 +34,7 @@

# instantiate the plan (note n_trans must be set here), also setting tolerance:
t0 = time.time()
plan = finufft.Plan(nufft_type, (N1, N2), eps=1e-4, n_trans=K, dtype='float32')
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is unrelated to the PR, but without it, CI simply fails. I don't know why this hasn't caused issues so far.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching this, it seems all the *f.py examples(in python/finufft/examples) should change according to PR606? otherwise the check is_single_dtype(dtype)

is_single = is_single_dtype(dtype)
will fail.

@@ -86,6 +120,19 @@ def test_finufft3_plan(dtype, dim, n_source_pts, n_target_pts, output_arg):

utils.verify_type3(source_pts, source_coefs, target_pts, target_coefs, 1e-6)

# test adjoint type 3
plan = Plan(3, dim, dtype=dtype, isign=-1, eps=1e-5)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm increasing eps from 1e-6 to 1e-5 here, because I get occasional failures with single precision otherwise. Given that 1e-6 is uncomfortably close to machine epsilon, I'm not too worried about this change.

@@ -154,7 +154,7 @@ def verify_type1(pts, coefs, shape, sig_est, tol):

type1_rel_err = np.linalg.norm(fk_target - fk_est) / np.linalg.norm(fk_target)

assert type1_rel_err < 25 * tol
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switching from assert to np.testing.assert_allclose here, because the latter will provide more information in case of failure, which speeds up debugging a lot.

}
}
}
#endif
#else
p->fftPlan->execute(); // if thisBatchSize<batchSize it wastes some flops
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs discussion: how do we want to deal with this situation? The trick used here is nice and simple, but it will make the adjoint call slower than the forward one.

@ahbarnett
Copy link
Collaborator

ahbarnett commented Feb 25, 2025 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants