Math symbols are not found during configuration

Hi,
Adding the flag -fopenmp-targets=nvptx64 makes math symbols M_E and M_PI defined in cmath not detected during the execution of CMake. How do I work around this? I am using the latest trunk Clang at this moment, and without the above flag, both symbols are detected properly.

Thanks,
Itaru.

Hi Itaru,

For now, you need to define them yourself when you need them in the target region.
We are working on a permanent solution.

Thanks,
  Johannes

How does #define not act on the full source code? How is that a compliant implementation of the preprocessor?

Jeff

#define works, the preprocessor works.

When the target region is compiled we do not include math.h. This will
change once we get support for variants. Till then, it is either no math
functions or only he ones Clang CUDA provides automatically, which seems
not to include these defines, maybe because they are not ISO C but POSIX
extensions.

I am curious how this works. Does the compiler not #include all headers or specific headers when the target compiler is running?

I make heavy use of preprocessing in all of my OpenMP codes, including the target ones. I don’t compile for the NVPTX back-end so I haven’t seen problems yet but I wonder if my code is broken in that setting.

Jeff

Johannes,
Clang 8.0.0 works without making modifications to the source code, thus I am confused as to
what needs to be done.

I am curious how this works. Does the compiler not #include all headers or
specific headers when the target compiler is running?

Correct. If you compile CUDA, or OpenMP target regions, Clang will
intercept certain header includes. Though, right now, only in the CUDA
case you will also get the system versions. For OpenMP target regions we
cannot do so as we would otherwise redefine symbols, e.g., the std::sin
version for the device and the one for the host have the same prototype.
CUDA solves this problem with the __device__/__host__ annotations.
OpenMP will with #variants.

I make heavy use of preprocessing in all of my OpenMP codes, including the
target ones. I don't compile for the NVPTX back-end so I haven't seen
problems yet but I wonder if my code is broken in that setting.

Preprocessor magic is not impacted at all. All we do is intercept
includes by providing custom headers earlier in the include path. The
preprocessor is not altered nor its function. As described above, the
difference between host and NVPTX device mode is that you will currently
not get the system/math.h header when you include math.h. Regarding your
use case, as long as the device architecture is the same as the host,
there is no need to do any of this.

Does this help?

You are correct, there is a regression but also a major improvement:

Clang 8.0: M_PI works in host code and NVPTX-device code
Clang 8.0: std::sin etc. works in host code but not NVPTX-device code
Clang 9.0: M_PI works in host code but not in NVPTX-device code
Clang 9.0: std::sin etc. works in host code and NVPTX-device code

So we basically traded in system math declarations that had a valid implementation
for NVPTX-devices, thus no vector intrinsics, inline assembly etc., for specialized math
declarations that are distributed with Clang CUDA (as builtin math functions).

I hope this does not cause too much trouble for you and you can benefit from the
additional support. Know that we are working to get both up and running.

Does this help?

In future releases, is NAN supported at least in host code? It’s scattered everywhere in the codebase I am currently working.

Now, and in future releases, host code should not be impacted.

The host code is affected with Clang 9 at this moment. I was originally reporting the host code can not be compiled with -fopemp-targets.

Can you share an example of your problem?

$ git clone https://github.com/nest/nest-simulator
$ cmake -DCMAKE_TOOLCHAIN_FILE=Platform/JURON_Clang -DCMAKE_INSTALL_PREFIX=/tmp/nest-clang-offload -Dwith-gsl=OFF -Dwith-openmp=ON -Dwith-mpi=OFF -Dwith-python=OFF -Dwith-offload=ON /path/to/nest-simulator

That is unfortunately not what I was looking for.

Do you have a single source file, preferably small, which showcases the problem?

#include
#include

int main()
{
std::cout << NAN << std::endl;
};

This gives you a build error when compiled with -fopenmp-targets=nvptx64, but not without it.

Thanks for the reproducer, that helped a lot.

So the problem is the host code but during device compilation.
I was earlier confused as host compilation should not be impacted by this and it is not.

I do not have a good workaround other than defining NAN, and other macros such as M_PI,
manually in NVPTX mode. In my system that would look like:

#ifdef __NVPTX__
  #define NAN (0.0f / 0.0f)
#endif

Can you give this a try and tell me if it works for you?

I will try that. Can I assume this is just a temporary fix?

Not permanent, correct.

Johannes,
This piece of code does not compile either (tested with Clang 10):

#include

int main() {
double_t d = 0.1;
}

There are many implementation .cpp files for my work that depend on the inclusion of the cmath header file.
What do I do for this case?

You can copy the appropriate declaration for "double_t" and guard it by NVPTX.
The definition of "double_t", if you need all the cases, is in math.h.
If you just need the common case, sth. like
#ifdef _NVPTX_
typedef float float_t;
typedef double double_t;
#endif
should suffice.
It works the same way for other defines/typedefs/declarations in math.h that are not provided by Clang-cuda.