11#! /usr/bin/env bash
22# Checks that multithreaded Geant4 in o2-sim gives the same output for 1 and N transport threads.
33#
4- # Usage: o2-sim-mt-equality.sh [-n events] [-j threads] [-g generator] [--field kG] [--seed seed] [--workdir dir] [module ...]
4+ # Usage: o2-sim-mt-equality.sh [-n events] [-j threads] [-g generator] [--field kG] [--seed seed]
5+ # [--seeding track|subevent] [--tolerance fraction] [--workdir dir] [module ...]
56#
67# Runs the same seeded workload with --isMT -j 1 and --isMT -j N and compares the kinematics and hit files
7- # event by event and branch by branch. Exits with 1 at the first difference. Without modules, the passive
8- # geometry with ITS is used.
8+ # event by event and branch by branch. A sequential run with the same seed is the reference for the number of
9+ # hits of each detector, which must not be zero and must agree within the tolerance (default 0.2). Exits with
10+ # 1 at the first difference. Without modules, the passive geometry with ITS is used.
911
1012nev=2
1113nthreads=2
1214gen=pythia8pp
1315field=-5
1416seed=4711
17+ seeding=track
18+ tolerance=0.2
1519workdir=
1620modules=()
1721while [ $# -gt 0 ]; do
@@ -21,18 +25,25 @@ while [ $# -gt 0 ]; do
2125 -g) gen=$2 ; shift 2 ;;
2226 --field) field=$2 ; shift 2 ;;
2327 --seed) seed=$2 ; shift 2 ;;
28+ --seeding) seeding=$2 ; shift 2 ;;
29+ --tolerance) tolerance=$2 ; shift 2 ;;
2430 --workdir) workdir=$2 ; shift 2 ;;
25- -h|--help) sed -n ' 2,9p ' $0 ; exit 0 ;;
31+ -h|--help) sed -n ' 2,10p ' $0 ; exit 0 ;;
2632 * ) modules+=(" $1 " ); shift ;;
2733 esac
2834done
2935[ ${# modules[@]} -eq 0 ] && modules=(HALL MAG DIPO COMP PIPE ABSO SHIL ITS)
36+ case $seeding in
37+ track) seedconf=" SimCutParams.trackSeed=true" ;;
38+ subevent) seedconf=" SimCutParams.trackSeed=false" ;;
39+ * ) echo " unknown seeding '$seeding ', use track or subevent" ; exit 1 ;;
40+ esac
3041o2sim=o2-sim
3142[ -x " $O2_ROOT /bin/o2-sim" ] && o2sim=$O2_ROOT /bin/o2-sim
3243[ -z " $workdir " ] && workdir=$( mktemp -d ${TMPDIR:-/ tmp} /o2sim-mt-equality-XXXXXX)
3344mkdir -p $workdir && cd $workdir || exit 1
3445
35- # content hash per event and branch of the o2sim tree, independent of the basket layout
46+ # content hash and number of entries per event and branch of the o2sim tree, independent of the basket layout
3647cat > hashtree.C << 'EOF '
3748void hashtree(const char* fname)
3849{
@@ -63,43 +74,68 @@ void hashtree(const char* fname)
6374 md5.Update((UChar_t*)buf.Buffer(), buf.Length());
6475 md5.Final();
6576 printf("HASH event %lld branch %s %s\n", i, name.c_str(), md5.AsString());
77+ if (auto proxy = cl->GetCollectionProxy()) {
78+ TVirtualCollectionProxy::TPushPop helper(proxy, obj);
79+ printf("COUNT event %lld branch %s %u\n", i, name.c_str(), proxy->Size());
80+ }
6681 }
6782 }
6883}
6984EOF
7085
71- run () { # <threads>
72- local dir=mt$1
86+ run () { # <directory> <o2-sim mode options>
87+ local dir=$1
88+ shift
7389 mkdir -p $dir && cd $dir
74- $o2sim --isMT 1 -j $1 -n $nev -g $gen -e TGeant4 --seed $seed --field $field -m ${modules[@]} \
75- --configKeyValues " SimCutParams.trackSeed=true" > sim.log 2>&1
90+ $o2sim " $@ " -n $nev -g $gen -e TGeant4 --seed $seed --field $field -m ${modules[@]} --configKeyValues " $seedconf " > sim.log 2>&1
7691 local rc=$?
7792 if [ $rc -ne 0 ] || ! grep -q " SIMULATION RETURNED SUCCESFULLY" sim.log; then
78- echo " o2-sim with $1 threads failed (exit code $rc ), see $workdir /$dir "
93+ echo " o2-sim in $dir failed (exit code $rc ), see $workdir /$dir "
7994 exit 1
8095 fi
8196 for f in o2sim_Kine.root o2sim_Hits* .root; do
82- [ -f $f ] && root -l -b -q " ../hashtree.C(\" $f \" )" 2> /dev/null | grep " ^HASH" | sed " s/^HASH/$f /" > $f .hashes
97+ [ -f $f ] || continue
98+ root -l -b -q " ../hashtree.C(\" $f \" )" 2> /dev/null > $f .out
99+ grep " ^HASH" $f .out | sed " s/^HASH/$f /" > $f .hashes
100+ grep " ^COUNT" $f .out | awk ' {n += $NF} END {print n + 0}' > $f .count
83101 done
84102 cd ..
85103}
86104
87- echo " o2-sim MT equality: ${modules[*]} , $nev events of $gen , field $field kG, 1 against $nthreads threads, in $workdir "
88- run 1
89- run $nthreads
105+ echo " o2-sim MT equality: ${modules[*]} , $nev events of $gen , field $field kG, $seeding seeding, 1 against $nthreads threads, in $workdir "
106+ run seq -j 1
107+ run mt1 --isMT 1 -j 1
108+ run mt$nthreads --isMT 1 -j $nthreads
90109status=0
91110for h in mt1/* .hashes; do
92111 f=$( basename $h )
112+ file=${f% .hashes}
93113 if [ ! -s $h ]; then
94- echo " ${f % .hashes} : no entries"
114+ echo " $file : no entries"
95115 status=1
96116 elif cmp -s $h mt$nthreads /$f ; then
97- echo " ${f % .hashes} : identical ($( wc -l < $h ) event-branch hashes)"
117+ echo " $file : identical ($( wc -l < $h ) event-branch hashes)"
98118 else
99- echo " ${f % .hashes} : DIFFERS, first at $( diff $h mt$nthreads /$f | grep -m1 ' ^<' | cut -d' ' -f3-6) "
119+ echo " $file : DIFFERS, first at $( diff $h mt$nthreads /$f | grep -m1 ' ^<' | cut -d' ' -f3-6) "
100120 status=1
101121 fi
102122done
103123[ $( ls mt$nthreads /* .hashes | wc -l) -eq $( ls mt1/* .hashes | wc -l) ] || { echo " the runs wrote different output files" ; status=1; }
124+ # the sequential run as reference for the number of hits, which catches a detector clone that makes no hits
125+ for c in seq/o2sim_Hits* .root.count; do
126+ [ -f " $c " ] || continue
127+ file=$( basename ${c% .count} )
128+ nseq=$( cat $c )
129+ nmt=$( cat mt1/$file .count 2> /dev/null || echo 0)
130+ if [ " $nmt " -eq 0 ]; then
131+ echo " $file : no hits in MT (sequential: $nseq )"
132+ status=1
133+ elif ! awk -v a=$nseq -v b=$nmt -v t=$tolerance ' BEGIN {exit !(a > 0 && (a - b < 0 ? b - a : a - b) <= t * a)}' ; then
134+ echo " $file : $nmt hits in MT against $nseq in sequential mode, beyond the tolerance $tolerance "
135+ status=1
136+ else
137+ echo " $file : $nmt hits in MT, $nseq in sequential mode"
138+ fi
139+ done
104140[ $status -eq 0 ] && echo " EQUALITY TEST PASSED" || echo " EQUALITY TEST FAILED"
105141exit $status
0 commit comments