Running each iteration in a for loop in parallel

I have the following code:

for i in "${atomic_mass[@]}"
do
        cd /home/eric2207/data/Z=66
        mkdir DY"$i"
        for j in "${deformation[@]}"
        do
                cd /home/eric2207/DRHBc
                make clean
                sed -e "s/\${A}/$i/" -e "s/\${beta}/$j/" $input > $output
                make
                cd /home/eric2207/data/Z=66/DY"$i"
                mkdir ./"$j"
                cd ./"$j"
                cp /home/eric2207/DRHBc/1drhbws .
                cp /home/eric2207/DRHBc/dir.dat .
                cp /home/eric2207/DRHBc/paramet.for .
        done
done

My question is how do I run the commands for all the j in parallel? That is, I want the commands in each j to run sequentially but the commands for all the j to run in parallel. I found that one can do

parallel --jobs (number of commands) < (file)

However, this does not help me in my case as I want the commands nested in the second for loop to run sequentially. Any help would be greatly appreciated!

2 answers

  • answered 2018-11-08 07:18 Mark Setchell

    Not at a proper computer, but:

    for
    do
       ...
       for 
       do
          (
            ...
            ...
          ) &
       done
       wait
    done
    

  • answered 2018-11-08 11:57 Ole Tange

    do_one() {
      i="$1"
      j="$2"
      jobslot="$3"
      cd /home/eric2207/data/Z=66
      mkdir -p DY"$i"
                cd /home/eric2207/
                # You need a new dir per combination due to race condition
                rsync -a DRHBc/ DRHBc-"$jobslot"/
                cd DRHBc-"$jobslot"
                make clean
                sed -e "s/\${A}/$i/" -e "s/\${beta}/$j/" $input > $output
                make
                cd /home/eric2207/data/Z=66/DY"$i"
                mkdir ./"$j"
                cd ./"$j"
                cp /home/eric2207/DRHBc-"$jobslot"/1drhbws .
                cp /home/eric2207/DRHBc-"$jobslot"/dir.dat .
                cp /home/eric2207/DRHBc-"$jobslot"/paramet.for .
    }
    export -f do_one
    parallel do_one {1} {2} {%} ::: "${atomic_mass[@]}" ::: "${deformation[@]}"
    

    Force outer loop in serial:

    inner() {
      i="$1"
      parallel -q do_one "$i" {1} {%} ::: "${deformation[@]}"
    }
    export -f inner
    env_parallel --env deformation -j1 inner ,,, "${atomic_mass[@]}"