OpenMP Labs June 2026

General Setup

We use the same code as for the OpenACC Lab. The exercises can be found in the file Jacobi.tgz. This file contains both C and Fortran versions of the code.

Open a Terminal in JupyterLab and copy the exercises to your home directory in the JupyterLab via

In the labs you will implement 6 different version of the code for multicore CPUs and GPUs. Note the execution time for each of those versions in the results sheet available online under https://doku.lrz.de/openmp-labs-results-june-2026-2763063802.html

Lab 1: Profiling with Nsight Systems

Check the configuration of the GPUs via the following commands which are provided with the NVIDIA HPC Software Development Kit (SDK) on the compute node:

nvidia-smi

nvaccelinfo

We are using the NVIDIA HPC SDK C and Fortran compilers for the hands-on.

Compile the code using the following commands:

For C:

nvc -fast -o laplace jacobi.c laplace2d.c

For Fortran:

nvfortran -fast -o laplace laplace2d.f90 jacobi.f90


To profile the code run the Nsight Systems command line interface on the compute node via:

nsys profile -t nvtx --stats=true --force-overwrite true -o laplace ./laplace


This will produce the trace files laplace.nsys-rep and laplace.sqlite. Use "nsys --help" and "nsys --help profile" to get more information about the available profiler options.

For performance reasons, visualisation of the trace files should be always done on the local PCs.

Copy the trace file *.nsys-rep to your local PC by  right-clicking on the file in the left pane of the JuptyerLab and selecting "Download".

Run Nsight Systems on the local PC and open the trace file via File → Open. Zoom in the timeline and also test different views like "Top-Down view". Identify the 2 most time consuming routines of the code.

Further information is available under https://developer.nvidia.com/nsight-systems

Using NVIDIA Tools Extension (NVTX)

For C:

Add #include "nvtx3/nvToolsExt.h" in a copy jacobi-nvtx.c of the source code jacobi.c and wrap parts of the code which you want to capture events with calls to the NVTX API functions. For example, try adding nvtxRangePush("calc") before calling calcNext() and nvtxRangePop() just after calling it. We recommend to wrap calls to the functions initialize(), calcNext() and swap() and also wrap the while-loop in which the last 2 functions are called.

For C compile the NVTX annotated code as before:

nvc -I$NVHPC_ROOT/cuda/include -fast -o laplace-nvtx jacobi-nvtx.c laplace2d.c

For Fortran:

Add use nvtx in a copy jacobi-nvtx.f90 of the source code jacobi.f90 and wrap parts of the code which you want to capture events with calls to the NVTX API functions. For example, try adding call nvtxStartRange("calc") before calling calcNext() and call nvtxEndRange() just after calling it. We recommend to wrap calls to the functions initialize(), calcNext() and swap() and also wrap the while-loop in which the last 2 functions are called.

For Fortran compile the NVTX annotated code and link the library nvhpcwrapnvtx as follows:

nvfortran -fast -o laplace-nvtx laplace2d.f90 jacobi-nvtx.f90 -lnvhpcwrapnvtx

Profile again on the compute node using

nsys profile -t nvtx --stats=true --force-overwrite true -o laplace-nvtx ./laplace-nvtx

and visualise the profile data on the local PC.

Further information can be found in the CUDA Profiler User’s Guide https://docs.nvidia.com/cuda/profiler-users-guide/index.html

You can use the NVTX annotated code also for profiling in the next Labs if you want.

Lab 2: OpenMP Directives

Using OpenMP for multicore CPUs with the parallel for directive

For C:

Make a copy laplace2d-multicore-parallel.c of the file laplace2d.c  and consider the following directives at the right place to parallelise the calcNext() and swap() functions:

#pragma omp parallel for

#pragma omp parallel for reduction(max:variable)

#pragma omp parallel for collapse(2)

For Fortran:

Make a copy laplace2d-multicore-parallel.f90 of the file laplace2d.f90  and consider the following directives at the right place to parallelise the calcNext() and swap() functions:

!$omp parallel do 

!$omp parallel do reduction(max:variable)

!$omp parallel do collapse(2)

Compile the code for multicore CPUs using the following commands:

For C:

nvc -fast -mp=multicore -Minfo=mp,opt -o laplace-multicore-parallel jacobi.c laplace2d-multicore-parallel.c

For Fortran:

nvfortran -fast -mp=multicore -Minfo=mp,opt  -o laplace-multicore-parallel jacobi.f90 laplace2d-multicore-parallel.f90

Run the code on the compute node. You can set the number of threads on the CPU via 

export OMP_NUM_THREADS=n

Profiling OpenMP code

Profile the code on the compute node via

nsys profile -t nvtx --stats=true --force-overwrite true -o laplace-multicore-parallel ./laplace-multicore-parallel

OpenMP Support is limited in nsys, however you can consider to compile your code via

nvc -fast -mp=multicore,ompt -Minfo=mp,opt

and profile it using

nsys profile -t nvtx,openmp --stats=true --force-overwrite true -o laplace-multicore-parallel ./laplace-multicore-parallel


Compare with the previous profiling results.

Lab 3: GPU Programming using OpenMP

For C:

Make a copy laplace2d-gpu-parallel.c of laplace2d-multicore-parallel.c.

Compile the code using the following commands

nvc -fast -mp=gpu -Minfo=mp,opt -o laplace-gpu-parallel jacobi.c laplace2d-gpu-parallel.c

For Fortran:

Make a copy laplace2d-gpu-parallel.f90 of laplace2d-multicore-parallel.f90.

Compile the code using the following commands

nvfortran -fast -mp=gpu -Minfo=mp,opt  -o laplace-gpu-parallel jacobi.f90 laplace2d-gpu-parallel.f90

Check if the code compiles and runs correctly on the GPU.

Consider the following directives at the right place to parallelise the calcNext() and swap() functions on the GPU:

For C:

#pragma omp target teams distribute parallel for

#pragma omp target teams distribute parallel for reduction(max:variable) 

#pragma omp target teams distribute parallel for collapse(2)


For Fortran:

!$omp target teams distribute parallel do

!$omp target teams distribute parallel do reduction(max:variable)

!$omp target teams distribute parallel do collapse(2)

...

!$omp end target teams distribute parallel do


Check if the code compiles and runs correctly on the GPU.

Modify the code to specify the sizes of the arrays to be copied from/to the GPU correctly. The sizes of the arrays can be specified with the  map clauses of the target directive, e.g.:

In C:

map(to: array[start_index:length]) 

map(from:array[start_index:length]) 

map(tofrom: array[start_index:length]) 

map(alloc: array[start_index:length])

map(delete: array[start_index:length])

In Fortran:

map(to: array(start_index:end_index)

map(from: array(start_index:end_index))

map(tofrom: array(start_index:end_index))

map(alloc: array(start_index:end_index)) 

map(delete: array(start_index:end_index))


For 2D arrays in Fortran, array sections must be specified as  array(start_index1:end_index1, start_index2:end_index2). If the whole array is used in OpenMP data mapping, it can be written simply as e.g.  map(to: array) without specifying bounds in Fortran.

Run and profile both versions of the code on the compute node and compare with the previous profiling results.

Consider using managed memory with OpenMP by compiling the same code with

nvc -fast -mp=gpu -gpu=managed -Minfo=mp,opt


For profiling GPU code use

nsys profile -t nvtx,cuda --stats=true --force-overwrite true -o laplace-gpu-parallel ./laplace-gpu-parallel

Lab 4: Data Management

OpenMP Structured Data Directive

For C:

Make a copy jacobi-gpu-data-structured.c of the file jacobi.c  and include the following directive at the right place with the right map clauses to create a data region:

#pragma omp target data <data clauses>
{
...
}

Compile the code using the following commands

nvc -fast -mp=gpu -Minfo=mp,opt -o laplace-gpu-data-structured-parallel jacobi-gpu-data-structured.c laplace2d-gpu-parallel.c

Run and profile the code on the compute node and compare with the previous profiling results.

For Fortran:

Make a copy jacobi-gpu-data-structured.f90 of the file jacobi.f90  and include the following directive at the right place with the right map clauses to create a data region:

!$omp target data <data clauses>
...
!$omp end target data

Compile the code using the following commands

nvfortran -mp=gpu -Minfo=mp,opt  -o laplace-gpu-data-structured-parallel jacobi-gpu-data-structured.f90 laplace2d-gpu-parallel.f90

Run and profile the code on the compute node and compare with the previous profiling results.

OpenMP Unstructured Data Directives

For C:

Make a copy laplace2d-gpu-data-unstructured-parallel.c of laplace2d-gpu-parallel.c.

Include the following directive at the end of the  initialize() function with the right data clauses 

#pragma omp target enter data <data clauses>

Include the following directive at the beginning of the  deallocate() function with the right data clauses

#pragma omp target exit data <data clauses>

Compile the code using the following commands

nvc -fast -mp=gpu -Minfo=mp,opt -o laplace-gpu-data-unstructured-parallel jacobi.c laplace2d-gpu-data-unstructured-parallel.c

If you get error messages, try to understand the problem and adapt the other files used during compilation accordingly.

Run and profile  the code on the compute node and compare with the previous profiling results.

For Fortran:

Make a copy laplace2d-gpu-data-unstructured-parallel.f90 of laplace2d-gpu-parallel.f90.

Include the following directive at the end of the  initialize() function with the right data clauses:

!$omp target enter data <data clauses>

Include the following directive at the beginning of the  deallocate() function with the right data clauses:

!$omp target exit data <data clauses>

Compile the code using the following commands

nvfortran -fast --mp=gpu -Minfo=mp,opt -o laplace-gpu-data-unstructured-parallel jacobi.f90 laplace2d-gpu-data-unstructured-parallel.f90

If you get error messages, try to understand the problem and adapt the other files used during compilation accordingly.

Run and profile  the code on the compute node and compare with the previous profiling results.

Solutions

The solutions can be found in the file OpenMP-solutions.tgz

Copy the solutions to your own home directory via