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

Templatize spreadinterp and more cleanups #567

Merged
merged 27 commits into from
Oct 22, 2024

Conversation

mreineck
Copy link
Collaborator

@mreineck mreineck commented Sep 24, 2024

This is a massive change to spreadinterp.cpp, both reordering the functions in the file to avoid forward declarations, and templatizing everything in there.

I'd be happy to get this in as soon as possible, but I appreciate that this will be very hard to review...

@mreineck
Copy link
Collaborator Author

There are now no more doubly-compiled sources in the library (there are still doubly-compiled tests however). The current state is not pretty, since I had to make a few compromises to arrive at this point, but from now on things should improve again.
Still, before continuing, I'd like to have some feedback whether this has a chance to be accepted.

@mreineck
Copy link
Collaborator Author

Current test failures seem to be related to network problems on the CI servers ... they failed to download FFTW.

@mreineck mreineck marked this pull request as ready for review September 25, 2024 18:45
@mreineck
Copy link
Collaborator Author

mreineck commented Sep 26, 2024

OK, I'll stop myself here and wait for the review.

Don't get me wrong: there is still much to be done to really gather the benefits of this restructuring ... but all these subsequent changes will be more or less localized, and they will be much more fun than it was getting to the current state.

My hope would be that this can be merged before any other of the open PRs, because incorporating any change on master into this PR will be extremely painful. Of course I'll be happy to help with adjusting the conflicts I cause in the other PRs!

src/finufft_core.cpp Outdated Show resolved Hide resolved
@mreineck
Copy link
Collaborator Author

mreineck commented Oct 18, 2024

A few answers to questions from the Google doc:

why pointer args sometimes became std::vector(T) &thing instead of T* thing ? Is this just to declare const?

No, the reason is to let C++ do as much memory management for us as possible. Whenever we have a vector, C++ will clean it up for us when it goes out of scope (or when its surrounding object is destroyed) -> no need to worry about free etc.

But we can't do this in all places. Sometimes we store pointers in the plan structure that have been provided by the caller. That means we must not do any memory management on them, and we cannot use vectors for them (unless we copy all the contents, which we don't want to do).

Is nullptr better than NULL ? (finufft_core.cpp)

Definitely yes, but the semantic differences are subtle. When writing modern C++ (since C++11), always use nullptr. I can dig out some references if anyone is interested in the details.

[Edit: intuitive example in https://en.cppreference.com/w/cpp/language/nullptr]

@mreineck
Copy link
Collaborator Author

I'll add a comment to finufft_core.cpp explaining the strange looking declarations with the different types.
They can be avoided by moving the templates into a header file instead of a cpp file. I usually do this, but it can be a burden on compile time, so I tried to be a bit more conservative here.

@DiamonDinoia
Copy link
Collaborator

Yes, that was kind of a bonus change, since I was touching all those lines anyway. I should probably have left that out and done it later.

It also fixes: #547

@DiamonDinoia
Copy link
Collaborator

DiamonDinoia commented Oct 18, 2024

OK, you are right: simple_interfaces.cpp looks more daunting now, but mostly because of the long type names: CPX -> std::complex<float/double>. I can introduce shortcuts for those ... not sure how much better that makes things, but I'll experiment a bit.

In my projects, I usually define a namespace types with something like:

namespace finufft{
namespace types{
using f32 = float;
using f64 = double;
using i32 = ...
using u32 = ... 
... 
}
}

and so on.

Then in .cpp files I just do using namespace finufft:types.

For public facing code I might define a shorthand for the namespace using finufft::types=FI so that I can do something like FI::i32. Something that still is intuitive and lets the reader understand the types.

For disclosure:
I have some hatred for keywords like single, double, int, long. My humble option is that they should have never existed.

src/finufft_core.cpp Outdated Show resolved Hide resolved
Copy link
Member

@lu1and10 lu1and10 left a comment

Choose a reason for hiding this comment

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

Thanks, it looks great.
With a quick scan, I only find several sanity check things.

  1. FINUFFT_PRECISION_DEPENDENT_SOURCES seems not used in cmake, the comments or cmake code with FINUFFT_PRECISION_DEPENDENT_SOURCES might be removed.
  2. Since src/finufft.cpp is renamed to src/finufft_core.cpp, any code comments or documentation under docs/ referring to src/finufft.cpp may be changed accordingly; for the removed file utils_precindep.cpp, docs still mentions next235even in utils_precindep.cpp, now it's moved to utils.cpp
  3. The guru interface source is now defined with template instantiation in src/simpleinterfaces.cpp, while in include/finufft_eitherprec.h we still mention it's in finufft.cpp. Though the filename simpleinterfaces.cpp may hint the users that the guru interface source may not be defined in simpleinterfaces.cpp.

@ahbarnett
Copy link
Collaborator

ahbarnett commented Oct 19, 2024 via email

Copy link
Collaborator

@ahbarnett ahbarnett left a comment

Choose a reason for hiding this comment

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

Thanks for this nice and big piece of work, Martin!

I must admit that de-macroizing and removing all the fwd-declarations looks a lot more maintainable (for the most part, apart from the new boilerplate to wrap the new class methods as standard functions, plus the , instances of everything - is this just so they are compiled into the lib?)
Overall compile time is longer (maybe factor of two?). But it is all going to be simpler in the end.

{Following a little out-of-date due to email chats:)
Since you are now becoming a major contributor, one piece of feedback would be to add code comments to explain the rationale for various decisions/changes. This is at the micro but also macro-level. We cannot read your mind, and it's easier if you err on the side of too many rather than too few explanations. You could add overall plan to docs/devnotes.rst too. But there is a big-picture plan implicit in your PR (eg: defs.h and FLT are now only for tests, and will go away soon) that we all need to have "on paper", to understand it, and figure out what happened post-hoc! It also helps you to delegate to us what needs doing.

My suggestions are optional and mostly just questions to understand stuff (I am no templating/class expert).

Thanks, Alex

makefile Outdated Show resolved Hide resolved
makefile Outdated Show resolved Hide resolved
makefile Outdated Show resolved Hide resolved
fortran/finufftfort.cpp Show resolved Hide resolved
include/finufft/defs.h Outdated Show resolved Hide resolved
src/spreadinterp.cpp Show resolved Hide resolved
src/spreadinterp.cpp Show resolved Hide resolved
src/spreadinterp.cpp Show resolved Hide resolved
src/spreadinterp.cpp Show resolved Hide resolved
src/spreadinterp.cpp Show resolved Hide resolved
mreineck added a commit to mreineck/finufft that referenced this pull request Oct 19, 2024
@mreineck
Copy link
Collaborator Author

I don't know why the Windows test fails. Is it known to have intermittent problems?

@DiamonDinoia
Copy link
Collaborator

I don't know why the Windows test fails. Is it known to have intermittent problems?

Due to the number of test we run. Sometimes the docker env messes up and tests do fail for no apparent reason. In these cases, a re-run usually fixes it. If it does not then it is likely to have a problem in the code.

@mreineck
Copy link
Collaborator Author

This was an actual unit test failure, i.e. the error of a transform was higher than the tolerance. I don't think this is due to docker issues; it could be due to non-repeatable random numbers though

@lu1and10
Copy link
Member

I don't know why the Windows test fails. Is it known to have intermittent problems?

Due to the number of test we run. Sometimes the docker env messes up and tests do fail for no apparent reason. In these cases, a re-run usually fixes it. If it does not then it is likely to have a problem in the code.

I don't know why the Windows test fails. Is it known to have intermittent problems?

this seems relate to #516
@ahbarnett fixed with finufft*d_test.cpp, the many finufft*dmany_test.cpp: test may still fail occasionally, rerun may pass.

@lu1and10
Copy link
Member

lu1and10 commented Oct 19, 2024

This was an actual unit test failure, i.e. the error of a transform was higher than the tolerance. I don't think this is due to docker issues; it could be due to non-repeatable random numbers though

see #516
one solution may just increase the tolerance a little bit.

@mreineck
Copy link
Collaborator Author

Coming back to this:

Which begs the question, why can't we rename finufft_core.cpp back to
finufft.cpp (after all) ?

Yes, we can do that, and I think it's a great idea. There was a need for finufft_core.cpp at an intermediate stage, where I was moving stuff bit by bit from the twice-compiled finufft.cpp to finufft_core.cpp that was just compiled once.

Is it OK to do that in a follow-up patch (which I'm already preparing)?

@ahbarnett
Copy link
Collaborator

Yes please do a follow-up PR :) (There is no need to change the name finufft_core, I realised, because of the confusion about what itg .h would be called, not to clash with the API finufft.h).

Are you ready to ok this PR and bring in? @DiamonDinoia @lu1and10 Thanks! Alex

@mreineck
Copy link
Collaborator Author

PR is now open, but don't look at the diffs yet, they'll look horribly until the current PR has been merged :-)
I have renamed finufft_core.cpp to finufft.cpp in there, but reverting this is no problem; let me know!

@lu1and10
Copy link
Member

I think it's good to merge as the follow-up PR #581 will fix the remainings.

Copy link
Collaborator

@DiamonDinoia DiamonDinoia left a comment

Choose a reason for hiding this comment

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

Minor things and some questions. One comment (the ceil) can be ignored I put it there as a memo for me mostly

printf("[%s] new plan: FINUFFT version " FINUFFT_VER " .................\n",
__func__);

p->fftPlan = std::make_unique<Finufft_FFT_plan<FLT>>(
p->fftPlan = std::make_unique<Finufft_FFT_plan<TF>>(
Copy link
Collaborator

Choose a reason for hiding this comment

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

can this be std::optional ? So to have it stack allocated

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That might work; I don't have much experience with optional, so I'll try tomorrow.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I propose to bring this in, and deal with such tweaks in the next PR.

src/finufft_core.cpp Show resolved Hide resolved
src/finufft_core.cpp Show resolved Hide resolved
src/finufft_core.cpp Show resolved Hide resolved
src/finufft_core.cpp Show resolved Hide resolved
src/simpleinterfaces.cpp Show resolved Hide resolved
src/simpleinterfaces.cpp Show resolved Hide resolved
src/spreadinterp.cpp Show resolved Hide resolved
src/spreadinterp.cpp Show resolved Hide resolved
src/spreadinterp.cpp Show resolved Hide resolved
# all lib dual-precision objs (note DUCC_OBJS empty if unused)
OBJSD = $(OBJS) $(OBJSF) $(OBJS_PI) $(DUCC_OBJS)
OBJS = $(SOBJS) contrib/legendre_rule_fast.o src/fft.o src/finufft_core.o src/simpleinterfaces.o fortran/finufftfort.o $(DUCC_OBJS)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks!

Copy link
Collaborator

@ahbarnett ahbarnett left a comment

Choose a reason for hiding this comment

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

I would like to bring this in since the few details can be hashed out in the next PR.
Thanks! Alex

@ahbarnett
Copy link
Collaborator

@DiamonDinoia I am squashing this in, and your remaining tweaks we can disciss in the the next PR. Thanks! Alex

@ahbarnett ahbarnett merged commit 5340e0b into flatironinstitute:master Oct 22, 2024
167 checks passed
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.

4 participants