diff --git a/labs/lab2/assets/1.png b/labs/lab2/assets/1.png new file mode 100644 index 0000000..0f310e8 Binary files /dev/null and b/labs/lab2/assets/1.png differ diff --git a/labs/lab2/assets/10.png b/labs/lab2/assets/10.png new file mode 100644 index 0000000..a25b4dd Binary files /dev/null and b/labs/lab2/assets/10.png differ diff --git a/labs/lab2/assets/11.png b/labs/lab2/assets/11.png new file mode 100644 index 0000000..5a2442d Binary files /dev/null and b/labs/lab2/assets/11.png differ diff --git a/labs/lab2/assets/2.png b/labs/lab2/assets/2.png new file mode 100644 index 0000000..829eab1 Binary files /dev/null and b/labs/lab2/assets/2.png differ diff --git a/labs/lab2/assets/3.png b/labs/lab2/assets/3.png new file mode 100644 index 0000000..15e4798 Binary files /dev/null and b/labs/lab2/assets/3.png differ diff --git a/labs/lab2/assets/4.png b/labs/lab2/assets/4.png new file mode 100644 index 0000000..d3a3eb7 Binary files /dev/null and b/labs/lab2/assets/4.png differ diff --git a/labs/lab2/assets/5.png b/labs/lab2/assets/5.png new file mode 100644 index 0000000..1de2c81 Binary files /dev/null and b/labs/lab2/assets/5.png differ diff --git a/labs/lab2/assets/6.png b/labs/lab2/assets/6.png new file mode 100644 index 0000000..06bb5e1 Binary files /dev/null and b/labs/lab2/assets/6.png differ diff --git a/labs/lab2/assets/7.png b/labs/lab2/assets/7.png new file mode 100644 index 0000000..864f375 Binary files /dev/null and b/labs/lab2/assets/7.png differ diff --git a/labs/lab2/assets/8.png b/labs/lab2/assets/8.png new file mode 100644 index 0000000..5916429 Binary files /dev/null and b/labs/lab2/assets/8.png differ diff --git a/labs/lab2/assets/9.png b/labs/lab2/assets/9.png new file mode 100644 index 0000000..147dc42 Binary files /dev/null and b/labs/lab2/assets/9.png differ diff --git a/labs/lab2/report.pdf b/labs/lab2/report.pdf new file mode 100644 index 0000000..99486f6 Binary files /dev/null and b/labs/lab2/report.pdf differ diff --git a/labs/lab2/report.typ b/labs/lab2/report.typ new file mode 100644 index 0000000..de325a8 --- /dev/null +++ b/labs/lab2/report.typ @@ -0,0 +1,254 @@ +#set text(size: 1.3em) + +#show raw.where(block: false): box.with( + fill: luma(240), + inset: (x: 3pt, y: 0pt), + outset: (y: 3pt), + radius: 2pt, +) + +#show raw.where(block: true): block.with( + fill: luma(240), + inset: 10pt, + radius: 4pt, +) + +// title + +#align(center)[Санкт-Петербургский национальный исследовательский университет информационных технологий, механики и оптики] +\ +\ +\ +#align(center)[Факультет инфокоммуникационных технологий] +#align(center)[Направление подготовки 11.03.02] +\ +\ +#align(center)[Лабораторная работа №2] +#align(center)[Создание и использование размерных типов данных] +\ +\ +\ //#align(center)[Вариант 19] +\ +\ +\ +\ +\ +\ +\ +#align(right)[Выполнил:] +#align(right)[Дощенников Никита Андреевич] +#align(right)[Группа: К3221] +#align(right)[Проверил:] +#align(right)[Береснев Артем Дмитриевич] +\ +\ +#align(center)[Санкт-Петербург] +#align(center)[2025] + +#pagebreak() + +=== Цель работы: + +Получить практические навыки программирования на bash, освоить практические приемы работы с командной оболочкой bash. + +=== Часть 1. Работа в среде bash. + +Для изменения приглашения командной строки я отредактировал файл `~/.bashrc`, добавив туда строку: + +```bash +PS1='\t \u \w \$ ' +``` + +Теперь приглашение отображает текущее время, имя пользователя, текущий каталог и символ `$`. + +#align(center)[#image("assets/1.png")] + +Создал алиас для вывода приветствия: + +```bash +alias hi='echo "Have a nice day, $(whoami)!"' +``` + +После этого при вводе команды `hi` в терминале появляется строка с приветствием и именем текущего пользователя. + +#align(center)[#image("assets/2.png")] + +Чтобы изменения сохранились при перезапуске, эти строки были добавлены в файл `~/.bashrc`. Применил изменения без выхода из системы командой: + +```bash +source ~/.bashrc +``` + +=== Часть 2. Простые задачи на bash. + +1. Принимает две строки как параметры и сравнивает их. + +```bash +#!/bin/bash +[ "$#" -ne 2 ] && echo "usage: $0 str1 str2" && exit 1 +[ "$1" = "$2" ] && echo "equal" || echo "not equal" +``` + +#align(center)[#image("assets/3.png")] + +2. Принимает три целых числа и находит максимальное из них. + +```bash +#!/bin/bash +[ "$#" -ne 3 ] && echo "usage: $0 a b c" && exit 1 +a=$1 +b=$2 +c=$3 +max=$a +(( b > max )) && max=$b +(( c > max )) && max=$c +echo "$max" +``` + +#align(center)[#image("assets/4.png")] + +3. Считывает строки до тех пор, пока не встретится строка `q`. После завершения цикла все введённые строки объединяются и выводятся в одну строку. + +```bash +#!/bin/bash +arr=() +while IFS= read -r line; do + [ "$line" = "q" ] && break + arr+=("$line") +done +printf "%s" "${arr[*]}" +``` + +#align(center)[#image("assets/5.png")] + +4. Считывает последовательность целых чисел. Чтение продолжается, пока не встретится чётное число. После этого выводится количество введённых чисел до него. + +```bash +#!/bin/bash +count=0 +while IFS= read -r n; do + r=$(( n % 2 )) + [ "$r" -eq 0 ] && break + count=$(( count + 1 )) +done +echo "$count" +``` + +#align(center)[#image("assets/6.png")] + +5. Создано текстовое меню с четырьмя пунктами: запуск редактора `nano`, редактора `vi`, браузера `links`, или выход. Перед выполнением команда `command -v` проверяет наличие программ. Если программа не установлена — выводится сообщение и скрипт завершается. + +```bash +#!/bin/bash +for cmd in nano vi links; do + command -v "$cmd" >/dev/null 2>&1 || { echo "$cmd is not installed"; exit 1; } +done +echo "1) nano" +echo "2) vi" +echo "3) links" +echo "4) exit" +read -r -p "choose 1-4: " choice +case "$choice" in + 1) exec nano ;; + 2) exec vi ;; + 3) exec links ;; + 4) exit 0 ;; + *) echo "invalid choice" ; exit 1 ;; +esac +``` + +#align(center)[#image("assets/7.png")] +#align(center)[#image("assets/8.png")] + +6. Принимает три параметра: имя файла, режим (`h` или `t`), и число строк. В режиме `h` печатаются первые N строк файла (`head -n`). В режиме `t` — последние N строк (`tail -n`). Ошибки при отсутствии файла подавляются перенаправлением `2>/dev/null`. + +```bash +#!/bin/bash +[ "$#" -ne 3 ] && echo "usage: $0 file h|t N" && exit 1 +file=$1 +mode=$2 +num=$3 +case "$mode" in + h) head -n "$num" -- "$file" 2>/dev/null ;; + t) tail -n "$num" -- "$file" 2>/dev/null ;; + *) echo "mode must be h or t" ; exit 1 ;; +esac +``` + +#align(center)[#image("assets/6.png")] + +=== Часть 3. Разработка скрипта расчета производительности. + +1. В этой части требовалось написать скрипт `script23`, который измеряет производительность CPU в FLOPS (Floating Point Operations Per Second). Для этого необходимо было реализовать большое количество операций с плавающей запятой и зафиксировать время их выполнения. + +2. Для вычислений использовалась утилита `bc`, так как она позволяет работать с произвольной точностью. В скрипте выставлена точность `scale=10`. + +3. В скрипте организована функция `bench`, в которой выполняется $N$ умножений двух одинаковых чисел. Параметр $N$ можно передать в скрипт, по умолчанию используется 1 000 000. + +4. С помощью команды `date +%s.%N` время сохраняется до и после выполнения функции. Далее определяется разница во времени и вычисляется показатель FLOPS по формуле: + +$ +F L O P S = frac(N, Delta t) +$ + +5. В завершении программа выводит три значения: количество итераций, время выполнения в секундах, и рассчитанный FLOPS. + +```bash +#!/bin/bash +n=${1:-1000000} +command -v bc >/dev/null 2>&1 || { echo "bc is required"; exit 1; } + +bench() { + printf 'scale=10\na=1.2345678901\nb=1.2345678901\nfor(i=0;i<%s;i++) x=a*b\n' "$n" | bc >/dev/null +} + +start=$(date +%s.%N) +bench +end=$(date +%s.%N) + +dur=$(echo "$end - $start" | bc -l) +flops=$(echo "$n / $dur" | bc -l) + +printf "iterations=%s\ntime_s=%s\nFLOPS=%s\n" "$n" "$dur" "$flops" +``` + +#align(center)[#image("assets/10.png")] + +=== Вопросы. + +==== 1. Как определить сколько параметров пользователь передал в скрипт при запуске? + +В bash для этого используется специальная переменная `$#`. +Она хранит количество аргументов, переданных скрипту. +Пример: + +```bash +echo "amount of params: $#" +``` + +==== 2. Что выведет простой скрипт с постдекрементом? + +Код: + +```bash +count=10 +echo $(( count-- )) +echo $(( count-- )) +``` + +#align(center)[#image("assets/11.png")] + +Первая строка напечатает `10`, потому что оператор постдекремента возвращает старое значение, а потом уменьшает переменную. После этой операции `count=9`. Вторая строка напечатает `9` — аналогично. + +==== 3. Недостатки подхода к определению FLOPS в нашем скрипте + +- Измеряется не только операция умножения, но и работа интерпретатора bash и программы `bc`. +- Не используется SIMD (векторные инструкции) и многопоточность, поэтому результат сильно занижен. +- Выполняется только умножение одинаковых чисел, что не отражает реальную работу CPU. +- На результат влияют другие процессы в системе, частота процессора, троттлинг, кэш. +- Такой метод больше демонстрационный и не сопоставим с эталонными тестами на C/Fortran. + +=== Вывод. + +В ходе проделанной работы я получил практические навыки программирования на bash, освоил практические приемы работы с командной оболочкой bash. + diff --git a/labs/lab2/scripts/q.sh b/labs/lab2/scripts/q.sh new file mode 100755 index 0000000..f5b2a49 --- /dev/null +++ b/labs/lab2/scripts/q.sh @@ -0,0 +1,3 @@ +count=10 +echo $(( count-- )) +echo $(( count-- )) diff --git a/labs/lab2/scripts/script221.sh b/labs/lab2/scripts/script221.sh new file mode 100755 index 0000000..6439064 --- /dev/null +++ b/labs/lab2/scripts/script221.sh @@ -0,0 +1,3 @@ +#!/bin/bash +[ "$#" -ne 2 ] && echo "usage: $0 str1 str2" && exit 1 +[ "$1" = "$2" ] && echo "equal" || echo "not equal" diff --git a/labs/lab2/scripts/script222.sh b/labs/lab2/scripts/script222.sh new file mode 100755 index 0000000..0e95d48 --- /dev/null +++ b/labs/lab2/scripts/script222.sh @@ -0,0 +1,9 @@ +#!/bin/bash +[ "$#" -ne 3 ] && echo "usage: $0 a b c" && exit 1 +a=$1 +b=$2 +c=$3 +max=$a +(( b > max )) && max=$b +(( c > max )) && max=$c +echo "$max" diff --git a/labs/lab2/scripts/script223.sh b/labs/lab2/scripts/script223.sh new file mode 100755 index 0000000..d37257a --- /dev/null +++ b/labs/lab2/scripts/script223.sh @@ -0,0 +1,8 @@ +#!/bin/bash +arr=() +while IFS= read -r line; do + [ "$line" = "q" ] && break + arr+=("$line") +done +printf "%s" "${arr[*]} " + diff --git a/labs/lab2/scripts/script224.sh b/labs/lab2/scripts/script224.sh new file mode 100755 index 0000000..2a89043 --- /dev/null +++ b/labs/lab2/scripts/script224.sh @@ -0,0 +1,9 @@ +#!/bin/bash +count=0 +while IFS= read -r n; do + r=$(( n % 2 )) + [ "$r" -eq 0 ] && break + count=$(( count + 1 )) +done +echo "$count" + diff --git a/labs/lab2/scripts/script225.sh b/labs/lab2/scripts/script225.sh new file mode 100755 index 0000000..991f8de --- /dev/null +++ b/labs/lab2/scripts/script225.sh @@ -0,0 +1,17 @@ +#!/bin/bash +for cmd in nano vi links; do + command -v "$cmd" >/dev/null 2>&1 || { echo "$cmd is not installed"; exit 1; } +done +echo "1) nano" +echo "2) vi" +echo "3) links" +echo "4) exit" +read -r -p "choose 1-4: " choice +case "$choice" in + 1) exec nano ;; + 2) exec vi ;; + 3) exec links ;; + 4) exit 0 ;; + *) echo "invalid choice" ; exit 1 ;; +esac + diff --git a/labs/lab2/scripts/script226.sh b/labs/lab2/scripts/script226.sh new file mode 100755 index 0000000..cefa8db --- /dev/null +++ b/labs/lab2/scripts/script226.sh @@ -0,0 +1,11 @@ +#!/bin/bash +[ "$#" -ne 3 ] && echo "usage: $0 file h|t N" && exit 1 +file=$1 +mode=$2 +num=$3 +case "$mode" in + h) head -n "$num" -- "$file" 2>/dev/null ;; + t) tail -n "$num" -- "$file" 2>/dev/null ;; + *) echo "mode must be h or t" ; exit 1 ;; +esac + diff --git a/labs/lab2/scripts/script23.sh b/labs/lab2/scripts/script23.sh new file mode 100755 index 0000000..a189822 --- /dev/null +++ b/labs/lab2/scripts/script23.sh @@ -0,0 +1,17 @@ +#!/bin/bash +n=${1:-1000000} +command -v bc >/dev/null 2>&1 || { echo "bc is required"; exit 1; } + +bench() { + printf 'scale=10\na=1.2345678901\nb=1.2345678901\nfor(i=0;i<%s;i++) x=a*b\n' "$n" | bc >/dev/null +} + +start=$(date +%s.%N) +bench +end=$(date +%s.%N) + +dur=$(echo "$end - $start" | bc -l) +flops=$(echo "$n / $dur" | bc -l) + +printf "iterations=%s\ntime_s=%s\nFLOPS=%s\n" "$n" "$dur" "$flops" + diff --git a/labs/lab2/scripts/test b/labs/lab2/scripts/test new file mode 100644 index 0000000..b414108 --- /dev/null +++ b/labs/lab2/scripts/test @@ -0,0 +1,6 @@ +1 +2 +3 +4 +5 +6 diff --git a/labs/lab2/task.pdf b/labs/lab2/task.pdf new file mode 100644 index 0000000..4cfcdfd Binary files /dev/null and b/labs/lab2/task.pdf differ diff --git a/labs/lab3/task.pdf b/labs/lab3/task.pdf new file mode 100644 index 0000000..b19dc0c Binary files /dev/null and b/labs/lab3/task.pdf differ diff --git a/labs/lab4/task.pdf b/labs/lab4/task.pdf new file mode 100644 index 0000000..3998fa3 Binary files /dev/null and b/labs/lab4/task.pdf differ