I have this code in visual c++ 2012:
void Run()
{
#pragma omp parallel for
for(int imageNo=0;imageNo<4;imageNo++)
{
RunForOneImage(imageNo, Data[imageNo],
width, height,
OutputWidth, OutputHeight);
}
}
All variables in RunForOneImage are local variables and it doesn't use any global or class member variables.
When run it, I can see that only one core became busy and other core are idle.
Why this is not running in parallel?
I selected multi processor option in visual studio (/MP). Is there any other option that I should select?
The /MP option means that the compilation will run on multiple processors, it's purpose is to "reduce the total time to compile the source files".
It has nothing to do with OpenMP API. To enable OpenMP support, there's an /openmp option (in the documentation you'll also find an example and the description of how to enable OpenMP support).
Just go to Project Properties->C/C++->Language->Open MP Support and switch it to Yes.
Related
I'm trying to compile a source code on Windows that works great on Linux.
Now, I'm facing the following issue:
The code relies on OpenMP and in there, the scheduling approach should be stored in a string and the chunk size in an integer.
The following code does extract the necessary information.
omp_sched_t omp_sched;
int chunkSize;
omp_get_schedule( &omp_sched, &chunkSize );
string jobScheduling;
switch ( omp_sched ) {
case omp_sched_static:
jobScheduling = "static";
break;
case omp_sched_dynamic:
jobScheduling = "dynamic";
break;
case omp_sched_guided:
jobScheduling = "guided";
break;
case omp_sched_auto:
jobScheduling = "auto";
break;
default:
jobScheduling = "auto";
break;
}
On Windows, by using the Microsoft Visual Studio compilers, it does not recognize omp_sched_t, omp_sched_static, omp_sched_dynamic...
Is this Linux specific? If not, how can I fix this (preferably without changing the source code)?
You are using features introduced in OpenMP 3.0 but Microsoft VisualC++ only supports OpenMP 2.0. And, AFAIK, even that support is deprecated though it's still there.
If you want support for modern OpenMP, you simply need a different compiler. Visual Studio comes with optional Clang, which has the required support, but enabling OpenMP via the Project Properties dialog can be a bit tricky. Another option is Intel C/C++ Compiler for Windows, which is a commercial piece of software.
I am storing some variables inside custom section in my program. During debugging session I can check it is created and that it contains the necessary data. But in release mode, it disappears!
Note: I am also creating an executable section which strangely is created in both version. The CPU platform seems to make no difference.
Why doesn't the "data" segment appear in the release version?
This is a short snapshot:
// Defnitions used for better code segmentation
#define store_variable(x) __declspec(allocate(x)) //for data segment
#define store_code(seg) __declspec(code_seg(seg)) //for execution segment
#pragma section(".eqwrt", read) //weird name because I thought there would be collision
store_variable(".eqwrt") UCHAR USER_DATA[SIZE];
store_variable(".eqwrt") USHORT Version = 1;
store_code(".wsect") bool sendError();
The program (it's a dll) is compiled with a fixed base address and with /MT flag.
Release version x64. Only one segment appears-the executable one:
Debug version x64. Both segments show up:
Try to disable Link-time optimizatizon scheme from the project's settings.
To do that go to: Configuration Properties 🠂 General 🠂 Whole Program Optimisation and set to No Whole Program Optimisation.
Most likely it has something to do with the optimisations performed during linking.
More details you can get from here : What's C++ optimization & Whole program optimization in visual studio
I just tried OpenMP with a simple c program
test() {
for(int i=0;i<100000000;i++);
}
main() {
printf("Num of CPU: %d\n", omp_get_num_procs());
#pragma omp parallel for num_threads(4)
for(int i=0;i<100;i++) test();
}
Compiled with g++ -fopenmp. It can correctly print out that I have 4 CPUs, but all test functions are running at thread 0.
I tried to modify the OMP_NUM_THREADS. But it has no effect also.
I had everything the same as the online examples but why wouldn't I get it to work?
Your problem is here:
#pragma omp parallel for num_thread(4) <---
The correct clause is num_threads(4), not num_thread(4). Incorrect openmp pragmas are ignored and so you ended up with a sequential program. :)
I'm surprised you didn't get a compiler warning, because I did.
I had this problem in visual studio and finally I understood that I had forgotten to enable Open MP support in visual studio. It didn't give me any error but executed the program just for one thread
first choose project _> properties -> c/c++ -> language -> open mp support -> choose yes
and then you will find above conformance mode (make it no )
use the function omp_set_num_threads(4) before calling the omp parallel section.
also, how do you determine the number of threads ??
embed your printfs in a critical section just to make sure everything is getting printed.
I encountered the very same situation on my ubuntu desktop when I extends numpy module with C code. openmp only ran with one thread. I happened to remove libopenblas-base and install libatlas-base-dev.(to deal with numpy installation problem) Then multi-threading openmp came back:)
I have tested it on a ubuntu server with 64 cores and it works just as my desktop!
I think this is because libopenblas conflicts with libraries like atlas.
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
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.