#!/usr/bin/env bash # Сколько узел занимает процессора и видеокарты в реальном времени. # Узел — в своём контейнере, запись проигрывается из другого (как у жюри), поэтому # процессор проигрывателя в замер не попадает. # # bash docker/usage_test.sh /путь/к/записи --gpus all # bash docker/usage_test.sh /путь/к/записи # без видеокарты # # Всё после записи — флаги видеокарты для контейнера узла. Загрузка видеокарты # берётся из nvidia-smi всей машины: сначала 5 с без узла, потом во время # проигрывания; в итоге — прибавка к фону. set -u BAG="${1:?укажите путь к записи на хосте}" shift GPU=("$@") here="$(cd "$(dirname "$0")" && pwd)" bag_dir="$(cd "$(dirname "$BAG")" && pwd)" bag_name="$(basename "$BAG")" tmp="$(mktemp -d)" SMI="$(command -v nvidia-smi || true)" [ -z "$SMI" ] && [ -x /usr/lib/wsl/lib/nvidia-smi ] && SMI=/usr/lib/wsl/lib/nvidia-smi gpu_sample() { # $1 — файл, $2 — секунд [ -n "$SMI" ] || return 0 timeout "$2" "$SMI" --query-gpu=utilization.gpu,memory.used \ --format=csv,noheader,nounits -lms 500 > "$1" 2>/dev/null || true } gpu_sample "$tmp/gpu_idle.csv" 5 docker rm -f fg_usage >/dev/null 2>&1 || true docker run -d --name fg_usage --network host --ipc host "${GPU[@]}" flyguard >/dev/null for _ in $(seq 1 40); do docker logs fg_usage 2>&1 | grep -q "вычисления: видеокарта\|вычисления: процессор" && break sleep 1 done docker logs fg_usage 2>&1 | grep -o "вычисления: [^,(]*" | tail -1 ( while docker inspect fg_usage >/dev/null 2>&1; do docker stats --no-stream --format '{{.CPUPerc}} {{.MemUsage}}' fg_usage 2>/dev/null done ) > "$tmp/cpu.txt" & CS=$! gpu_sample "$tmp/gpu_run.csv" 600 & GS=$! docker run --rm --network host --ipc host -e NODE=external \ -v "$bag_dir:/data:ro" -v "$here:/smoke:ro" flyguard \ bash /smoke/demo_test.sh "/data/$bag_name" 2>&1 | grep -E "кадр|итог|принято|обработ" | head -8 docker kill --signal=INT fg_usage >/dev/null 2>&1 sleep 3 kill "$CS" "$GS" 2>/dev/null pkill -f "nvidia-smi --query-gpu" 2>/dev/null || true docker logs fg_usage 2>&1 | grep -E "итог" | sed 's/.*\] //' docker rm -f fg_usage >/dev/null 2>&1 echo echo "=== узел: процессор (100 % = одно ядро) и память ===" awk '{gsub("%","",$1); if ($1+0 > 1) print $1+0}' "$tmp/cpu.txt" | sort -n | awk ' {v[NR]=$1} END {if (NR) {i = int(NR * 0.95) + 1; if (i > NR) i = NR printf "процессор: медиана %.0f %%, 95 %% замеров ниже %.0f %% (%d замеров)\n", v[int(NR/2)+1], v[i], NR}}' awk '{print $2}' "$tmp/cpu.txt" | sort -h | tail -1 | sed 's/^/память, наибольшая: /' if [ -s "$tmp/gpu_run.csv" ]; then echo "=== видеокарта (вся машина, прибавка к фону) ===" awk -F', *' 'NR==FNR {u0+=$1; m0+=$2; n0++; next} {u[++n]=$1; if ($2>mx) mx=$2} END {asort(u); printf "загрузка: фон %.0f %%, при работе медиана %.0f %%, наибольшая %.0f %%\n", u0/n0, u[int(n/2)+1], u[n]; printf "память видеокарты: +%.0f МБ к фону (%.0f МБ)\n", mx - m0/n0, m0/n0}' \ "$tmp/gpu_idle.csv" "$tmp/gpu_run.csv" fi rm -rf "$tmp"