Reputation: 18614
I was playing around with OpenMP and came across the following 2 methods: omp_get_num_threads()
and omp_get_num_procs()
. I tried them using just plain C, without the OpenMP directives and even without #include <omp.h>
:
int main ()
{
int t, p;
t = omp_get_num_threads();
p = omp_get_num_procs();
printf("Number of threads = %d\n", t);
printf("Number of processors = %d\n", p);
}
Nevertheless I got the expected result:
Number of threads = 1
Number of processors = 4
As those methods both start with opm
I assume these are OpenMP methods and are unknown in C. How come they deliver the right result even outside of OpenMP?
Upvotes: 2
Views: 6673
Reputation: 390
In short:-
omp_get_num_procs() gets the number of processors or threads in the hardware level your system has. It does not matter where you can choose to call this method, it will forever get the number of hardware threads dedicated to your system by the manufacturer.
On the other hand, omp_get_num_threads() gets the number of threads that are currently executing a block of code.
For example, in a serial program or just before your parallel region, this function would return 1. If you call it inside the parallel region, it returns the number of threads that are currently active or set to be running in this region.
USES:- omp_get_num_procs() can be used if you want to create a parallel region and you want to know prio the total number of hardware threads/ processors your system has. And therefore create a parallel region with the exact number of threads/ processors your system has. By the way, you can create a parallel region with a any number of threads i.e number of threads can be greater than the number of hardware threads dedicated to your system.
omp_get_num_threads() can be used just to get the number of active threads, and that's it.
Upvotes: 0
Reputation: 47583
First of all, there is no such thing as "outside" OpenMP. The OpenMP pragmas just translate to normal code, for example using pthread functions if compiled with gcc. So any function of OpenMP would work even if you don't have a #pragma omp
.
Indead, omp_get_num_procs
returns the number of processors, regardless of what you are running or if at all you use OpenMP, and omp_get_num_threads
returns the number of collaborating threads which would of course be 1 if not using OpenMP:
Returns the number of threads in the current team. In a sequential section of the program omp_get_num_threads returns 1.
Now the actual question becomes the following: How can C know that it should call those OpenMP functions without you including the header?
It actually doesn't. If you enable warnings on your compiler (for example gcc -Wall
, you would receive warnings saying:
implicit declaration of function ‘omp_get_num_threads’
implicit declaration of function ‘omp_get_num_procs’
But this is not forbidden by the standard. So what happens is that C assumes these implicitly defined functions don't take any parameters (which by chance matches the declaration of omp_get_num_procs/threads
).
Next, there is the link stage, which is done after the compilation and you are beyond the realm of C. The linker however, doesn't bother with function signatures. All it needs is to know function names. Since those functions are implicitly declared, they are still declared! So they exist in the object file and are ready to be linked. If the linker is instructed to link against the OpenMP library, it would correctly link those implicitly declared functions.
Only mystery remaining is why your compiler is trying to link with OpenMP even if you haven't told it? First guess is that you have told it to link against OpenMP. If not, there could be a couple of reasons. Off the top of my head, if you are using software made for grandmothers (e.g. Microsoft products), it may have been configured to link every program against many unnecessary libraries so the programmer won't have to bother with that configuration.
With gcc 4.8.1, this is the output (note that you should write int main(void)
and also return something from it, not to mention you haven't included stdio.h
):
$ gcc -c a.c -Wall
a.c: In function ‘main’:
a.c:5:5: warning: implicit declaration of function ‘omp_get_num_threads’ [-Wimplicit-function-declaration]
t = omp_get_num_threads();
^
a.c:6:5: warning: implicit declaration of function ‘omp_get_num_procs’ [-Wimplicit-function-declaration]
p = omp_get_num_procs();
^
a.c:8:5: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
printf("Number of threads = %d\n", t);
^
a.c:8:5: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
a.c:10:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
Note that what is stated in the comment above:
I think you enabled OpenMP in the compiler, which automatically defined the functions for you.
is not true at least for gcc, as the output of gcc -c a.c -Wall -fopenmp
is exactly the same.
And during link, if you don't specify -fopenmp
, the linker won't find the symbols:
$ gcc a.o
a.o: In function `main':
a.c:(.text+0xe): undefined reference to `omp_get_num_threads'
a.c:(.text+0x1b): undefined reference to `omp_get_num_procs'
collect2: error: ld returned 1 exit statusw
Upvotes: 4