<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.snu.edu.in/index.php?action=history&amp;feed=atom&amp;title=Magus02%2FOpenMP_Usage</id>
	<title>Magus02/OpenMP Usage - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.snu.edu.in/index.php?action=history&amp;feed=atom&amp;title=Magus02%2FOpenMP_Usage"/>
	<link rel="alternate" type="text/html" href="https://wiki.snu.edu.in/index.php?title=Magus02/OpenMP_Usage&amp;action=history"/>
	<updated>2026-11-04T19:44:29Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.9</generator>
	<entry>
		<id>https://wiki.snu.edu.in/index.php?title=Magus02/OpenMP_Usage&amp;diff=1185&amp;oldid=prev</id>
		<title>Deepak: Created page with &quot;{{DISPLAYTITLE:OpenMP Usage — Magus02 HPC}} &lt;div style=&quot;background:#0d1b2a;border:1px solid #1e3a5a;border-radius:8px;padding:12px 18px;margin-bottom:20px;font-size:13px;fon...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.snu.edu.in/index.php?title=Magus02/OpenMP_Usage&amp;diff=1185&amp;oldid=prev"/>
		<updated>2026-04-20T06:43:09Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;{{DISPLAYTITLE:OpenMP Usage — Magus02 HPC}} &amp;lt;div style=&amp;quot;background:#0d1b2a;border:1px solid #1e3a5a;border-radius:8px;padding:12px 18px;margin-bottom:20px;font-size:13px;fon...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{DISPLAYTITLE:OpenMP Usage — Magus02 HPC}}&lt;br /&gt;
&amp;lt;div style=&amp;quot;background:#0d1b2a;border:1px solid #1e3a5a;border-radius:8px;padding:12px 18px;margin-bottom:20px;font-size:13px;font-family:monospace;color:#5ba3d9;&amp;quot;&amp;gt;&lt;br /&gt;
📍 [[Magus02/Knowledge_Base|Magus02 Knowledge Base]] → HPC User → OpenMP Usage&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
OpenMP (Open Multi-Processing) is the standard API for '''shared-memory parallel programming''' on multi-core processors. It uses compiler directives (pragmas) to parallelize loops and code regions across multiple threads on a single node.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== What is OpenMP? ==&lt;br /&gt;
&lt;br /&gt;
OpenMP allows a program to use multiple CPU cores within a single compute node by spawning '''threads''' that work simultaneously on different parts of the data. Unlike [[Magus02/MPI_Usage|MPI]], OpenMP threads share the same memory space — no message passing is needed.&lt;br /&gt;
&lt;br /&gt;
On Magus02:&lt;br /&gt;
* Each AMD EPYC 7763 Compute Node has '''128 cores''' — ideal for large OpenMP thread counts&lt;br /&gt;
* Each AMD EPYC 7543 High Memory Node has '''64 cores'''&lt;br /&gt;
* OpenMP does '''not''' scale across multiple nodes — use MPI or Hybrid jobs for that&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background:#0d1a2a;border-left:4px solid #00c9ff;border-radius:6px;padding:14px 18px;margin:16px 0;font-size:14px;color:#94a8be;&amp;quot;&amp;gt;&lt;br /&gt;
💡 No additional module is needed for OpenMP itself — OpenMP support is built into the compiler. You simply need to load your compiler module (Intel or GCC) and add the appropriate flag.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compiling OpenMP Code ==&lt;br /&gt;
&lt;br /&gt;
Add the OpenMP flag for your compiler when compiling:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;background:#0d1b2a;color:#94a8be;&amp;quot; | Compiler&lt;br /&gt;
! style=&amp;quot;background:#0d1b2a;color:#94a8be;&amp;quot; | Flag&lt;br /&gt;
! style=&amp;quot;background:#0d1b2a;color:#94a8be;&amp;quot; | Example Command&lt;br /&gt;
|-&lt;br /&gt;
| GNU (&amp;lt;code&amp;gt;gcc&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;gfortran&amp;lt;/code&amp;gt;) || &amp;lt;code&amp;gt;-fopenmp&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;gcc -fopenmp -O2 mycode.c -o myprogram&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Intel (&amp;lt;code&amp;gt;icc&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;ifort&amp;lt;/code&amp;gt;) || &amp;lt;code&amp;gt;-qopenmp&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;icc -qopenmp -O2 mycode.c -o myprogram&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Clang || &amp;lt;code&amp;gt;-fopenmp&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;clang -fopenmp -O2 mycode.c -o myprogram&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Oracle Studio || &amp;lt;code&amp;gt;-xopenmp&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;cc -xopenmp -O2 mycode.c -o myprogram&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| NAG Fortran || &amp;lt;code&amp;gt;-openmp&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;nagfor -openmp -O2 mycode.f90 -o myprogram&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Without the OpenMP flag, all &amp;lt;code&amp;gt;#pragma omp&amp;lt;/code&amp;gt; directives in your code are silently ignored and the program runs serially.&lt;br /&gt;
&lt;br /&gt;
=== Example: Compiling with Intel compiler ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ module purge&lt;br /&gt;
$ module load intel/oneapi&lt;br /&gt;
&lt;br /&gt;
# Compile an OpenMP C program:&lt;br /&gt;
$ icc -qopenmp -O2 -march=native omp_program.c -o omp_program&lt;br /&gt;
&lt;br /&gt;
# Compile an OpenMP Fortran program:&lt;br /&gt;
$ ifort -qopenmp -O2 -march=native omp_program.f90 -o omp_program&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Example: Compiling with GCC ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ module purge&lt;br /&gt;
$ module load gcc/11.2.0&lt;br /&gt;
&lt;br /&gt;
$ gcc -fopenmp -O2 -march=native omp_program.c -o omp_program&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Running an OpenMP Program ==&lt;br /&gt;
&lt;br /&gt;
=== Setting OMP_NUM_THREADS ===&lt;br /&gt;
&lt;br /&gt;
'''Always set &amp;lt;code&amp;gt;OMP_NUM_THREADS&amp;lt;/code&amp;gt;''' before running an OpenMP program. If unset, behaviour depends on the system default — sometimes it defaults to 1 (serial), sometimes to all available cores (potentially overloading the node).&lt;br /&gt;
&lt;br /&gt;
Set it for a single execution:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ OMP_NUM_THREADS=32 ./omp_program&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or export it to the environment for the session:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ export OMP_NUM_THREADS=64&lt;br /&gt;
$ ./omp_program&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In a Slurm jobscript, tie it to the allocated cores:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Complete Slurm Jobscript for OpenMP ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
#SBATCH --job-name=openmp_run&lt;br /&gt;
#SBATCH --partition=medium&lt;br /&gt;
#SBATCH --nodes=1&lt;br /&gt;
#SBATCH --ntasks=1&lt;br /&gt;
#SBATCH --cpus-per-task=64&lt;br /&gt;
#SBATCH --mem=256G&lt;br /&gt;
#SBATCH --time=06:00:00&lt;br /&gt;
#SBATCH --output=omp_%j.out&lt;br /&gt;
#SBATCH --error=omp_%j.err&lt;br /&gt;
&lt;br /&gt;
module purge&lt;br /&gt;
module load intel/oneapi&lt;br /&gt;
&lt;br /&gt;
# Set threads to match allocated cores:&lt;br /&gt;
export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK&lt;br /&gt;
&lt;br /&gt;
# Thread placement for NUMA-awareness:&lt;br /&gt;
export OMP_PLACES=cores&lt;br /&gt;
export OMP_PROC_BIND=close&lt;br /&gt;
&lt;br /&gt;
./omp_program input.dat&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Thread Pinning ==&lt;br /&gt;
&lt;br /&gt;
On Magus02's AMD EPYC nodes, each node has '''multiple NUMA domains''' (memory regions local to groups of cores). Pinning OpenMP threads to specific cores prevents the operating system from migrating threads between cores or NUMA domains, improving memory locality and performance.&lt;br /&gt;
&lt;br /&gt;
Key environment variables:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Variable !! Values !! Effect&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;OMP_PLACES&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;cores&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;threads&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sockets&amp;lt;/code&amp;gt; || Defines the &amp;quot;places&amp;quot; threads can be bound to&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;OMP_PROC_BIND&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;close&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;spread&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;master&amp;lt;/code&amp;gt; || Strategy for distributing threads across places&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Recommended for Magus02 (maximises cache locality):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export OMP_PLACES=cores&lt;br /&gt;
export OMP_PROC_BIND=close&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For jobs that benefit from spreading across NUMA domains:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export OMP_PLACES=sockets&lt;br /&gt;
export OMP_PROC_BIND=spread&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[Magus02/NUMA|NUMA Architecture]] for deeper explanation of why this matters on multi-socket nodes.&lt;br /&gt;
&lt;br /&gt;
== Verifying Parallelism ==&lt;br /&gt;
&lt;br /&gt;
After launching, check that threads are actually running in parallel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# From a separate terminal while the job runs (replace NODE with actual node name):&lt;br /&gt;
$ ssh NODE&lt;br /&gt;
$ top&lt;br /&gt;
# You should see your program using well over 100% CPU (e.g. 6400% for 64 threads)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Within your program, you can print the thread count:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;omp.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    #pragma omp parallel&lt;br /&gt;
    {&lt;br /&gt;
        int tid = omp_get_thread_num();&lt;br /&gt;
        int nthreads = omp_get_num_threads();&lt;br /&gt;
        if (tid == 0)&lt;br /&gt;
            printf(&amp;quot;Running with %d threads\n&amp;quot;, nthreads);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
* [[Magus02/NUMA|NUMA Architecture — Thread Pinning]]&lt;br /&gt;
* [[Magus02/Batch_Scheduler|Batch Scheduler — OpenMP Jobscript]]&lt;br /&gt;
* [[Magus02/MPI_Usage|MPI Usage — Distributed Parallelism]]&lt;br /&gt;
* [[Magus02/Compiler|Compilers on Magus02]]&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-family:monospace;font-size:11px;color:#484f58;text-align:right;&amp;quot;&amp;gt;&lt;br /&gt;
[[Magus02/Knowledge_Base|↑ Back to Knowledge Base]] · Maintained by HPC Administration · wiki.snu.edu.in&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Deepak</name></author>
	</entry>
</feed>