Hello from OpenMP
Our first examples print the thread ID and total number from each thread. The thread ID and number of threads are respectively analogous to rank and number of processes in MPI. As for MPI ranks, thread count starts at 0.
A major difference between MPI and OpenMP is that in OpenMP, the threads only exist in a parallel region. They are forked at the beginning and join when the region is terminated.
Operations that are performed by only one thread at a time are said to be atomic. We will learn more about this later. In these first examples, the print/write statements are not guaranteed to be atomic but for the simple codes here, usually will effectively be so.
Exercise 1
Compiled Languages
C++
Contents of omp_hello.cxx#include <iostream>
#include <cstdio>
#include <omp.h>
using namespace std;
int main() {
int tid, nthreads;
#pragma omp parallel private(tid)
{
nthreads=omp_get_num_threads();
tid=omp_get_thread_num();
printf("Hello from thread %d of %d\n",tid, nthreads);
//cout<<"Hello from thread"<<" "<<tid<<" of"<<nthreads<<"\n";
}
}
Download omp_hello.cxx file
Note for C++
In this example, the line for stream output is commented out and C-style stdio is used. Comment out the printf line and uncomment cout. Recompile and rerun. What do you observe? Why do you think this might have happened?
Explanation
In C++ stream IO, each stream (separated by the << operator) is executed separately. The output stream (stdout in Unix) is a shared resource, so the results care generally jumbled. This is actually possible with printf as well, but for with printf the full output string is written at once and in most cases this will succeed before another thread tries to access stdout. So it often completes successfully even though atomicity is not guaranteed.
Fortran
Contents of omp_hello.f90program omp_hello
use omp_lib
implicit none
integer :: i
integer :: nthreads, tid
!$omp parallel private(tid)
nthreads=omp_get_num_threads()
tid=omp_get_thread_num()
write(*,'(a,i3,a,i3)') "Hello from thread ",tid," of ",nthreads
!$omp end parallel
end program
Download omp_hello.f90 file
Python
Contents of omp_hello.pyfrom omp4py import *
import os
def set_init_omp_nthreads():
global _threads
if os.getenv("OMP_NUM_THREADS") is not None:
_threads=int(os.getenv("OMP_NUM_THREADS"))
else:
_threads=os.cpu_count()
omp_set_num_threads(_threads)
@omp
def hello():
tid=0
with omp("parallel private(tid)"):
tid=omp_get_thread_num()
print(f"Hello from thread {tid} of {_threads}")
return None
set_init_omp_nthreads()
hello()
Download omp_hello.py file
Notes for Python
The omp4py package we are using does not, at this point, directly support OMP_NUM_THREADS or set the number of threads in the same manner as the compiled languages, so there is some extra code to handle this.
Exercises 1B and 1C
B. Try setting different values for OMP_NUM_THREADS.
C. Add an appropriate print/write statement immediately before the pragma, pseudocomment, or function call.