############################################################################### SHELL := /usr/bin/bash .ONESHELL: ############################################################################### ATT = $(EXE:=.att) C = 10 CPU != echo $$(( $$(grep -m 1 "cpu cores" /proc/cpuinfo | grep -o '[[:digit:]]*') / 2 )) SRC = $(sort $(wildcard *.c *.cc)) EXE = $(basename $(SRC)) N != sed -n 's/^.*const size_t N = \([[:digit:]]*\);$$/\1/p' le.cc P1 = 13 P2 = 7 REP = 25 STA = $(EXE:=.sta) TXT = $(EXE:=.txt) LOG = $(EXE:=.log) ############################################################################### #CXXFLAGS = -fanalyzer -fsanitize=address -g -Og -std=c++20 -Wall CXXFLAGS = -g -O3 -std=c++20 -Wall ############################################################################### all: @if make -qs $(TXT); then make -s sort else make -s stat fi att: $(ATT) clave: @printf "%$$(($(P1) + $(P2) * 15))s\n" | tr ' ' '-' echo "clave:" printf "%$$(($(P1) + $(P2) * 15))s\n" | tr ' ' '-' echo " cc : condiciones de carrera = escrituras incorrectas" echo " ln : número de total de lecturas (siempre correctas)" echo " lmin : mínimo número de lecturas" echo " lmedia : número medio de lecturas" echo " ldesv : desviación típica del número de lecturas" echo " lmax : máximo número de lecturas" echo " en : número de total de escrituras (no siempre correctas)" echo " emin : mínimo número de escrituras" echo " emedia : número medio de escrituras" echo " edesv : desviación típica del número de escrituras" echo " emax : máximo número de escrituras" echo " just : log(lmedia / emedia) máxima justicia = 0" echo " msg : ln + en" echo " cpu : tiempo de cpu (en milisegundos)" echo " rend : msg / tiempo" clean: -rm -fv $(ATT) $(EXE) $(TXT) $(LOG) $(STA) core* *~ -find -mindepth 2 -maxdepth 2 -name makefile -execdir make $@ \; cpu: n$(CPU) 10ms all default: cpu exe: $(EXE) max: n10 10ms all min: n1 10ms all sort: clave @declare -a N=('13' '14' '15' '16') declare -a F=('just' 'msg' 'cpu' 'rend') declare -a R=('' 'r' '' 'r') for (( i=0; i<$${#N[@]}; ++i )); do printf "%$$(($(P1) + $(P2) * 15))s\n" | tr ' ' '-' make -s $(firstword $(TXT)) head -n 1 $(firstword $(TXT)) | sed "s/ \($${F[$$i]}\)/\[\1\]/" printf "%$$(($(P1) + $(P2) * 15))s\n" | tr ' ' '-' make stat | grep -E -w "$$(echo $(EXE) | tr ' ' '|')" | sort -k$${N[$$i]},$${N[$$i]}n$${R[$$i]} -k16,16nr -k13,13n -s done printf "%$$(($(P1) + $(P2) * 15))s\n" | tr ' ' '-' stat: clave @printf "%$$(($(P1) + $(P2) * 15))s\n" | tr ' ' '-' for i in $(TXT); do make -s $$i if [[ "$$i" == "$(firstword $(TXT))" ]]; then head -n1 $$i printf "%$$(($(P1) + $(P2) * 15))s\n" | tr ' ' '-' fi tail -n1 $$i done printf "%$$(($(P1) + $(P2) * 15))s\n" | tr ' ' '-' ############################################################################### %.att: % objdump -Cd $< > $@ %.leak: % valgrind --leak-check=full -s --show-leak-kinds=all ./$< %.log %.sta: % # sudo sysctl kernel.perf_event_paranoid=-1 # por si perf falla... @LANG=C perf stat -r $(REP) 2> $*.sta -- ./miecho.sh ./$< > $*.log %.txt: %.log %.sta @LANG=C declare -A l; for ((i=0; i<$(N); ++i)); do l["$$i"]="0" done while read v k; do l["$$k"]=$$(bc -lq <<< "$$v / ($(C) * $(REP))") done < <(sed 's/\(.\)/\1\n/g' $*.log | grep "[[:digit:]]" | sort | uniq -c) if (( $${#l[@]} < $(N) )); then echo "[$*.log]: $${#l[@]} < $(N)"; exit 1; fi ln=0 lmin=0 lmedia=0 ldesv=0 lmax=0 if [ "$${#l[@]}" -gt "0" ]; then lv="[$$(echo $${l[@]} | tr ' ' ',')]" ln=$$(python3 -c "print(sum($$lv))") lmin=$$(python3 -c "print(min($$lv))") lmedia=$$(python3 -c "import statistics; print(statistics.mean($$lv))") if [ "$${#l[@]}" -gt "1" ]; then ldesv=$$(python3 -c "import statistics; print(statistics.stdev($$lv))") fi lmax=$$(python3 -c "print(max($$lv))") fi declare -A e; for ((i=0; i<$(N); ++i)); do e["$$i"]="0" done while read v k; do e["$$k"]=$$(bc -lq <<< "$$v / ($(C) * $(REP))") done < <(sed 's/\(.\)/\1\n/g' $*.log | grep "[[:lower:]]" | sort | uniq -c) if (( $${#l[@]} < $(N) )); then echo "[$*.log]: $${#e[@]} < $(N)"; exit 1; fi en=0 emin=0 emedia=0 edesv=0 emax=0 if [ "$${#e[@]}" -gt "0" ]; then ev="[$$(echo $${e[@]} | tr ' ' ',')]" en=$$(python3 -c "print(sum($$ev))") emin=$$(python3 -c "print(min($$ev))") emedia=$$(python3 -c "import statistics; print(statistics.mean($$ev))") if [ "$${#e[@]}" -gt "1" ]; then edesv=$$(python3 -c "import statistics; print(statistics.stdev($$ev))") fi emax=$$(python3 -c "print(max($$ev))") fi msg=$$(python3 -c "print($$ln + $$en)") cc=$$(grep [0-9] $*.log | grep [a-z] | wc -l) # cc lector/escritor for i in {a..z}; do # cc escritor/escritor for j in $$(eval echo {$$i..z}); do if [[ "$$i" < "$$j" ]]; then if [ "$$(grep $$i$$j $*.log | wc -l)" != "0" ]; then (( ++cc )) fi fi done done (( cc = cc / ($(C) * $(REP)) )) just=$$(bc -lq <<< "l(($$lmedia + 10^-10) / ($$emedia + 10^-10))/l(10)") cpu=$$(grep -o ".* msec task-clock" $*.sta | grep -o "[[:digit:].]*") rend=$$(bc -lq <<< "$$msg / $$cpu") printf '%$(P1)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s\n' programa cc ln lmin lmedia ldesv lmax en emin emedia edesv emax just msg cpu rend > $@ printf '%$(P1)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s%$(P2)s\n' $* $$cc $$(printf '%.0f' $$ln) $$(printf '%.0f' $$lmin) $$(printf '%.0f' $$lmedia) $$(printf '%.0f' $$ldesv) $$(printf '%.0f' $$lmax) $$(printf '%.0f' $$en) $$(printf '%.0f' $$emin) $$(printf '%.0f' $$emedia) $$(printf '%.0f' $$edesv) $$(printf '%.0f' $$emax) $$(printf '%.2f' $$just) $$(printf '%.0f' $$msg) $$(printf '%.1f' $$cpu) $$(printf '%.1f' $$rend) >> $@ n%: $(SRC) @n=$@ if (( $${n:1} > 10 )); then n='n10'; fi sed --follow-symlinks -i "s/const size_t N = .*;/const size_t N = $${n:1};/" $^ %ms: $(SRC) @sed --follow-symlinks -i "s/^ std::this_thread::sleep_for(.*);/ std::this_thread::sleep_for($@);/" $^ ############################################################################### .PHONY: all clave clean cpu default exe max min sort stat .PRECIOUS: $(STA) $(TXT) $(LOG) ###############################################################################