upd
BIN
labs/lab2/assets/1.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
labs/lab2/assets/10.png
Normal file
|
After Width: | Height: | Size: 92 KiB |
BIN
labs/lab2/assets/11.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
labs/lab2/assets/2.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
labs/lab2/assets/3.png
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
labs/lab2/assets/4.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
labs/lab2/assets/5.png
Normal file
|
After Width: | Height: | Size: 131 KiB |
BIN
labs/lab2/assets/6.png
Normal file
|
After Width: | Height: | Size: 119 KiB |
BIN
labs/lab2/assets/7.png
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
labs/lab2/assets/8.png
Normal file
|
After Width: | Height: | Size: 263 KiB |
BIN
labs/lab2/assets/9.png
Normal file
|
After Width: | Height: | Size: 295 KiB |
BIN
labs/lab2/report.pdf
Normal file
254
labs/lab2/report.typ
Normal file
@@ -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.
|
||||
|
||||
3
labs/lab2/scripts/q.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
count=10
|
||||
echo $(( count-- ))
|
||||
echo $(( count-- ))
|
||||
3
labs/lab2/scripts/script221.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
[ "$#" -ne 2 ] && echo "usage: $0 str1 str2" && exit 1
|
||||
[ "$1" = "$2" ] && echo "equal" || echo "not equal"
|
||||
9
labs/lab2/scripts/script222.sh
Executable file
@@ -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"
|
||||
8
labs/lab2/scripts/script223.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
arr=()
|
||||
while IFS= read -r line; do
|
||||
[ "$line" = "q" ] && break
|
||||
arr+=("$line")
|
||||
done
|
||||
printf "%s" "${arr[*]} "
|
||||
|
||||
9
labs/lab2/scripts/script224.sh
Executable file
@@ -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"
|
||||
|
||||
17
labs/lab2/scripts/script225.sh
Executable file
@@ -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
|
||||
|
||||
11
labs/lab2/scripts/script226.sh
Executable file
@@ -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
|
||||
|
||||
17
labs/lab2/scripts/script23.sh
Executable file
@@ -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"
|
||||
|
||||
6
labs/lab2/scripts/test
Normal file
@@ -0,0 +1,6 @@
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||