Script Bash per automatizzare i calcoli HPC

Sep 01 2020

Sono uno studente di chimica che lavora su un semplice script bash per automatizzare i calcoli della teoria funzionale della densità HPC utilizzando Quantum Espresso (pw.x). Sono un principiante nello scripting di shell e apprezzerei alcune critiche / feedback prima di provare a implementarlo sul cluster. Lo script chiama ingen.py che è uno script Python che ho scritto per generare nuovi file di input se determinate soglie di parametri nel file di registro non vengono soddisfatte.

#!/bin/bash
    
#SBATCH --job-name=2x2x6_PbCO3          # job name        
#SBATCH --output=slurm.out              # Output file name                                                                                                                                                
#SBATCH --error=slurm.err               # Error file name                                                                                                                                                 
#SBATCH --partition=batch               # Partition                                                                                                                                                       
#SBATCH --qos=medium+                   # Queue                                                                                                                                                           
#SBATCH --time=24:00:00                 # Time limit                                                                                                                                                      
#SBATCH --nodes=3                       # Number of nodes                                                                                                                                                 
#SBATCH --ntasks-per-node=16            # MPI processes per node 

errors='MPI_ABORT|error|aborted|SIGTERM|TIME|CANCELLED|SIGCONT|terminated|fork'
job='2x2x6_PbCO3'
max_runs=5
prefix=PbCO3

#-------------------------------------------------------------------------------
Clear () 
{
# Checks for input/log from a completed batch script
if [[ -f "$prefix.in" && -f "$prefix.log"  ]]; then
   # If both are found a new input file is generated
   python ~/path-to-in-gen.py $prefix.log $prefix.in $job override if [ -z "$(ls -A ../logs_and_inputs)" ]; then
      index=1
   else
      indices=()
      # Old input/log are tagged and stored
      for entry in "../logs_and_inputs"/$prefix.in-*; do indices+=("${entry: -1}")
      done
      max=${indices[0]} for n in "${indices[@]}" ; do
         ((n > max)) && max=$n done index=$((max+1))
      rm -r *x*x*
      mv $prefix.in ../logs_and_inputs/$prefix.in-$index mv $prefix.log ../logs_and_inputs/$prefix.log-$index
      mv $prefix.in-new $prefix.in
   fi
fi
}
#-------------------------------------------------------------------------------
# Creates a directory for old logs and inputs to be stored with a numerical tag from 1 to k
Sort ()
{
if [ ! -d "../logs_and_inputs" ]; then
    mkdir ../logs_and_inputs
    iter=1
else
   if [ -z "$(ls -A ../logs_and_inputs)" ]; then iter=1 else indices=() for entry in "../logs_and_inputs"/$prefix.in-*; do
         indices+=("${entry: -1}") done max=${indices[0]}
      for n in "${indices[@]}" ; do ((n > max)) && max=$n
      done
      iter=$((max+1)) fi fi max_iter=$((iter+max_runs))
}
#-------------------------------------------------------------------------------                                                                                                   
Automode () 
{
mpirun ~/path-to-pw.x < $prefix.in > $prefix.log
# Runs pw.x job, checks for completion and errors
if grep -E -q -- $errors "slurm.err"; then exit 1 fi if grep -q "job DONE." "$prefix.log"; then
   # Clear wavefunction files and temp directories
   rm -r *x*x*
   # Generates new input file
   python ~/path-to-in-gen.py $prefix.log $prefix.in $job # Tags and stores the previous input and log mv $prefix.in ../logs_and_inputs/$prefix.in-$iter
   mv $prefix.log ../logs_and_inputs/$prefix.log-$iter else exit 1 fi # Checks for generation of new input file if test -f "$prefix.in-new"; then
   mv $prefix.in-new $prefix.in
else
   exit 1
fi
let "iter=iter+1"
}
#-------------------------------------------------------------------------------                                                                                                   
Clear

Sort

while ((iter < max_iter)); do
   Automode
done

Risposte

4 l0b0 Sep 01 2020 at 10:02

Suggerimenti specifici:

  1. I nomi delle funzioni sono per convenzione snake_case.
  2. Usa più citazioni ™ .
  3. [[dovrebbe essere usato al posto di[ , perché è più sicuro.
  4. [[ EXPRESSION ]] && [[ EXPRESSION ]]sarebbe più chiaro di [[ EXPRESSION && EXPRESSION ]], a mio parere.
  5. set -o errexit -o noclobber -o nounset -o pipefaile shopt -s globfailrenderebbe la gestione degli errori molto più rigorosa.
  6. Questo non è più un codice banale, quindi consiglierei di implementarlo in un linguaggio non shell come Python.

Suggerimenti per gli strumenti:

  1. Eseguire shellcheckregolarmente lo script è un buon modo per acquisire possibili problemi. In questo caso l'unica cosa che trova è per rm -r *x*x*:

    SC2035: usa ./ glob o - glob in modo che i nomi con trattini non diventino opzioni.