compile c++ code with and without fopenmp flag - c++

I have installed the C++ and Fortran compiler and tested the (C++) programs
(serial and parallel versions).
in Fortran when compiling a (parallelized) code without enabling the -openmp option should compile the code in (default) serial mode
but in C++ I get errors like
undefined reference to omp_get_thread_num
but in Fortran when you compile code without the -fopenmp flag it ignores any code which start with $!omp like
$!omp id = omp_get_thread_num()
Is there any option like that in C++?

You can protect your C/C++ code with the _OPENMP define. This way you can avoid introducing calls to the OpenMP runtime whenever your application is not linked against it.
For instance, you can have the following code
void foo (void)
{
#ifdef _OPENMP
printf ("I have been compiled with OpenMP support\n");
#else
printf ("I have been compiled without OpenMP support\n");
#endif
}

Related

Visual Studio C++ compiler tries to compile CUDA C/C++ files

I am trying to make a project I've been working on use CUDA.
At the moment it has four build configs, two (release and debug) which define a compiler symbol so it compiles with CUDA, and two (release and debug) which instead directs it to CPU code.
This is a short version of main.cpp:
#ifdef CUDA
#include "CUDACode.cu"
#else
#include "CPUCode.h"
#endif
int main() {
functionDefinedinBothHeaders(params);
}
but for some reason NVCC runs and compiles it fine but then the C++ compiler trys to compile it and that causes many errors that I've managed to circumvent using #ifdef __NVCC__ statements but now I have an issue where main.cpp has to use something from a header so I put is outside the #ifdef __NVCC__ statements and now I get linker error as they are defined twice as NVCC compiles it and the C++ compile does as well
error LNK2005: "class boost::random::mersenne_twister_engine<unsigned int,32,351,175,19,3433795303,11,4294967295,7,834054912,15,4293197824,17,1812433253> generator" (?generator##3V?$mersenne_twister_engine#I$0CA#$0BFP#$0KP#$0BD#$0MMKLIOOH#$0L#$0PPPPPPPP#$06$0DBLGKLAA#$0P#$0PPOFAAAA#$0BB#$0GMAHIJGF##random#boost##A) already defined in CUDAStateCalc.cu.obj
the .cu files are set to CUDA C/C++ code. How do I stop it from doing that? and is there a better method than what I'm doing?
Robert Crovella answered my question in the comments, what I needed to do was have a header function that was included in main.cpp and CUDACode.cu and contained the function prototype for functionDefinedinBothHeaders but CUDACode.cu defined it

LLVM code generation with C++ API: How to handle OpenMP calls

I'm working on a compiler for a small language. Inside the compiler, I'm using the LLVM C++ API to generate llvm code, similar to the LLVM Kaleidoscope tutorial. So I'm using TheModule, TheContext, BasicBlocks,
and calls to Builder.Create...().
I can currently generate valid llvm code for arithmetic, control flow, and methods. However, I would also like my small language to support very simple OpenMP pragmas. For example,
#pragma omp parallel
{
print "Hello World"
}
I've tried writing a similar program in C++,
#include <iostream>
int main() {
#pragma omp parallel
{
std::cout << "Hi";
}
}
and generating llvm using clang++ -S -emit-llvm file.cpp -fopenmp. Along with the rest of the code, this generates the following lines which seem to implement the OpenMP functionality:
declare void #__kmpc_fork_call(%ident_t*, i32, void (i32*, i32*, ...)*, ...)
define internal void #.omp_outlined.(...)
From researching these statements, I found the Clang OpenMP API that contains calls like
OMPParallelDirective * OMPParallelDirective::Create(...)
I'm guessing this is what the Clang compiler uses to generate the statements above. However, it seems to be separate from the LLVM C++ API, as it doesn't reference TheContext, TheModule, etc...
So my question: Is there any way to leverage the Clang OpenMP API calls with my LLVM C++ API calls to generate the kmpc__fork_call and #.omp_outlined IR needed for parallel computation?
I did try decompiling the llvm generated from the C++ code back into LLVM C++ API code using llc -march=cpp file.bc ... but was unsuccessful.
The API you found operate on clang AST and are hardly usable outside clang. In fact, there are no OpenMP constructs at the LLVM IR level - everything is already lowered down to runtime calls, etc.
So, you'd really need to implement codegeneration for OpenMP by yourself emitting runtime calls as necessary (and per your language semantics).

Unknown pragma when compiling OpenMP with g++

I am working on C++ code which contains openmp pragmas. While trying to compile with g++, I am receiving the following error message:
ignoring #pragma omp parallel [-Werror=unknown-pragmas]
I understand that the error is from not using fopenmp flag with in the makefile. I have tried including the fopenmp flag to the CXXFLAGS. Still, it is not working.
Would anyone think of solutions to work around this issue?
Note: This question looks like a repeat question of similar question on same error and I have gone through and tried it too. Therefore, I would request this question not to be flagged as repeat question.
This is warning appears if you compile OpenMP code without the -fopenmp flag. The g++ man page tells us what -fopenmp does:
Enable handling of OpenMP directives "#pragma omp" in C/C++ and
"!$omp" in Fortran. When -fopenmp is specified, the compiler
generates parallel code according to the OpenMP Application Program
Interface v3.0 http://www.openmp.org/. This option implies
-pthread, and thus is only supported on targets that have support
for -pthread

How to disable OpenMP directives in a nice way?

I have C++ code with OpenMP pragmas inside. I want to test this code both for multithread mode (with OpenMP) and in single thread mode (no OpenMP).
For now, to switch between modes I need to comment #pragma omp (or at least parallel).
What is the cleanest, or default, way to enable / disable OpenMP?
If you do not compile with -fopenmp option, you won't get the parallel code. You can do it with an appropiate define and makefile that generates all codes.
The OpenMP documentation says (only an example):
#ifdef _OPENMP
#include <omp.h>
#else
#define omp_get_thread_num() 0
#endif
See http://www.openmp.org/mp-documents/spec30.pdf (conditional compilation).
Look into the compiler manual for the switch that disables OpenMP. For GCC, OpenMP is disabled by default and enabled with the -fopenmp option.
Another option would be to run the code with the OMP_NUM_THREADS environment variable set to 1, though that is not exactly the same as compiling without OpenMP in the first place.
The way such things are usually handled (the general case) is with #defines and #ifdef:
In your header file:
#ifndef SINGLETHREADED
#pragma omp
#endif
When you compile, add -DSINGLETHREADED to disable OpenMP:
cc -DSINGLETHREADED <other flags go here> code.c

Ignore OpenMP on machine that does not have it

I have a C++ program using OpenMP, which will run on several machines that may have or not have OpenMP installed.
How could I make my program know if a machine has no OpenMP and ignore those #include <omp.h>, OpenMP directives (like #pragma omp parallel ...) and/or library functions (like tid = omp_get_thread_num();) ?
OpenMP compilation adds the preprocessor definition "_OPENMP", so you can do:
#if defined(_OPENMP)
#pragma omp ...
#endif
For some examples, see http://bisqwit.iki.fi/story/howto/openmp/#Discussion and the code which follows.
Compilers are supposed to ignore #pragma directives they don't understand; that's the whole point of the syntax. And the functions defined in openmp.h have simple well-defined meanings on a non-parallel system -- in particular, the header file will check for whether the compiler defines ENABLE_OPENMP and, if it's not enabled, provide the right fallbacks.
So, all you need is a copy of openmp.h to link to. Here's one: http://cms.mcc.uiuc.edu/qmcdev/docs/html/OpenMP_8h-source.html .
The relevant portion of the code, though, is just this:
#if defined(ENABLE_OPENMP)
#include <omp.h>
#else
typedef int omp_int_t;
inline omp_int_t omp_get_thread_num() { return 0;}
inline omp_int_t omp_get_max_threads() { return 1;}
#endif
At worst, you can just take those three lines and put them in a dummy openmp.h file, and use that. The rest will just work.
OpenMP is a compiler runtime thing and not a platform thing.
ie. If you compile your app using Visual Studio 2005 or higher, then you always have OpenMP available as the runtime supports it. (and if the end-user doesn't have the Visual Studio C runtime installed, then your app won't work at all).
So, you don't need to worry, if you can use it, it will always be there just like functions such as strcmp. To make sure they have the CRT, then you can install the visual studio redistributable.
edit:
ok, but GCC 4.1 will not be able to compile your openMP app, so the issue is not the target machine, but the target compiler. As all compilers have pre-defined macros giving their version, wrap your OpenMP calls with #ifdef blocks. for example, GCC uses 3 macros to identify the compiler version, __GNUC__, __GNUC_MINOR__ and __GNUC_PATCHLEVEL__
How could I make my program know if a machine has no OpenMP and ignore those #include <omp.h>, OpenMP directives (like #pragma omp parallel ...) and/or library functions (like tid = omp_get_thread_num();) ?
Here's a late answer, but we just got a bug report due to use of #pragma omp simd on Microsoft compilers.
According to OpenMP Specification, section 2.2:
Conditional Compilation
In implementations that support a preprocessor, the _OPENMP macro name
is defined to have the decimal value yyyymm where yyyy and mm are the
year and onth designations of the version of the OpenMP API that the
implementation supports.
It appears modern Microsoft compilers only support OpenMP from sometime between 2000 and 2005. I can only say "sometime between" because OpenMP 2.0 was released in 2000, and OpenMP 2.5 was released in 2005. But Microsoft advertises a version from 2002.
Here are some _OPENMP numbers...
Visual Studio 2012 - OpenMP 200203
Visual Studio 2017 - OpenMP 200203
IBM XLC 13.01 - OpenMP 201107
Clang 7.0 - OpenMP 201107
GCC 4.8 - OpenMP 201107
GCC 8.2 - OpenMP 201511
So if you want to use, say #pragma omp simd to guard a loop, and #pragma omp simd is available in OpenMP 4.0, then:
#if _OPENMP >= 201307
#pragma omp simd
for (size_t i = 0; i < 16; ++i)
data[i] += x[i];
#else
for (size_t i = 0; i < 16; ++i)
data[i] += x[i];
#endif
which will run on several machines that may have or not have OpenMP installed.
And to be clear, you probably need to build your program on each of those machines. The x86_64 ABI does not guarantee OpenMP is available on x86, x32 or x86_64 machines. And I have not read you can build on one machine, and then run on another machine.
There is another approach that I like, borrowed from Bisqwit:
#if defined(_OPENMP)
#include <omp.h>
extern const bool parallelism_enabled = true;
#else
extern const bool parallelism_enabled = false;
#endif
Then, start your OpenMP parallel for loops like this:
#pragma omp parallel for if(parallelism_enabled)
Note: there are valid reasons for not using pragma, which is non-standard, hence why Google and others do not support it.