Content from Why I/O matters


Last updated on 2026-10-28 | Edit this page

Estimated time: 15 minutes

Overview

Questions

  • What is the difference between a metadata server and a data server?
  • Why do a thousand small files cost more than one file of the same total size?
  • Which of three files belongs on home?

Objectives

  • Separate a file’s name and permissions from the bytes of the file.
  • Explain why many small files put extra work on the metadata server.
  • Choose home for a small source file, and not for a 10 GB working file.

A job does three kinds of work


An HPC application computes, it sends messages between processes, and it reads and writes files. This lesson is the third of those. The other two can be fast and the job can still sit idle, waiting on the file system.

Input is not one thing. A grid, a genome, or a climate field can be a huge file that many processes read. A job parameter file is small. Output is not one thing either. A checkpoint is large and has to be precise, because the next job starts from it. An analysis file can be a subset. A progress log is a short text file from one process.

Those files do not all belong on the same disk. The next episode names the disks. This episode is why the choice changes the runtime.

The metadata server and the data servers


A parallel file system splits the work across two roles.

The metadata server records the name, the owner, the permissions, the size, and the location of the bytes. Creating a file, opening it, listing a directory, and asking for its size all talk to the metadata server. The record for one file is an inode. A quota can count inodes as well as bytes.

The data servers hold the bytes. Once the metadata server has said where a large file lives, the read and the write talk to the data servers.

ls of a directory with a huge number of names is almost all metadata. Reading one 10 GB file is one metadata lookup and then a long transfer from the data servers. The second case is what the fast disks are built for. The first case can leave those disks idle while the metadata server has a queue of its own.

On Snellius the scratch areas share a GPFS file system. A path that realpath prints under /gpfs/scratch1/ is that file system. Home is a different file system: smaller, and backed up. You will use both. You should not use them for the same kind of file.

Where a file goes. The nodes drawn are home, scratch-shared, project, and scratch-node. The arrows read large job output, files the group shares, and hottest temporary files.
Where a file goes. The nodes drawn are home, scratch-shared, project, and scratch-node. The arrows read large job output, files the group shares, and hottest temporary files.

Why many small files hurt


One thousand files of 1 MB hold the same 1 GB as one file of 1 GB. They are not the same amount of work.

Each small file is a create, an open, a write, a close, and a name to store. That is a thousand trips to the metadata server for a modest amount of data. A copy of the directory repeats the work on the destination: a thousand creates, not one.

One archive of those files is one metadata record and one stream of bytes. The copy is then one lookup and one transfer. The data servers do the work. The metadata server does little. Random bytes do not shrink when you compress them. What you save is the number of files, not the number of bytes. A later episode times the copy. The reason is this one.

The same cost shows up in a quota. Home on Snellius has a cap on inodes as well as a cap on bytes. A tree of tiny files can hit the inode cap while du still shows free space.

What home is for


Home is the small, backed-up place. A source file you will edit next week belongs there. If you delete it by mistake, the backup can still have it. On Snellius that backup keeps a deleted home file for three weeks.

A 10 GB file that a job is still writing does not belong there. It is large, it is temporary, and putting it through the backup helps no one. A result you must keep until the project ends is a third case. Scratch will expire. Home will fill. The next episode gives that result a project path and, on Snellius, an archive.

Discussion

Which file belongs on home?

You have three files:

  1. A source file of a few kilobytes that you will edit next week.
  2. A 10 GB file a job is writing and will not need after the run.
  3. A result you must keep until the project ends.

Which one belongs on home? Where do the other two go?

Only the source file belongs on home. It is small, you will change it, and the backup is there if the edit goes wrong.

The 10 GB file is scratch. It is working data. It should not sit on the backed-up disk, and it should not stay after the run.

The result you must keep does not go to the 14-day scratch, and it does not go to home if it is large. It goes to the project space, which lasts for the life of the project. On Snellius a long-term copy can also go to the archive. The next episode names the paths and the lifetimes.

Key Points
  • The metadata server stores names, permissions, and locations. The data servers store bytes.
  • A thousand small files mean a thousand metadata operations. One archive means one.
  • Home is for the small source file. A 10 GB working file is scratch. A result you must keep is project space.

Content from The file systems


Last updated on 2026-10-28 | Edit this page

Estimated time: 30 minutes

Overview

Questions

  • How long does a file last on home, on scratch-shared, in $TMPDIR, and on the project space?
  • What does a Snellius quota line say, and what do you run when myquota is not there?

Objectives

  • Match home, scratch-shared, scratch-local, scratch-node, project, and archive to a lifetime.
  • Read a 200 GiB home quota and a three-week restore window for deleted home files.
  • Use the tab’s paths on the course cluster instead of the Snellius paths.

Six places on Snellius


A path decides the speed, the backup, and the day the file disappears. On Snellius the layout is a table. Learn the table, then read the tab. If your tab does not list a path, that path is not on your machine. Do not create it because the table has the name.

Place Speed Size Backed up When it ends
/home Normal 200 GiB Yes Project end, plus 15 weeks
/scratch-shared Fast 8 TiB, shared with scratch-local No 14 days
/scratch-local Fast Counted in that 8 TiB No 6 days
/scratch-node Very fast The node disk, no quota No End of the job
/projects Fast On demand No End of the project
/archive Very slow On demand Yes End of the project

Home is /home/$USER. The quota is 200 GiB. The file system is backed up overnight. A home file that has already been backed up can be restored for three weeks after you delete it. The directory itself lasts until the project ends, plus 15 weeks. Three weeks is how long a deleted file stays in the backup. Fifteen weeks after the project is when the directory itself goes away.

Home is the right place for scripts, configuration, and small inputs. It is a poor place for a multi-gigabyte output. The backup has to copy what you put there, and the quota is the smallest cap in the table.

Scratch is fast temporary space. The default scratch quota is 8 TiB, counted across scratch-local and scratch-shared for your user. There is no backup.

Scratch-shared is /scratch-shared. The login node and the compute nodes can see it. You make your own directory, /scratch-shared/$USER. Data that sits unused is removed after 14 days. Use it for large job output that other nodes, or a later job this week, must read.

Scratch-local is a directory on that same GPFS scratch, created for a job and reached as $TMPDIR. The path looks like /scratch-local/$USER.$SLURM_JOB_ID. realpath shows a GPFS path under /gpfs/scratch1/nodespecific/. The directory is specific to the job. A second job on the same node gets a different directory. The table gives it 6 days. It counts against the 8 TiB quota, so old job directories still count until they expire.

Scratch-node is NVMe on the node itself. $TMPDIR points at your directory under /scratch-node when the job asked for it. It is removed when the job ends, so a result you need has to be copied off before the script exits. There is no quota and no backup. On Snellius it is not on every node. Fat nodes have it, and a subset of the rome, genoa, and GPU nodes have it. The request is --constraint=scratch-node. A shared node gives you a portion of that disk, not the whole device.

Project space is /projects. It is fast, it is not backed up, and it lasts until the project ends. This is the place for a result the group must keep, and for data that is too big for home. The size is on demand.

Archive is /archive. It is very slow, it is backed up, and it lasts until the project ends. It is for data you will not read during the run. The Snellius tab below names it as tape, and as a path you use from the login and staging nodes.

Where a file goes. The nodes drawn are home, scratch-shared, project, and scratch-node. The arrows read large job output, files the group shares, and hottest temporary files.
Where a file goes. The nodes drawn are home, scratch-shared, project, and scratch-node. The arrows read large job output, files the group shares, and hottest temporary files.

The course cluster does not have this list


The table is Snellius. The course cluster has a shorter set of paths. Read them from the tab. Do not type /scratch-shared, /scratch-node, or /archive unless the tab lists them.

Place Path What it is for
Home /home/$USER Shared with the compute nodes
Project /project Shared
Scratch /scratch Shared with the manager, not a separate parallel scratch
Node disk $TMPDIR This job only. Removed when the job ends

There is no /scratch-shared, no /scratch-node, and no /archive.

On the course cluster the tab has home, a project path, a scratch path, and $TMPDIR for the job. There is no /scratch-shared, no /scratch-node, and no /archive. $TMPDIR is removed when the job ends. A file on the login node’s scratch is not the same file as a compute node’s scratch. The later episode writes job files inside the job.

Read the quota before you fill it


The command depends on the machine. On Snellius, myquota prints bytes and inodes for home and for scratch. A home line from the documentation looks like this:

scur1448@home4|GiB:quota=200.00,limit=210.00,usage=0.0000%|Inodes:quota=1000000,limit=1200000,usage=0.0008%

quota is the amount you are given. limit is a little above that. usage is how full you are. Home is 200 GiB and 1,000,000 inodes. Scratch is 8 TiB across scratch-local and scratch-shared. Inodes are the metadata count from the previous episode. A small usage on bytes can still sit next to a full inode quota if the directory is many tiny files.

On the course cluster there is no myquota. df -h prints size, used, and free for a mount. du -sh ~ prints one size for your home.

Callout

Type along

Run the command in the tab. Read the home number before you copy a large tree.

There is no myquota here.

BASH

[YOUR_LOGIN@LOGIN ~]$ df -h /home /project /scratch
[YOUR_LOGIN@LOGIN ~]$ du -sh ~

A job directory is not a place you keep


$TMPDIR inside a job is space for that job. Copy anything you must keep to home or to the project path before the script exits. The login node’s $TMPDIR is a different directory. Do not prepare a job’s files there and expect the compute node to see them.

$TMPDIR in a job is /localscratch/$USER.$SLURM_JOB_ID.0 on the node’s own disk. The cluster deletes it when the job ends. There is one login node, so compare the login node’s /tmp with a job’s $TMPDIR.

Scratch-node is the fast case of the same idea, and only on Snellius. The constraint is how you ask for a node that has the disk. The course cluster tab tells you to drop the constraint.

There is no --constraint=scratch-node. $TMPDIR is already on the node’s own disk. Drop the constraint and write to $TMPDIR.

Challenge

Which file is still there?

A job writes the same run.dat in three places:

  • A. /scratch-shared/$USER/run.dat on Snellius
  • B. $TMPDIR/run.dat in a scratch-node job on Snellius, or the job’s $TMPDIR on the course cluster
  • C. the project path from your tab, for example /projects/$USER/run.dat on Snellius

Nobody touches the files afterwards. Which copies still exist after the job ends? Which still exist 14 days later? Which still exist when the project ends?

After the job ends, A and C are still there. B is gone. Scratch-node is removed at the end of the job. On the course cluster the job’s $TMPDIR is removed at the end of the job as well. The login node cannot open that path in the afternoon.

Fourteen days later, A is gone. Unused scratch-shared data is removed after 14 days. C is still there. B was already gone.

When the project ends, C ends with the project. A ended at 14 days. B ended with the job. Home is not one of these three. Home would last until the project ends plus 15 weeks, and a deleted home file can be restored for three weeks, but a large run.dat should not have been put there.

Scratch-local, the $TMPDIR you get without --constraint=scratch-node on Snellius, has its own lifetime. The table gives it 6 days, and it is not path B.

Key Points
  • Snellius home is 200 GiB, backed up, with three weeks of deleted files in the backup.
  • Scratch-shared lasts about 14 days. Scratch-local lasts about 6 days. Scratch-node ends with the job.
  • Project space and the archive last until the project ends. The archive is the slow, backed-up copy.
  • The course cluster tab replaces this list. Do not invent /scratch-shared there.
  • myquota is the Snellius report. df -h and du -sh are the tools when it is absent.

Content from Files and directories


Last updated on 2026-10-28 | Edit this page

Estimated time: 35 minutes

Overview

Questions

  • How do you see the directory you are in, and how do you make a directory on scratch?
  • After mv, what does ls show?
  • What does rmdir print when the directory is not empty?

Objectives

  • Run pwd, mkdir -p, cd, and ls so an empty scratch directory prints nothing.
  • Create a file, show it with cat, copy it, and rename it so ls shows only the new name.
  • Remove an empty directory with rmdir, read the error on a non-empty directory, and remove it after emptying it.

The shell starts in home


Right after SSH, the current directory is your home directory. pwd prints that path. On Snellius it is /home/$USER. cd with no argument returns there from anywhere. ls prints the names in the current directory. An empty directory prints nothing. That empty print is success, not an error.

The scratch directory in the first task is not home. On Snellius it is /scratch-shared/$USER. mkdir -p creates it, and a second run does not fail if it is already there. The course cluster has no /scratch-shared. The tab names the scratch path you do have. Make your directory under that path. The pwd and ls checks are the same: ls of a new directory prints nothing.

Place Path What it is for
Home /home/$USER Shared with the compute nodes
Project /project Shared
Scratch /scratch Shared with the manager, not a separate parallel scratch
Node disk $TMPDIR This job only. Removed when the job ends

There is no /scratch-shared, no /scratch-node, and no /archive.

Caution

Login node

pwd, mkdir, and cat of one small file are what the login node is for. Do not generate a thousand files in this shell, and do not run the print-n program here. Those belong in the last episode, and they go through sbatch.

Callout

Type along

Use the Snellius commands if your tab lists /scratch-shared. Otherwise use the scratch path in the tab, then the same pwd and ls.

Challenge

Task 1: make a scratch directory and show that it is empty

On Snellius:

BASH

pwd
mkdir -p /scratch-shared/$USER
cd /scratch-shared/$USER
ls
pwd
cd
pwd

On the course cluster, /scratch-shared is not there. The tab names the scratch path. Create your directory under that path, cd into it, and run the same ls and pwd. Then cd with no argument.

pwd starts as /home/<your-login>.

mkdir -p creates the directory. On Snellius the path is /scratch-shared/$USER. On the course cluster it is a directory under the scratch path in the tab, not under /scratch-shared.

After cd into that directory, pwd prints it. ls prints nothing. No names, and no error, means the directory is empty.

cd with no argument returns to home. pwd prints /home/<your-login> again.

A file you can show, copy, and rename


touch creates an empty file. An editor such as nano or vim puts text in it. cat prints the file. printf is a way to put one known line in the file without an interactive editor, so the later cat has an answer you can check.

cp copies. The original stays. mv changes the name. After mv, ls of that directory shows the new name and does not show the old name.

Challenge

Task 2: copy, then rename

Start in home. On Snellius the scratch directory is /scratch-shared/$USER. On the course cluster, use the directory you created under the scratch path in the tab. The commands below say SCRATCH. Set it to that directory before you copy.

BASH

cd
SCRATCH=/scratch-shared/$USER
printf 'one line\n' > notes.txt
cat notes.txt
mkdir -p "$SCRATCH"
cp notes.txt "$SCRATCH/notes.txt"
ls "$SCRATCH"
mv "$SCRATCH/notes.txt" "$SCRATCH/notes-kept.txt"
ls "$SCRATCH"
ls notes.txt

On the course cluster, set SCRATCH to the directory you created under the scratch path in the tab. Do not use /scratch-shared/$USER there.

cat prints:

one line

The first ls of the scratch directory prints notes.txt.

The ls after mv prints notes-kept.txt and does not print notes.txt. The new name is the only name in that directory.

The last ls notes.txt still finds the original in home. cp left it there. mv renamed only the copy.

Directories, empty and not


mkdir creates a directory. cd enters it. rmdir removes a directory only when it is empty. That limit is useful. rmdir will not delete a tree of files because you pointed it at the wrong place.

If the directory still has a file, rmdir prints an error and leaves the directory in place. Remove the file, then run rmdir again.

Challenge

Task 3: an empty directory

Run this in home.

BASH

cd
mkdir demo-dir
cd demo-dir
pwd
ls
cd
rmdir demo-dir
ls

pwd inside demo-dir ends in /demo-dir. ls there prints nothing.

After cd back to home, rmdir demo-dir removes it because it is empty. The following ls does not list demo-dir.

Challenge

Task 3 continued: rmdir refuses a file

BASH

cd
mkdir demo-dir
cd demo-dir
touch keep.txt
cd ..
rmdir demo-dir
rm demo-dir/keep.txt
rmdir demo-dir
ls

What does the first rmdir print, and what is true after the second?

The first rmdir fails. The message is:

rmdir: failed to remove 'demo-dir': Directory not empty

demo-dir is still there, and keep.txt is still inside it. rmdir did not delete the file.

rm demo-dir/keep.txt empties the directory. The second rmdir then succeeds. ls in home does not list demo-dir.

Key Points
  • pwd prints the current directory. A new shell starts in home.
  • mkdir -p /scratch-shared/$USER is the Snellius scratch directory. The course cluster uses the path in the tab.
  • ls of an empty directory prints nothing.
  • After mv, ls shows the new name only. cp leaves the original.
  • rmdir removes an empty directory. On a non-empty directory it errors, and it succeeds after you empty it.

Content from Permissions and quota


Last updated on 2026-10-28 | Edit this page

Estimated time: 30 minutes

Overview

Questions

  • What does chmod g-r change in the mode string?
  • How do you see whether home is close to full?

Objectives

  • Read the ten-character mode string from ls -l.
  • Remove group read with chmod g-r and read the new string.
  • Run the quota command for your machine and name the home cap on Snellius.

The mode string


ls -l prints one line per file. The first field is the mode string. It has ten characters.

The first character is the type. - is a regular file. d is a directory.

The next nine characters are three groups of three: the owner, the group, and everyone else. Each group is r, w, x, or - when that permission is absent. r is read, w is write, x is execute.

- rw- r-- r--

with the spaces removed is -rw-r--r--. The owner can read and write. The group can read. Everyone else can read. Nobody can execute.

The numbers match the letters. Read is 4, write is 2, execute is 1. Add them inside one group. rw- is 6. r-- is 4. chmod 644 sets -rw-r--r--. chmod 640 sets -rw-r-----: the owner can read and write, the group can read, and everyone else has nothing.

chmod can also change one letter. The form is who, then + or -, then the letter. u is the owner, g is the group, o is everyone else. chmod g-r means “group, remove, read”. It does not change the owner, and it does not change everyone else.

A new file’s starting string depends on the account. On Snellius the hands-on files in the source notes are -rw-r-----. Your file may already lack group read. Set a known mode first, then remove the bit, so the change is visible.

Quota is a cap, not a suggestion


Home on Snellius is 200 GiB, with a limit a little above the quota, and a separate cap on inodes. Scratch is 8 TiB across scratch-local and scratch-shared. A full home stops the next copy. It also stops you writing the script that would move the data.

The command is in the tab. On Snellius it is myquota. On the course cluster there is no myquota. df -h prints size, used, and available for each mount you name. du -sh ~ prints one total for home, not a line per file. -s is the summary. -h prints units you can read.

There is no myquota here.

BASH

[YOUR_LOGIN@LOGIN ~]$ df -h /home /project /scratch
[YOUR_LOGIN@LOGIN ~]$ du -sh ~
Caution

Do not fill home

A multi-gigabyte output does not belong in home. Home is 200 GiB on Snellius and it is backed up. A full quota stops the small edits too. Write large job output to scratch or to the project path, and remove a test file when the exercise is over.

Challenge

Task 4: chmod g-r

Run this in home.

BASH

cd
printf 'one line\n' > mode-demo.txt
chmod 640 mode-demo.txt
ls -l mode-demo.txt
chmod g-r mode-demo.txt
ls -l mode-demo.txt

What is the mode string before chmod g-r, and what is it after?

After chmod 640, ls -l shows -rw-r-----. The type is -. The owner is rw-. The group is r--. Everyone else is ---.

chmod g-r removes the group’s r. The next ls -l shows -rw-------. The owner is unchanged. Everyone else is unchanged.

If your ls -l after chmod 640 is not -rw-r-----, write down the string you do see. chmod g-r still only clears group read. The group column becomes --- when it started as r--.

Challenge

Task 5: read the quota

Run the command in the tab.

There is no myquota here.

BASH

[YOUR_LOGIN@LOGIN ~]$ df -h /home /project /scratch
[YOUR_LOGIN@LOGIN ~]$ du -sh ~

On Snellius, what is the home quota in GiB, and what else does the line count? On the course cluster, which commands replace myquota, and what does each print?

On Snellius, myquota prints a home line with quota=200.00 in GiB. The limit in the documented example is 210.00. usage is the fraction already used. The same line counts inodes: the documented quota is 1000000. A scratch line is in TiB, with quota 8.00, counted across scratch-local and scratch-shared.

On the course cluster, myquota is not installed. df -h prints one line per mount you named, with the size, the amount used, and the amount free. du -sh ~ prints a single size for your home directory.

A home usage near the quota is the signal to move large files before the next job, not after the write has failed.

Key Points
  • The mode string is type, then owner, group, and everyone else.
  • chmod 640 sets -rw-r-----. chmod g-r then sets -rw-------.
  • Snellius home is 200 GiB. myquota prints the cap and the inode cap.
  • Without myquota, df -h shows the mounts and du -sh ~ shows home.

Content from Space for a job


Last updated on 2026-10-28 | Edit this page

Estimated time: 40 minutes

Overview

Questions

  • What does a job’s $TMPDIR look like, and why do two jobs on one node get two directories?
  • How do you ask Snellius for scratch-node, and what do you do on a cluster that has no such disk?
  • How do you shrink ex1/run.sh without editing it?

Objectives

  • Submit a job that lists $TMPDIR, creates a file there, and prints realpath.
  • Read the tcn386 transcript: job 4401218 and job 4401219 are two directories on one node.
  • Request scratch-node on Snellius, and follow the tab where that constraint does not exist.
  • Run print-n for 10^6 to 10^9 values on Snellius, or iend=8 wdir=TMPDIR sbatch run.sh on a small cluster.

The directory belongs to the job


$TMPDIR inside a job is a directory the scheduler created for that job. It is not the login node’s /tmp, and it is not the login node’s $TMPDIR. Write scratch files there. Copy anything you must keep to a path that lasts, before the script exits.

The tab says what the variable points at on your machine.

$TMPDIR in a job is /localscratch/$USER.$SLURM_JOB_ID.0 on the node’s own disk. The cluster deletes it when the job ends. There is one login node, so compare the login node’s /tmp with a job’s $TMPDIR.

On Snellius, a compute-node $TMPDIR is /scratch-local/$USER.$SLURM_JOB_ID. realpath prints the GPFS path under /gpfs/scratch1/nodespecific/<node>/. Two jobs on the same node get two directories. The job id is in the name. On the course cluster, $TMPDIR is on the node’s own disk and is deleted when the job ends. There is one login node, so the comparison is the login node’s /tmp against a job’s $TMPDIR, not two login nodes.

This script is the check. It prints the node, lists the directory, creates one empty file, lists again, and prints both the variable and realpath.

BASH

#!/bin/bash
#SBATCH -J files
#SBATCH -t 5
#SBATCH -p rome

hostname
ls -l $TMPDIR
touch "$TMPDIR/testfile.foo"
ls -l $TMPDIR
echo $TMPDIR
realpath $TMPDIR

-t 5 asks for five minutes. -J files is the job name. The script’s partition line is -p rome, as published. Leave that line as it is in the file. Submit the file with sbatch. Do not run it with bash on the login node.

The source notes recorded two submits that both ran on tcn386. The output files were slurm-4401218.out and slurm-4401219.out.

tcn386.local.snellius.surf.nl
total 0
total 0
-rw-r----- 1 scur1448 scur1448 0 Nov  9 00:25 testfile.foo
/scratch-local/scur1448.4401218
/gpfs/scratch1/nodespecific/tcn386/scur1448.4401218
tcn386.local.snellius.surf.nl
total 0
total 0
-rw-r----- 1 scur1448 scur1448 0 Nov  9 00:25 testfile.foo
/scratch-local/scur1448.4401219
/gpfs/scratch1/nodespecific/tcn386/scur1448.4401219

Read it from the top. hostname is the compute node, tcn386, not a login node. The first ls -l prints total 0 and no file. The directory was empty. The second ls -l prints total 0 and then testfile.foo. touch created an empty file, so the size is 0. The mode -rw-r----- is the mode from the previous episode.

echo $TMPDIR prints /scratch-local/scur1448.<jobid>. realpath prints /gpfs/scratch1/nodespecific/tcn386/scur1448.<jobid>. Those are two names for one directory. The job id changes. The node in this pair does not: both jobs ran on tcn386.

Scratch-local can still be listed after the job has written the file. It counts against the scratch quota until it expires. The table in the previous episode gives it 6 days. From a Snellius login node the source notes listed leftover directories with:

BASH

ls -ld /gpfs/scratch1/nodespecific/*/scur1448.*

That printed three directories on tcn386, for jobs 4401213, 4401218, and 4401219. Your login replaces scur1448. Do not run that ls on the course cluster. There is no /gpfs/scratch1/nodespecific there.

Caution

Login node

Submit the script. Do not execute it on the login node. A write there uses the shared login node, and the temporary directory you see is not the job’s $TMPDIR.

Challenge

Read the two job outputs

Using only the transcript above: did the two jobs share a node? Did they share a directory? Which printed path is the GPFS path?

They shared a node. Both hostnames are tcn386.local.snellius.surf.nl.

They did not share a directory. The ids are 4401218 and 4401219. Same node, two job directories.

The GPFS path is the realpath line, /gpfs/scratch1/nodespecific/tcn386/scur1448.<jobid>. The /scratch-local/... line is the other name for that same directory.

Challenge

Submit the TMPDIR job

Put the script in a file, files-tmpdir.sh, and submit it:

BASH

sbatch files-tmpdir.sh

When the output file appears, compare it with the tcn386 transcript. Your job id and your node name will differ.

The output has six parts:

  1. A compute-node hostname, not your login node.
  2. total 0 from the first ls -l, with no filename.
  3. total 0 and testfile.foo from the second ls -l. The size is 0 because touch creates an empty file.
  4. echo printing $TMPDIR.
  5. realpath printing another absolute path for that same directory.

On Snellius the two paths look like /scratch-local/$USER.<jobid> and /gpfs/scratch1/nodespecific/<node>/$USER.<jobid>. A second submit gets a new job id in the name, even on the same node.

On the course cluster the path is the one in the $TMPDIR tab, on the node’s disk, and the directory is removed when the job ends. The output file from sbatch remains in the directory where you submitted. That file is how you read the path after the job.

Scratch-node ends with the job


Scratch-node is the same idea on a faster disk, and only on Snellius. The disk is NVMe on the node. $TMPDIR points at your directory on it. The directory is removed when the job ends. There is no quota. Copy results off before the script exits. The node feature is not universal, so the script asks for it.

There is no --constraint=scratch-node. $TMPDIR is already on the node’s own disk. Drop the constraint and write to $TMPDIR.

The course cluster has no --constraint=scratch-node. $TMPDIR is already on the node’s disk. Drop the constraint and still write to $TMPDIR.

Challenge

Write one file on the fast disk

On Snellius, submit:

BASH

#!/bin/bash
#SBATCH -J scratch-node-test
#SBATCH -t 5
#SBATCH -p rome
#SBATCH --constraint=scratch-node

touch "$TMPDIR/testfile-scratch-node.foo"
echo "This is a file on scratch-node" > "$TMPDIR/testfile-scratch-node.foo"
realpath "$TMPDIR/testfile-scratch-node.foo"

On the course cluster, follow the tab: do not add --constraint=scratch-node. Keep the touch, the echo, and the realpath.

The output is one absolute path, and the path ends in testfile-scratch-node.foo.

On Snellius that path is on the node disk you requested. The directory is removed when the job ends, so the login node cannot open it afterwards. The line in the slurm output file is the record.

On the course cluster the constraint is absent. realpath still prints a path ending in testfile-scratch-node.foo, under the job’s $TMPDIR. That directory is also removed when the job ends.

If the Snellius job waits and never starts, no node with the feature was free. Read the tab and the script, and do not drop the constraint on Snellius just to get a start. Drop it only on the machine whose tab says to drop it.

A million to a billion values


episodes/files/ex1/print-n.c writes n random double-precision values to a file, in ASCII or in binary. It then prints how long the write took, the file size in MB, and the rate in MB/s. run.sh compiles it and calls it in a loop.

The script loads module load 2025 and GCC/14.2.0, compiles print-n.c to print-n.out, and loops i from ibeg to iend (the end index is excluded). The defaults are ibeg=6 and iend=10, so n is 10^6, 10^7, 10^8, and 10^9. The last array is 8 GB of memory. The file is ASCII, so it is larger than that array. nmax stops a run that would be even bigger.

wdir is the directory the file is written to. The default is $HOME. wdir=TMPDIR is a keyword. The script expands it to the job’s $TMPDIR inside the job. Setting wdir to the login node’s $TMPDIR before sbatch would point at the wrong directory. Use the keyword.

On Snellius, from the ex1 directory:

BASH

sbatch run.sh

That is the full run, 10^6 through 10^9 values, into home unless you set wdir. Remove ex1.dat when you have read the output. Home is 200 GiB. The file does not belong there overnight.

On a small cluster, do not submit the full range. The tab has the smaller command. The line for this exercise is:

BASH

iend=8 wdir=TMPDIR sbatch run.sh

iend=8 keeps i at 6 and 7, so the job writes 10^6 values and then 10^7 values, into the job’s $TMPDIR. iend=8 sbatch run.sh writes those same two sizes into home, which is the comparison and also the one to avoid if home is tight. Prefer the wdir=TMPDIR form.

On a two-core node, pass the smaller request on the command line. Do not edit the script.

BASH

sbatch --cpus-per-task=2 pi.sh
sbatch --array=0-99%10 array_job.sh
QCG_MAX_INPUTS=100 sbatch --ntasks=2 qcg_job.sh
iend=8 wdir=TMPDIR sbatch run.sh

Check the core count with sinfo first.

The other lines in that tab belong to later lessons. Use the run.sh line.

Caution

Do not fill home

The published default writes ex1.dat in home. On a small cluster, iend=8 wdir=TMPDIR keeps the file in the job directory, which is removed at the end of the job. The slurm output file in the submit directory is the part you keep. Delete a home copy if you made one.

Challenge

Run print-n at the size your machine can hold

From episodes/files/ex1, submit the full script on Snellius:

BASH

sbatch run.sh

On a small cluster, submit the line from the tab:

BASH

iend=8 wdir=TMPDIR sbatch run.sh

How many Printing lines do you get, and which powers of ten are they? Where is ex1.dat?

The program prints, for each n, a line of this shape, then the script prints Printing:

1000000 random double-precision values written to <path>/ex1.dat in ascii format
 Elapsed time [s]: <seconds>
 File size [MB]: <size>
 Transfer rate [MB/s]: <rate>
Printing 1000000 elements

The seconds, the size, and the rate depend on the node. ASCII is about 9 bytes per value (0.123456 and a newline), so the 10^6 file is about 9 MB and the 10^7 file is about 90 MB. Do not expect those sizes to the last digit. Do expect the size to grow by about ten times when n grows by ten times.

On Snellius, sbatch run.sh prints four Printing lines: 1000000, 10000000, 100000000, and 1000000000. The default path is your home directory. Remove ex1.dat after you have read the rates.

On a small cluster, iend=8 wdir=TMPDIR sbatch run.sh prints two Printing lines: 1000000 and 10000000. The path contains the job’s $TMPDIR. That directory is gone when the job ends. The slurm output file is still in the directory where you submitted.

This challenge is optional. Skip it when time is short or when df -h shows little free space. On the course cluster, create 100 files of 1 MB, not 1000. If home and the scratch path are the same disk, the copy is not a useful comparison. Use the job’s $TMPDIR as the destination, or skip the challenge.

Challenge

Optional: many small files against one archive

This is the cost from the first episode, timed.

On Snellius, create 1000 files of 1 MB in home, then copy them to scratch-shared. On the course cluster, create 100 files, and use the scratch path in the tab. Check df -h first. Stop if the free space is close to the size you are about to write.

Place Path What it is for
Home /home/$USER Shared with the compute nodes
Project /project Shared
Scratch /scratch Shared with the manager, not a separate parallel scratch
Node disk $TMPDIR This job only. Removed when the job ends

There is no /scratch-shared, no /scratch-node, and no /archive.

BASH

mkdir ~/file_transfer_test
cd ~/file_transfer_test
for i in {1..1000}; do
  head -c 1M </dev/urandom > "file_${i}.bin"
done
du -sh ~/file_transfer_test

On the course cluster the loop is {1..100}.

Set DEST to /scratch-shared/$USER on Snellius, or to the scratch directory from the tab. Do not set DEST to $TMPDIR in this login shell. The login node’s $TMPDIR is the wrong disk. On the course cluster, if you want the node disk, put the cp lines in a job and let that job expand $TMPDIR.

BASH

time cp -r ~/file_transfer_test "$DEST/"
tar -C ~ -czf ~/file_transfer_test.tar.gz file_transfer_test
du -sh ~/file_transfer_test.tar.gz
time cp ~/file_transfer_test.tar.gz "$DEST/"

Then remove the test, in home and in DEST:

BASH

rm -r ~/file_transfer_test
rm ~/file_transfer_test.tar.gz
rm -r "$DEST/file_transfer_test"
rm "$DEST/file_transfer_test.tar.gz"

Check pwd and echo "$DEST" before rm -r. Remove only this test.

What do you expect from the two du sizes, and which time cp finishes sooner?

head -c 1M writes 1,048,576 bytes. A thousand of those files is about 1000M. du -sh ~/file_transfer_test prints a size near 1000M or 1.0G. One hundred files, the course-cluster count, is near 100M.

The archive is about the same size as the directory. The bytes are random. gzip does not compress them. The single file is the win, not a smaller file.

time cp of the archive finishes in less time than time cp -r of the loose files. The archive is one create and one stream of bytes. The directory is a thousand creates. That is the metadata server from the first episode.

After the four rm commands, ls ~/file_transfer_test fails because the directory is gone, and ls "$DEST/file_transfer_test.tar.gz" fails for the same reason. Home is back to the size it had before the test.

Key Points
  • $TMPDIR in a job is that job’s directory. Two jobs on tcn386 got scur1448.4401218 and scur1448.4401219.
  • realpath on those jobs printed /gpfs/scratch1/nodespecific/tcn386/ plus the same job directory.
  • Scratch-node is --constraint=scratch-node on Snellius. The course cluster drops the constraint and uses $TMPDIR.
  • sbatch run.sh writes 10^6 through 10^9 values. A small cluster uses iend=8 wdir=TMPDIR sbatch run.sh.
  • A thousand small files copy slower than one archive of the same bytes. Clean the test up.