Skip to content

Conversation

@DiamonDinoia
Copy link
Collaborator

@mreineck when building locally. The issue seems to be just in the test. Not in anything public facing.

@mreineck
Copy link
Collaborator

This looks good, but I still think that using plain abs() in a C++ code (as is happening in other places of finufft) is an accident waiting to happen. Including <math.h> is archaic C++ for 27 years now, and if things go wrong, they tend to go wrong very subtly and require tedious debugging.
It's happened to me, and I've seen it happen to several other people ... but this can definitely wait for a follow-up patch.

@DiamonDinoia
Copy link
Collaborator Author

@mreineck I totally agree. We should not use abs in .cpp code. The issue with std::abs is when used on thrust::complex

@DiamonDinoia
Copy link
Collaborator Author

I turned that warning in an error. To mitigate the issue. Let me try having a go at fixing this.

@ahbarnett
Copy link
Collaborator

When I include std:: in testutils, as in this new version, tests pass fine on my linux machine with GCC 11.4.
So, I don't understand the CI "illegal" errors.

Note that in some sources in test/ I have using namespace std; which is probably bad practice but saved a lot of typing of std:: for math.
I also used fabs in many places.

Happy to insert std:: everywhere needed.

@mreineck
Copy link
Collaborator

The "illegal" errors are unrelated, I'm quite sure. I just have no idea what is causing them.

@lu1and10
Copy link
Member

the CI "illegal" errors.

@ahbarnett I'm not sure why CI breaks so often. One possible reason is, to accelerate the ci runs, @DiamonDinoia uses sccache in ci to cache the compiled object files(.o) from previous ci runs, if the previous ci run was ran on avx512 machine with flag -march=native, and the next ci run re-uses the cached object files and run on avx2 machine, there might be illegal instructions.

What is the "key" that sccache used to distinguish changes(currently how sccache decide to reuse .o files or not), besides the C++ flags, does sscache distinguish cpu instructions?

Currently, it seems with "-march=native", the ci may break with reused object files, I guess.

@mreineck
Copy link
Collaborator

mreineck commented Oct 24, 2025

Oh! If files compiled with -march=native are re-used on different hardware, the "illegal" makes perfect sense ... it's a cut-down "illegal instruction" error.

But CI should definitely never do this ...

And "illegal instruction" should not be truncated like this ... strange,

@lu1and10
Copy link
Member

But CI should definitely never do this ...

Yes, not sure if it's sccache problem. If it is, we should tell it, machine changed, with -march=native, please rerun no reuse...

@DiamonDinoia
Copy link
Collaborator Author

DiamonDinoia commented Oct 24, 2025

But CI should definitely never do this ...

Yes, not sure if it's sccache problem. If it is, we should tell it, machine changed, with -march=native, please rerun no reuse...

Worth opening a separate issue for it. We could add the instruction set from lscpu to the key. Or manually set the vector width. This allows to test different vectorizations same as xsimd does.

PS: @lu1and10 that's a very good guess! I was wondering what the problem was too.

@lu1and10
Copy link
Member

We could add the instruction set from lscpu to the key.

Good idea, we can retain the ci speedup from sccache and at the same time avoid illegal instructions.

@DiamonDinoia
Copy link
Collaborator Author

@mreineck I went ahead and remove using namespace std and fixed all the compiler warning/errors that originates from it (-werror has be incredibly useful).

I also fixed examples and one documentation file containing using namespace std. I don't think we should encourage bad practices.

I ran this though an LLM to tell me if I missed something and it says it is okay.

@mreineck, @lu1and10 what do you think?

@DiamonDinoia
Copy link
Collaborator Author

@blackwer I am a confused by examples/cuda/getting_started.cpp it seems to me a c file masquerading as cpp.

@mreineck
Copy link
Collaborator

Hi @DiamonDinoia, this is of course the cleanest approach to fix the issue (and also prevent it from happening again)!

I wouldn't say that using namespace std; is bad practice in general; it's only unconditionally bad if you "force" it onto users by putting it unprotected in a header file. Apart from that it can save a lot of typing; you only need to make sure that you are not using any "C-like" headers (like <math.h>).

That said, I like the change very much as it is, even though it touches a lot of files!

int m = 0;
for (int m2 = -(N2 / 2); m2 <= (N2 - 1) / 2; ++m2) // loop in correct order over F
for (int m1 = -(N1 / 2); m1 <= (N1 - 1) / 2; ++m1)
ct += fkstart[m++] * exp(J * (m1 * x[jt] + m2 * y[jt])); // crude direct
Copy link
Collaborator

Choose a reason for hiding this comment

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

Here, the exp seems to be missing a std::. Don't put too much trust in LLMs :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

grep was my best friend here...

@blackwer
Copy link
Member

@blackwer I am a confused by examples/cuda/getting_started.cpp it seems to me a c file masquerading as cpp.

This whole package was written with as C plus some stuff. It's fine to update it to a more proper C++ style. It was just consistent with the way everything else was written.

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 doing this. It's good you enforced the correct abs and exp etc in the library source and tests.

I feel that it makes the example codes much less readable. I would prefer the examples to simply using namespace std; because they are so limited, short, and designed for humans to read (Would it be a pain to just git checkout the examples from master, and fix the header from math.h to cmath ?). Ie, I think the PR got a little too big in scope, beyond just making sure the src/tests were secure.

In fact the whole thing makes me depressed about C++ ... what's the point of a language where you have to write std:: in front of every other function? Declaring complex vectors is particularly ugly now, as is any stdio stuff. It's not like we are inserting using namespace std; into a header file that affects other people here. It is just there to make clean, short, source codes for testing and examples.

Thoughts?

c[j] =
2 * ((double)rand() / RAND_MAX) - 1 + 1i * (2 * ((double)rand() / RAND_MAX) - 1);
c[j] = 2 * ((double)std::rand() / RAND_MAX) - 1 +
std::complex<double>(0.0, 1.0) *
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we use I which was defined above for a reason? I must say this std:: everywhere is highly unpleasant! I'm not sure why in our example codes we're killing using namespace std; ....

c[j] =
2 * ((double)rand() / RAND_MAX) - 1 + 1i * (2 * ((double)rand() / RAND_MAX) - 1);
c[j] = 2 * ((double)std::rand() / RAND_MAX) - 1 +
std::complex<double>(0.0, 1.0) *
Copy link
Collaborator

Choose a reason for hiding this comment

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

I

x[j] = PI * (2 * ((double)rand() / RAND_MAX) - 1); // uniform random in [-pi,pi)
x[j] = PI * (2 * ((double)std::rand() / RAND_MAX) - 1); // uniform random in [-pi,pi)
// note FINUFFT doesn't use std::vector types, so we need to make a pointer...
finufft_setpts(plan, M, x.data(), NULL, NULL, 0, NULL, NULL, NULL);
Copy link
Collaborator

Choose a reason for hiding this comment

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

nullptr ? Surely it doesn't matter since setpts ignores them.

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 missed it. I'll fix it.

x[j] = PI * (2 * ((float)std::rand() / RAND_MAX) - 1); // uniform random in [-pi,pi)
// note FINUFFT doesn't use std::vector types, so we need to make a pointer...
finufftf_setpts(plan, M, &x[0], NULL, NULL, 0, NULL, NULL, NULL);
finufftf_setpts(plan, M, &x[0], nullptr, nullptr, 0, nullptr, nullptr, nullptr);
Copy link
Collaborator

Choose a reason for hiding this comment

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

x.data()

int ier = finufft_makeplan(type, dim, Ns, +1, ntrans, tol, &plan, nullptr);
// step 2: send in M nonuniform points (just x, y in this case)...
finufft_setpts(plan, M, &x[0], &y[0], NULL, 0, NULL, NULL, NULL);
finufft_setpts(plan, M, &x[0], &y[0], nullptr, 0, nullptr, nullptr, nullptr);
Copy link
Collaborator

Choose a reason for hiding this comment

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

x.data() etc

@@ -1,26 +1,21 @@
#include "finufft/finufft_utils.hpp"
#include <finufft/spreadinterp.h>
#include <finufft/test_defs.h>
Copy link
Collaborator

Choose a reason for hiding this comment

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

It seems like adding using namespace std::printf etc to test_defs.h would make this a whole lot less ugly...

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's a good idea! We can also add I to test_defs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

and rand

// public header
#include <finufft.h>
// private headers
#include <algorithm>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could I ask what from the algorithm library is used? Ah, max I guess..


#include <finufft_common/common.h>
#include <cufinufft.h>
#include <finufft_common/common.h>
Copy link
Collaborator

Choose a reason for hiding this comment

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

If this header ordering is important, please add a comment...

F[k] = std::sin((FLT)0.7 * k) + IMA * std::cos((FLT)0.3 * k); // set F for t2
ier = FINUFFT1D2(M, x, c, +1, 0, N, F, &opts);
if (ier != FINUFFT_WARN_EPS_TOO_SMALL) {
printf("1d2 tol=0:\twrong err code %d\n", ier);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm assuming printf is fine here, thank god! Not sure why it wasn't fine earlier...

free(u);
if (isnan(errmax) || (errmax > errfail)) {
if (std::isnan(errmax) || (errmax > errfail)) {
printf("\tfailed! err %.3g > errfail %.3g\n", errmax, errfail);
Copy link
Collaborator

Choose a reason for hiding this comment

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

hoping printf is fine here... please :)

@DiamonDinoia
Copy link
Collaborator Author

DiamonDinoia commented Oct 28, 2025

In general I do not like using exp in c++ or abs without std:: because I never know if I am calling a compiler builtin with implicit conversion or an actual function. One way to make is safer is to use -Wconversion

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.

5 participants