hostname: xcrescox001-060.enea.frascati.it
early availability: July 7, 2024
start of production: September 30, 2024
This system is a small partition of CINECA MARCONI 100 dismissed in 2023. It is an accelerated cluster based on Power9 chips and Volta NVIDIA GPUs, assigned by CINECA within the ENEA-CINECA agreement.
Architecture: IBM
Power 9 AC922
Internal Network: Mellanox
Infiniband EDR 100 Gb/s
Storage: 140
TB (usable) NFS of local storage
Login nodes: 2 Login IBM Power9 LC922 (similar to the compute nodes)
|
Model: IBM Power AC922 (Whiterspoon) Racks: 3 total |
|
Peak performance details
The peak performance of XCRESCO (58 compute
nodes + 2 login nodes) is about 1.9PFlops. The performance of the single node
is 32 TFlops due to 0.8 for the CPU part and 7.8x4 for the four GPUs on the
node.
The theoretical peak performance is 60*(0,8+4*7,8) = 1.92 PFlop/s
In the below table you can find the single node theoretical peak performance of
the AC992 CN node with two Power9 processors and four NVIdia V100 GPUs.
|
Node Performance |
||
|
Theoretical |
CPU (nominal/peak freq.) |
691/791 GFlops |
|
GPU |
31.2 TFlops |
|
|
Total |
32 TFlops |
|
|
Memory Bandwidth (nominal/peak freq.) |
220/300 GB/s |
|
All the login nodes have an identical environment and can be reached with SSH (Secure Shell) protocol using the hostname:
> xcrescox001.frascati.enea.it > xcrescox002.frascati.enea.it
The storage organization conforms to the CRESCO infrastructure (see Section Data Management and Filesystems).
In addition to the home directory $HOME, for each user is defined a scratch area $PFS_SCRATCH_1, a NFS storage area shared with all compute and login nodes.
It is also available a temporary storage local on compute nodes accessible as /tempwork
The software modules are collected in different profiles and organized by functional categories (compilers, libraries, tools, applications,..). The profiles are of two types: “programming” type (base and advanced) for compilation, debugging and profiling activities, and “domain” type (chem-phys, lifesc,..) for the production activity. They can be loaded together.
"Base" profile is the default. It is automatically loaded after login and it contains basic modules for the programming activities (gnu, nvidia-sdk compilers, math libraries, profiling and debugging tools,..).
If you want to use a module placed under other profiles, for example an application module, you will have to load preventively the corresponding profile:
>module load profile/<profile name> >module load autoload <module name>
For listing all profiles you have loaded you can use the following command:
>module list
In order to detect all profiles, categories and modules available on MARCONI100 the command “modmap” is available. With modmap you can see if the desired module is available and which profile you have to load to use it.
>modmap -m <module_name>
GPU and intra/inter connection environment
XCRESCO consists of 58 compute nodes and 2 login nodes, connected with a Mellanox Infiniband EDR network arranged in a ring topology.
The login nodes and the compute nodes are exactly the same. Each node consists in 2 Power9 sockets, each of them with 16 cores and 2 Volta GPUs (32 cores and 4 GPUs per node). The multi-threading is active with 4 threads per physical core (128 total threads – or logical cpus – per node).

Due to how the hardware is detected on a Power9 architecture, the numbering of (logical) cpus follows the order of threading. You can get it with the ppc64_cpu command:
$ ppc64_cpu --infoCore 0: 0* 1* 2* 3*Core 1: 4* 5* 6* 7*Core 2: 8* 9* 10* 11*Core 3: 12* 13* 14* 15*...... (Cores from 4 to 28)........Core 29: 116* 117* 118* 119* Core 30: 120* 121* 122* 123*Core 31: 124* 125* 126* 127*
The topology of the node can be visualized by running the command nvidia-smi as follows:
$ nvidia-smi topo -m GPU0 GPU1 GPU2 GPU3 NIC0 NIC1 CPU Affinity NUMA Affinity GPU NUMA IDGPU0 X NV3 SYS SYS SYS SYS 0-63 0 N/AGPU1 NV3 X SYS SYS SYS SYS 0-63 0 N/AGPU2 SYS SYS X NV3 SYS SYS 64-127 8 N/AGPU3 SYS SYS NV3 X SYS SYS 64-127 8 N/ANIC0 SYS SYS SYS SYS X SYS NIC1 SYS SYS SYS SYS SYS X Legend: X = Self SYS = Connection traversing PCIe as well as the SMP interconnect between NUMA nodes (e.g., QPI/UPI) NODE = Connection traversing PCIe as well as the interconnect between PCIe Host Bridges within a NUMA node PHB = Connection traversing PCIe as well as a PCIe Host Bridge (typically the CPU) PXB = Connection traversing multiple PCIe bridges (without traversing the PCIe Host Bridge) PIX = Connection traversing at most a single PCIe bridge NV# = Connection traversing a bonded set of # NVLinks NIC Legend: NIC0: mlx5_0 NIC1: mlx5_1
From the output of the command it is possible to see that GPU0 and GPU1 are connected with the NVLink (NV3), as well as the couple GPU2 & GPU3. The first couple is connected to (virtual) cpus 0-63 (on the first socket), the second to (virtual) cpus 64-127 (on the second socket). The cpus are numbered from 0 to 127 because of a hyperthreading. The two Power9 sockets are connected by a 64 GBps X bus. Each of them is connected with 2 GPUs via NVLink 2.0.
The knowledge of the topology of the node is important for correctly distribute the parallel threads of your applications in order to get the best performances.
The internode communications is based on a Mellanox Infiniband EDR network 100 Gb/s, and the OpenMPI are configured so to exploit the Mellanox Fabric Collective Accelerators (also on CUDA memories) and Messaging Accelerators.
Since XCRESCO is a general purpose system and it is used by several users at the same time, long production jobs must be submitted using a queuing system (scheduler). This guarantees that the access to the resources is as fair as possible. On XCRESCO the available scheduler is SLURM (our documentation on SLURM can be found here.)
XCRESCO is based on a policy of node sharing among different jobs, i.e. a job can ask for resources and these can also be a part of a node, for example few cores and 1 GPUs. This means that, at a given time, one physical node can be allocated to multiple jobs of different users. Nevertheless, exclusivity at the level of the single core and GPU is guaranteed by low-level mechanisms.
Roughly speaking, there are two different modes to use an HPC system: Interactive and Batch:
Interactive
A serial program can be executed in the standard UNIX way:
> ./program
This is allowed only for very short runs on the login nodes, since the interactive environment has a 10 minutes cpu-time limit. Please do not execute parallel applications on the login nodes!
A serial (or parallel) program, also using GPUs and needing more than 10 minutes can be executed interactively within an "interactive" SLURM batch job.
A request for resources allocation on the compute nodes is delivered to SLURM with salloc/srun commands, the request is queued and scheduled as any other batch job but, when granted, the standard input, output, and error streams of the interactive job connected to the terminal session from which the request was launched.
For example, to start an interactive session on one node and get the full node in exclusive way (including the four GPUs) for one hour, launch the command:
> > salloc -N1 --exclusive --gres=gpu:4 -A enea -p xcresco --time=01:00:00salloc: Granted job allocation 1174 … Run here your applications using srun or mpirun for example: - srun -n 1 serial.exe (serial or OpenMP application) - srun -n 4 parallel.exe (MPI or mixed application) Stop the session with exit or ^Dexitsalloc: Relinquishing job allocation 1174> In the following is reported an interactive job on 2 cores and two GPUs. Within the job a parallel (MPI) program using 2 MPI tasks and two GPUs is executed. Since the request of tasks per node (--ntasks-per-node) refers to the 128 (virtual) cpus, if you want 2 physical cores you also have to specify that each task is made of 4 (virtual) cpus (--cpus-per-tasks=4). > salloc -N1 --ntasks-per-node=2 --cpus-per-task=4 --gres=gpu:2 -A enea -p xcresco --time=01:00:00salloc: Granted job allocation 1175> srun ./myprogram….> exit
SLURM automatically exports the environment variables you defined in the source shell, so that if you need to run your program "myprogram" in a controlled environment (i.e. specific library paths or options), you can prepare the environment in the origin shell being sure to find it in the interactive shell.
A more specific description of the options used by salloc/srun to allocate resources or to give direction to SLURM on how to place tasks and threads on the resources (pinning) is reported later in the “Batch” section, because they are the same of the sbatch command described there.
An alternative way to submit an interactive session using the srun command is as follows:
> srun --nodes=1 --ntasks-per-node=2 --cpus-per-task=64 -p xcresco --pty /bin/bash
In this way an interactive session start on a single compute node with cpus/cores fully allocated.
In a FARO session, an X11 interactive session can be run with the option --x11 and 10 hours time as follows:
> srun --x11 --nodes=1 -t 10:00:00 --ntasks-per-node=2 --cpus-per-task=64 -p xcresco --pty /bin/bash
N.B: you have to export the DISPLAY environment variable.
Batch
As usual on HPC systems, the large production runs are executed in batch mode. This means that the user writes a list of commands into a file (for example script.x) and then submits it to a scheduler (SLURM for XCRESCO) that will search for the required resources in the system. As soon as the resources are available script.x is executed and the results and sent back to the user.
This is an example of script file:
#!/bin/bash #SBATCH -A enea#SBATCH -p xcresco#SBATCH --time 12:10:00 # format: HH:MM:SS#SBATCH -N 6 # 6 nodes#SBATCH --ntasks-per-node=8 # 8 tasks out of 128#SBATCH --cpus-per-task=16 # 16 cores out of 128#SBATCH --gres=gpu:4 # 4 gpus per node out of 4#SBATCH --mem=246000MB # memory per node out of 246000MB#SBATCH --job-name=HPL#SBATCH --err=%j_%A_%a.err#SBATCH --out=%j_%A_%a.out#SBATCH --mail-type=ALL#SBATCH --mail-user=frsncesco.iannone@enea.itexport OMP_NUM_THREADS=16srun--mpi=pmix_v3 ./xhpl
> sbatch script.x
The script file must contain both directives to SLURM and commands to be executed, as better described in the section Batch Scheduler SLURM.
Using SLURM directives you indicate the account_number (-A: which project pays for this work), where to run the job (-p: partition), what is the maximum duration of the run (--time: time limit). Moreover you indicate the resources needed, in terms of cores, GPUs and memory.
One of the commands will be probably the launch of a parallel MPI application. In this case the right command is srun, as an alternative to the usual mpirun command. In this way you will get full support for process tracking, accounting, task affinity, suspend/resume and other features.
SLURM partitions
A list of partitions defined on the cluster, with access rights and resources definition, can be displayed with the command sinfo:
> sinfo -o "%10D %20F %P"
The command returns a more readable output which shows, for each partition, the total number of nodes and the number of nodes by state in the format "Allocated/Idle/Other/Total".
In the following table you can find the main features and limits imposed on the partitions of XCRESCO.
Note: core refers to a physical cpu, with its 4 HTs; cpu refers to a logical cpu (1 HT). Each node has 32 cores/128 cpus.
|
SLURM partition |
Job QOS |
nodes / GPUs |
max walltime |
max running jobs per user/ max n. of cores/nodes/GPUs per user |
priority |
|
xcresco |
normal |
max = 16 nodes per jobs max mem= 246GB per nodes |
24:00:00 |
TbD
TbD |
40 |
|
TbD |
TbD |
TbD |
TbD |
TbD |
XCRESCO specific information
In the following we report information specific to XCRESCO, as well as examples suited for this kind of system.
Each node exposes itself to SLURM as having 128 (virtual) cpus, 4 GPUs and 246.000 MB memory. SLURM assigns a node in shared way, assigning to the job only the resources required and allowing multiple jobs to run on the same node/nodes. If you want to have the node/s in exclusive mode, use the SLURM option “--exclusive” together with “--gres=gpu:4”.
The maximum memory which can be requested is 246.000 MB (average memory per physical core ~ 7GB) and this value guarantees that no memory swapping will occur.
Even if the nodes are shared among users, exclusivity is guaranteed for the single physical core and the single GPU. When you ask for “tasks” (--ntasks-per-node), SLURM gives you the requested number of (virtual) cpus rounded on multiple of four. For example
#SBATCH --ntasks-per-node = 1 (or 2, 3, 4) → 1 core#SBATCH --ntasks-per-node = 13 (or 14, 15, 16) → 4 cores
By default the number of (virtual) cpus per task is one, but you can change it.
#SBATCH --ntasks-per-node=8#SBATCH --cpus-per-task=4
In this way each tasks will correspond to one (physical) core.
XCRESCO GPU use report
A statistics of the GPU utilization during a job, provided by nvidia dcgmi tool, can be obtained at the end of the job by explicitly requesting the constraing "gpureport":
#SBATCH --constraint=gpureport (or -C gpureport)
This option will result, at the end of the job, in producing a file for each of the nodes assigned to the job with the relevant information on the employed GPUs (performance statistics, such as Energy Consumed, Power Usage, Max GPU Memory Used, GPU and Memory Used etc.; Event Stats, as ECC Errors etc.; Slowdown Stats; Overall Health). The files are named "dcgmi_stats_<node_name>_<jobid>.out".
Submitting batch jobs for production
Examples
> salloc -N1 --ntasks-per-node=2 --cpus-per-task=4 --gres=gpu:2 --partition=.... export OMP_NUM_THREADS=4
mpirun ./myprogram
Two full cores on one node are requested, as well as 2 GPUs. A hybrid code is executed with 2 MPI tasks and 4 OMP threads, exploiting the HT capability of XCRESCO. Since 2 GPUs are used, 16 cores will be accounted to this job.
For the OpenMPI environment, both srun and mpirun can be used.
> salloc -N1 --ntasks-per-node=4 --cpus-per-task=16 --gres=gpu:2 --partition=... export OMP_NUM_THREADS=16
export OMP_PLACES=threadsmpirun ./myprogramORsrun --mpi=pmix_v3 ./myprogram 16 full cores are requested and 2 GPUs. The 16x4 (virtual) cpus are used for 4 MPI tasks and 16 OMP threads per task. The -m flag in the srun command specifies the desired process distribution between nodes/socket/cores (the default is block:cyclic). Please refer to srun manual for more details on the processes distribution and binding. > salloc -N1 --ntasks-per-node=32 --cpus-per-task=4 --gres=gpu:2 --partition=... export OMP_NUM_THREADS=4mpirun ./myprogram 32 full cores are requested and 2 GPUs. The 32x4 (virtual) cpus are used for 32 MPI tasks and 4 OMP threads. In this way you are asking for entire node and you can ask for 2 or 3 or 4 GPUs, because you can obtain only cores related to the requested GPUs.
If a graphic session is desired we recommend to use the tool FARO.
XCRESCO login and compute nodes host four Tesla Volta (V100) GPUs per node (CUDA compute capability). The most recent versions of nVIDIA CUDA toolkit and of the Community Edition PGI compilers (supporting CUDA Fortran) is available in the module environment, together with a set of GPU-enabled libraries, applications and tools.
The programming environment of the XCRESCO cluster consists of a choice of compilers for the main scientific languages (Fortran, C and C++), debuggers to help users in finding bugs and errors in the codes, profilers to help in code optimisation.
If you use a given set of compilers and libraries to create your executable, very probably you have to define the same "environment" when you want to run it. This is because, since by default linking is dynamic on Linux systems, at runtime the application will need the compiler shared libraries as well as other proprietary libraries. This means that you have to specify "module load" for compilers and libraries, both at compile time and at run time. To minimize the number of needed modules at runtime, use static linking to compile the applications.
Compilers
You can check the complete list of available compilers on MARCONI with the command:
> module available
and checking the "compilers" section. The available compilers are:
- NVIDIA HPC-SDK (ex PGI with CUDA integrated)
- GNU
NVIDIA HPC SDK (ex PORTLAND PGI + NVIDIA CUDA)
As of August 5, 2020, the "PGI Compilers and Tools" technology is a part of the NVIDIA HPC SDK product, available as a free download from NVIDIA.
|
Invocations |
Usage |
|
nvc |
Compile C source files (C11 compiler. It supports GPU programming with OpenACC, and supports multicore CPU programming with OpenACC and OpenMP) |
|
nvc++ |
Compile C++ source files (C++17 compiler. It supports GPU programming with C++17 parallel algorithms (pSTL) and OpenACC, and supports multicore CPU programming with OpenACC and OpenMP) |
|
nvfortran |
Compile FORTRAN source files (supports ISO Fortran 2003 and many features of ISO Fortran 2008. It supports GPU programming with CUDA Fortran and OpenACC, and supports multicore CPU programming with OpenACC and OpenMP) |
|
nvcc |
CUDA C and CUDA C++ compiler driver for NVIDIA GPUs |
For legacy reasons, the nVIDIA HPC SDK suite also offers the PGI C, C++, and Fortran compilers with their original names:
|
Invocations |
Usage |
|
pgcc |
Compile C source files. |
|
pgc++ |
Compile C++ source files. |
|
pgf77 |
Compile FORTRAN 77 source files |
|
pgf90 |
Compile FORTRAN 90 source files |
|
pgf95 |
Compile FORTRAN 95 source files |
The OpenMP parallelization is enabled by the -mp compiler option. The GPU offload via OpenMP is enabled by the -mp=gpu option
GNU compilers
The gnu compilers are always available but they are not the best optimizing compilers, it ensures the maximum portability. You do not need to load the module for using them.
The name of the GNU compilers are:
- g77: Fortran77 compiler
- gfortran: Fortran95 compiler
- gcc: C compiler
- g++: C++ compiler
The documentation can be obtained with the man command after loading the gnu module:
> man gfortan
> man gcc
Debugger and Profilers
If at runtime your code dies, then there is a problem. In order to solve it, you can decide to analyze the core file (core not available with PGI compilers) or to run your code using the debugger.
Compiler flags
Whatever your decision, in any case, you need to enable compiler runtime checks, by putting specific flags during the compilation phase. In the following we describe those flags for the different Fortran compilers: if you are using the C or C++ compiler, please check before because the flags may differ.
The following flags are generally available for all compilers and are mandatory for an easier debugging session:
-O0 Lower level of optimization-g Produce debugging information
Other flags are compiler specific and are described in the following:
PORTLAND Group (PGI) Compilers
The following flags are useful (in addition to "-O0 -g") for debugging your code:
-C Add array bounds checking-Ktrap=ovf,divz,inv Controls the behavior of the processor when exceptions occur: FP overflow, divide by zero, invalid operands
GNU Fortran compilers
The following flags are useful (in addition to "-O0 -g")for debugging your code:
-Wall Enables warnings pertaining to usage that should be avoided-fbounds-check Checks for array subscripts.
Debuggers available
Totalview
The TotalView debugger is a programmable
tool that lets you debug, analyze, and tune the performance of complex serial,
multiprocessor, and multithreaded programs.
TotalView has many features and it gives you a great number of
tools for finding your program's problems.
Details on how to use totalview are in
https://docs.roguewave.com/en/totalview/current/html/
PGI: pgdbg (serial/parallel debugger)
pgdbg is the Portland Group Inc. symbolic source-level debugger for F77, F90, C, C++ and assembly language programs. It is capable of debugging applications that exhibit various levels of parallelism.
GNU: gdb (serial debugger)
GDB is the GNU Project debugger and allows you to see what is going on 'inside' your program while it executes -- or what the program was doing at the moment it crashed.
VALGRIND
Valgrind is a framework for building dynamic analysis tools. There are Valgrind tools that can automatically detect many memory management and threading bugs, and profile your programs in detail. The Valgrind distribution currently includes six production-quality tools: a memory error detector, two thread error detectors, a cache and branch-prediction profiler, a call-graph generating cache profiler, and a heap profiler.
Valgrind is Open Source / Free Software, and is freely available under the GNU General Public License, version 2.
Profilers (gprof)
In software engineering, profiling is the investigation of a program's behavior using information gathered as the program executes. The usual purpose of this analysis is to determine which sections of a program to optimize - to increase its overall speed, decrease its memory requirement or sometimes both.
A (code) profiler is a performance analysis tool that, most commonly, measures only the frequency and duration of function calls, but there are other specific types of profilers (e.g. memory profilers) in addition to more comprehensive profilers, capable of gathering extensive performance data.
gprof
The GNU profiler gprof is a useful tool for measuring the performance of a program. It records the number of calls to each function and the amount of time spent there, on a per-function basis. Functions which consume a large fraction of the run-time can be identified easily from the output of gprof. Efforts to speed up a program should concentrate first on those functions which dominate the total run-time.
gprof uses data collected by the -pg compiler flag to construct a text display of the functions within your application (call tree and CPU time spent in every subroutine). It also provides quick access to the profiled data, which let you identify the functions that are the most CPU-intensive. The text display also lets you manipulate the display in order to focus on the application's critical areas.
Usage:
> gfortran -pg -O3 -o myexec myprog.f90> ./myexec> ls -ltr ....... -rw-r--r-- 1 usr0 enea 506 Apr 6 15:33 gmon.out> gprof myexec gmon.out
It is also possible to profile at code line-level (see "man gprof" for other options). In this case, you must use also the “-g” flag at compilation time:
> gfortran -pg -g -O3 -o myexec myprog.f90> ./myexec> ls -ltr ....... -rw-r--r-- 1 usr0 enea 506 Apr 6 15:33 gmon.out> gprof -annotated-source myexec gmon.out
It is possible to profile MPI programs. In this case, the environment variable GMON_OUT_PREFIX must be defined in order to allow to each task to write a different statistical file. Setting
export GMON_OUT_PREFIX=<name>
once the run is finished each task will create a file with its process ID (PID) extension
<name>.$PID
If the environmental variable is not set every task will write the same gmon.out file.
GPU profilers (Nvidia Nsight System)
Nvidia Nsight System is a system-wide
performance analysis tool designed to visualize an application’s algorithms,
help you identify the largest opportunities to optimize, and tune to scale
efficiently across any quantity or size of CPUs and GPUs; from large server to
our smallest SoC.
You can find general info on how to use it in the dedicated Nvidia User Guide pages.
On XCRESCO only the Command Line Interface (CLI) is available since the GUI does not support Power9 nodes. Our suggestion is to run the CLI inside your job script in order to generate the qdrep files. Then you can download the qdrep files on your local PC and visualize them with the Nsight System GUI available on your workstation.
The profiler is available under the modules hpc-sdk, cuda/11.0 and later versions.
Standard usage of an MPI job running on GPU is
> mpirun <options> nsys profile -o ${PWD}/output_%q{OMPI_COMM_WORLD_RANK} -f true --stats=true --cuda-memory-usage=true <your_code> <input> <output>
On the single node you can also run the profiler as "nsys profile mpirun", but keep in mind that with this syntax nsys will put everything in a single report.
Unfortunately nsys usually generates several
files in /tmp dir of the compute node even if a TMPDIR environment variable is
set. These files may be big causing the filling
of the /tmp folder and, as a consequence, the crash of the compute
node and the failure of
the job.
In order to avoid such a problem we strongly suggest to include in your sbatch
script the following lines around your mpirun call as a workaround:
> rm -rf /tmp/nvidia> ln -s $TMPDIR /tmp/nvidia> mpirun ... nsys profile .....> rm -rf /tmp/nvidia
This will place the temporary outputs of the
nsys code in your TMPDIR folder.
This workaround may cause conflicts between multiple jobs running this profiler
on a compute node at the same time, so we strongly suggest also to request the
compute node exclusively:
#SBATCH --exclusive
Nsight Systems can also collect kernel IP samples and backtraces, however, this is prevented by the perf event paranoid level being set to 2 on XCRESCO. It is possible to bypass this restriction by adding the SLURM directive:
#SBATCH --gres=sysfs
Along with the exclusive one.
MPI environment
We offer two options for MPI environment on
XCRESCO:
> OpenMPI
Here you can find some useful details on how to use them on XCRESCO.
OpenMPI
This most common MPI implementation is
installed inside the GNU environment.
It is configured to support both CUDA-aware and GPUDirect.
The openmpi module provides the following wrappers:
|
compiler |
wrapper |
Usage |
|
gcc |
mpicc |
Compile C source files with GNU |
|
g++ |
mpic++ |
Compile C++ source files with GNU |
|
gfortran |
mpif77 |
Compile FORTRAN source files with GNU |

