Как компьютер выполняет программу
Процессор, память, диск и видеокарта на кухонных аналогиях; что такое программа, язык и интерпретатор Python; файлы и пути; как текст и дробные числа превращаются в байты — и первые строки на Python прямо в браузере.
Зачем это нужно
Заголовок раздела «Зачем это нужно»Очень скоро вы встретите сообщения вроде CUDA out of memory, «веса модели — 14 ГБ в BF16»
или UnicodeDecodeError. Все они про одно: как устроен компьютер и как он хранит данные.
Без этих знаний ошибки выглядят как заклинания. С ними — как понятные подсказки.
Это урок компьютерной грамотности для будущего AI-инженера. Мы разберём, из чего состоит компьютер и почему для ИИ так важны видеокарты, что такое программа и как Python её выполняет, как устроены файлы и пути, как текст и дробные числа превращаются в биты. А в конце напишете свои первые строки на Python — прямо здесь, в браузере, ничего не устанавливая.
Из чего состоит компьютер: кухня ресторана
Заголовок раздела «Из чего состоит компьютер: кухня ресторана»Удобно представить компьютер как кухню ресторана.
| Часть компьютера | На кухне | Что делает |
|---|---|---|
| Процессор (CPU)центральный процессор (CPU)EN central processing unit (CPU)Универсальный «мозг» компьютера — от нескольких до десятков мощных ядер; каждое быстро выполняет любые инструкции одну за другой. | Шеф-повара | Выполняет любые инструкции: считает, сравнивает, принимает решения. Ядер (поваров) немного, но каждое очень умелое |
| Оперативная памятьоперативная память (ОЗУ, RAM)EN random-access memory (RAM)Быстрая память для данных работающих программ. При выключении питания стирается. (RAM) | Рабочий стол | Здесь лежат данные, с которыми работают прямо сейчас. Быстро, но места мало, а при выключении стол убирают дочиста |
| Диск (SSD, HDD)диск, постоянная память (SSD, HDD)EN storage, disk driveХранит файлы, пока компьютер выключен. Больше и дешевле оперативной памяти, но медленнее. | Кладовая | Хранит всё — программы, фото, модели — даже без питания. Огромная, но ходить туда дольше |
| Видеокарта (GPU)графический процессор (GPU, видеокарта)EN graphics processing unit (GPU)Тысячи простых вычислительных ядер. Идеально подходит для матричных умножений, поэтому на GPU обучают нейросети. | Цех из тысяч поварят | Каждый умеет немного — например, только резать морковь, — зато все режут одновременно |
| Видеопамятьвидеопамять (VRAM)EN video memory (VRAM)Собственная память видеокарты. Веса модели и промежуточные данные должны поместиться сюда, иначе GPU не сможет их быстро обрабатывать. (VRAM) | Стол цеха | Своя память видеокарты. Всё, с чем работает GPU, должно лежать здесь |
Любая программа работает по одной схеме: данные достают из кладовой (диска), раскладывают на столе (в оперативной памяти), и повара (процессор или видеокарта) их обрабатывают.
flowchart LR D["Диск<br/>файлы, веса модели"] -->|"загрузка"| R["Оперативная память<br/>(RAM)"] R <--> C["Процессор<br/>(CPU)"] R <-->|"шина PCIe"| V["Видеопамять<br/>(VRAM)"] V <--> G["Видеокарта<br/>(GPU)"]
Вот как это выглядит в цифрах на вашей машине:
| Компонент | У вас | Скорость чтения (порядок) |
|---|---|---|
| Диски | 3 × Samsung 990 Pro по 1 ТБ (NVMe SSD) | около 7 ГБ/с каждый |
| Оперативная память | 128 ГБ DDR4-3200, до 8 каналов | до 200 ГБ/с (теоретический максимум, если заняты все 8 каналов) |
| Процессор | AMD EPYC 7H43: 48 ядер, 96 потоков | — |
| Видеокарты | 4 × RTX 4080 по 32 ГБ видеопамяти | около 700 ГБ/с у каждой |
Оперативная память быстрее диска в 15–30 раз (смотря сколько каналов памяти занято), а видеопамять быстрее оперативной ещё в несколько раз. Отсюда два практических вывода:
- Модель на 14 ГБ даже с быстрого NVMe грузится несколько секунд. Поэтому модель загружают один раз, а потом много раз используют.
- Сообщение
CUDA out of memoryозначает «на столе цеха не хватило места»: веса модели и промежуточные данные не поместились в видеопамять. Лечится уменьшением данных или хранением чисел в меньшем числе байт (об этом ниже).
Почему для ИИ нужны видеокарты
Заголовок раздела «Почему для ИИ нужны видеокарты»Работа нейросети — это в основном умножения и сложения. Огромное количество однотипных умножений. Внутри слоя средней языковой модели список из 4096 чисел (его называют вектором) умножается на таблицу чисел (матрицу) 4096 × 4096 — это почти 17 миллионов умножений. На один токен. А таких матриц в слое несколько, и слоёв — десятки.
Главное: эти умножения не зависят друг от друга, их можно делать одновременно. Представьте, что нужно проверить диктанты 10 000 школьников. Профессор сделает это идеально, но по одному. Стадион из 10 000 студентов, каждый со своим диктантом, справится за минуту.
- Процессор — профессор. У вашего EPYC 48 мощных ядер.
- Видеокарта — стадион. У RTX 4080 почти 10 тысяч простых вычислительных ядер (9728 CUDA-ядер).
Видеокарты придумали для игр: каждый пиксель на экране можно раскрашивать независимо от других. В 2012 году нейросеть AlexNet, обученная на двух игровых видеокартах, с большим отрывом выиграла конкурс по распознаванию изображений ImageNet. С этого момента и начался бум глубокого обучения, а видеокарты стали главным «топливом» ИИ.
Что такое программа
Заголовок раздела «Что такое программа»ПрограммапрограммаEN programПоследовательность инструкций для компьютера, записанная в файле. — это рецепт: последовательность инструкций, записанная в файле. «Возьми число, умножь на 2, если больше 10 — напечатай “много”». Процессор выполняет инструкции одну за другой — миллиарды в секунду.
Но процессор понимает только машинный кодмашинный кодEN machine codeИнструкции в виде чисел — единственное, что процессор понимает напрямую. — инструкции, закодированные числами. Писать числами неудобно, поэтому люди придумали языки программированияязык программированияEN programming language: Python, C, C++, JavaScript, Rust, CUDA. Это способ записать рецепт понятными человеку словами, который потом переводится в машинный код.
Компилятор и интерпретатор
Заголовок раздела «Компилятор и интерпретатор»Перевести программу в машинный код можно двумя способами — как перевести книгу.
| КомпиляторкомпиляторEN compilerПрограмма, которая заранее переводит весь код в машинный. Так работают C, C++, Rust, CUDA. | ИнтерпретаторинтерпретаторEN interpreterПрограмма, которая читает код и сразу выполняет его строку за строкой. Python — интерпретируемый язык. | |
|---|---|---|
| Аналогия | Переводчик книги: сначала переводит целиком, потом вы читаете | Синхронный переводчик: переводит фразу за фразой прямо во время разговора |
| Когда видно ошибку | До запуска, при переводе | Ошибки записи — сразу при запуске, остальные — когда выполнение дойдёт до ошибочной строки |
| Скорость работы | Очень быстро | Медленнее |
| Языки | C, C++, Rust, CUDA | Python, JavaScript |
Одна и та же программа на C и на Python:
#include <stdio.h>
int main(void) { printf("Привет, мир!\n"); return 0;}print("Привет, мир!")На Python — одна строка. Программу на C нужно сначала скомпилировать отдельной командой и только потом запускать. Программу на Python можно запускать сразу.
Почему Python — язык ИИ
Заголовок раздела «Почему Python — язык ИИ»Python медленнее C. Почему же на нём пишут почти весь код для ИИ — от учебных примеров до обучения DeepSeek?
- Простой синтаксис. Код читается почти как английский текст — идеально для экспериментов.
- Огромные библиотеки. NumPy, PyTorch, Hugging Face Transformers, vLLM — всё доступно одной командой установки.
- Тяжёлую работу делает не Python. Когда вы пишете на PyTorch
y = x @ W(умножить матрицы), Python лишь отдаёт команду. Само умножение выполняет быстрый код на C++ и CUDACUDAEN CUDA (Compute Unified Device Architecture)Платформа NVIDIA для вычислений на видеокартах. В PyTorch видеокарта NVIDIA — это устройство"cuda"("cuda:0","cuda:1"…). прямо на видеокарте (CUDA — платформа NVIDIA, на которой пишут программы для видеокарт). Python — дирижёр, а оркестр играет на GPU.
Как запускается программа на Python
Заголовок раздела «Как запускается программа на Python»- Вы пишете текст программы в файл, например
hello.py. Расширение.pyподсказывает, что внутри код на Python. - Запускаете команду
python hello.pyв терминале — окне для текстовых команд (о нём в уроке 0.1.1). Интерпретатор Python читает файл с диска в память. - Python выполняет строки сверху вниз: первая, вторая, третья…
- Если на какой-то строке ошибка, выполнение останавливается и Python печатает сообщение. Читать такие сообщения научимся в следующем уроке.
Кроме файлов, код запускают в интерактивном режиме (приглашение >>>: ввели строку — сразу получили ответ),
в Jupyter-блокнотах и прямо в браузере. Задания на этом сайте работают через Pyodide — это интерпретатор Python,
собранный так, чтобы работать внутри браузера. Установка Python на компьютер — в уроке 0.1.2.
Файлы, папки и пути
Заголовок раздела «Файлы, папки и пути»Файл — это именованная последовательность байт на диске. У имени обычно есть расширение
после точки, которое подсказывает формат: .py — код на Python, .txt — текст, .json — структурированные данные,
.safetensors — веса нейросети. Расширение — просто часть имени: переименовав photo.jpg в photo.txt,
вы не превратите картинку в текст.
Папки (директории) содержат файлы и другие папки — получается дерево. Например, так может выглядеть репозиторий курса на вашем компьютере:
/home/user/ChinaAI/├── README.md├── homework/│ └── s0-hw01-python-warmup/│ ├── README.md│ └── code/└── site/Путь к файлупуть к файлуEN file pathАдрес файла в дереве папок, например /home/mei/ChinaAI/README.md (Linux, macOS) или C:\Users\Mei\ChinaAI\README.md (Windows). — это адрес файла в дереве, имена папок через разделитель.
| Linux и macOS | Windows | |
|---|---|---|
| Разделитель | / | \ (Python понимает и /) |
| Пример абсолютного пути | /home/user/ChinaAI/README.md | C:\Users\Anya\ChinaAI\README.md |
| Большие и маленькие буквы | различаются: Data.txt и data.txt — разные файлы | не различаются |
Абсолютный путь начинается от корня диска и работает откуда угодно. Относительный отсчитывается
от текущей папки: если вы находитесь в /home/user/ChinaAI/homework, то путь ../README.md
ведёт к файлу /home/user/ChinaAI/README.md. Здесь .. значит «на уровень выше», а . — «текущая папка».
Биты и байты
Заголовок раздела «Биты и байты»Внутри компьютера миллиарды крошечных переключателей — транзисторов. Каждый может быть включён или выключен, то есть хранит 1 или 0. Это битбитEN bitНаименьшая единица информации — 0 или 1. — наименьшая единица информации.
Один бит различает 2 варианта. Два бита — 4 варианта (00, 01, 10, 11). Три бита — 8 вариантов (000, 001, …, 111). Каждый новый бит удваивает число вариантов: вариантов для бит. Запись читается «два в степени эн» и означает «двойку умножить саму на себя раз»: . Так компьютер записывает числа в двоичной системе:
| Десятичное | Двоичное |
|---|---|
| 0 | 0 |
| 1 | 1 |
| 2 | 10 |
| 5 | 101 |
| 255 | 11111111 |
Как читать двоичную запись: разряды справа налево «стоят» 1, 2, 4, 8, 16… — каждый вдвое больше предыдущего (в привычной десятичной системе — 1, 10, 100…). Складываем разряды, где стоит единица: , а . Переводить числа в уме не понадобится — важно понимать идею.
Восемь бит — это байтбайтEN byte8 бит, 256 возможных значений (от 0 до 255). В байтах измеряют размер файлов, памяти и моделей.: вариантов, числа от 0 до 255. В байтах измеряют всё:
| Что | Размер (примерно) |
|---|---|
| Одна русская буква в UTF-8 | 2 байта |
| Роман на 300 страниц, обычный текст | около 1 МБ |
| Фото со смартфона | 3–5 МБ |
| Модель на 7 млрд параметров в BF16 | 14 ГБ |
| DeepSeek-V3 (671 млрд параметров) в FP8 | около 700 ГБ |
Здесь 1 КБ ≈ тысяча байт, 1 МБ ≈ миллион, 1 ГБ ≈ миллиард, 1 ТБ ≈ триллион.
Текст и кодировки
Заголовок раздела «Текст и кодировки»Компьютер хранит только числа. Чтобы хранить текст, нужна договорённость: какой букве соответствует какое число.
В 1960-х появилась таблица ASCII — 128 символов: английские буквы, цифры, знаки препинания. Ни русских букв, ни иероглифов. Каждая страна придумала свою таблицу: для русского — KOI8-R и Windows-1251, для китайского — GB2312 и GBK. Пока файл читают «своей» таблицей, всё хорошо. Откройте его чужой — и вместо текста появится каша, «кракозябры».
Решение — ЮникодЮникодEN UnicodeЕдиная таблица символов всех письменностей; каждому символу соответствует номер (code point), например «я» = U+044F, «λ» = U+03BB.: единая таблица для всех письменностей мира, больше 150 тысяч символов (и место для новых ещё есть).
Каждый символ получил номер (code point). В Python номер символа даёт ord, а символ по номеру — chr:
| Символ | Номер в Юникоде |
|---|---|
A | 65 |
я | 1103 |
€ | 8364 |
😀 | 128512 |
Но номер — это ещё не байты. Как записать номер 8364 на диск? Это решает кодировкакодировка (символов)EN character encodingСпособ записать символы байтами. UTF-8: латиница — 1 байт, кириллица — 2, китайские иероглифы — 3.. Самая популярная кодировка — UTF-8. Она экономная: маленькие номера (латиница) занимают 1 байт, большие — до 4 байт.
| Строка | Символов | Байт в UTF-8 | Почему |
|---|---|---|---|
"Hello" | 5 | 5 | латиница — по 1 байту |
"Привет" | 6 | 12 | кириллица — по 2 байта |
"€₽" | 2 | 6 | знаки валют — по 3 байта (как и китайские иероглифы) |
"😀" | 1 | 4 | эмодзи — 4 байта |
Так что русский текст действительно «весит» больше английского: буква «я» — это два байта d1 8f,
знак «€» — три байта e2 82 ac, а эмодзи «😀» — четыре: f0 9f 98 80.
Если байты UTF-8 прочитать чужой кодировкой, получатся кракозябрыкракозябры (mojibake)EN mojibakeНечитаемый текст из-за декодирования байтов не той кодировкой, например «РџСЂРёРІРµС‚» вместо «Привет»..
Слово «Привет», записанное в UTF-8 и прочитанное как Windows-1251, превращается в Привет.
А прочитанное как западноевропейская Windows-1252 — в Привет. Увидели такое — почти наверняка перепутана кодировка.
Почему это важно для LLM. Токенизаторы многих моделей работают с байтами текста. Токенизатор, обученный в основном на английском, режет русский текст на больше токенов, чем английский того же смысла. А больше токенов — дороже запрос, медленнее ответ и меньше текста помещается в контекст. В словарях Qwen и DeepSeek много токенов для китайского языка, поэтому китайский текст они режут экономно. Мы вернёмся к этому по спирали: в уроке о файлах (0.2.4) и на ступени 4, когда будем строить токенизатор на байтах.
Числа с плавающей точкой
Заголовок раздела «Числа с плавающей точкой»С целыми числами просто: двоичная запись. А как хранить 3.14 или 0.0015? Вспомните
научную записьнаучная (экспоненциальная) записьEN scientific notation3e-4 = 3·10⁻⁴ = 0.0003; 6.71e11 = 671 млрд. из школы:
, а . Здесь — единица с шестью нулями (миллион),
а — одна тысячная, 0.001. Значащие цифры (их называют мантиссой) одни и те же — 1.5,
а порядок (степень десятки) говорит, на сколько позиций сдвинуть точку вправо или влево: — на шесть
вправо, — на три влево. В Python научную запись пишут через букву e: 1.5e6 — это 1 500 000,
а 3e-4 — 0.0003. Такие числа вы будете постоянно встречать в коде обучения.
Компьютер делает так же, только в двоичной системе: .
Это число с плавающей точкойчисло с плавающей точкой (float)EN floating-point numberСпособ хранить дробные числа как «мантисса × 2 в степени». Форматы: FP32 (4 байта), FP16 и BF16 (2 байта), FP8 (1 байт). (по-английски float): точка «плавает» в зависимости от порядка.
На мантиссу отводится конечное число бит, и тут сюрприз. Дробь 1/3 в десятичной системе — бесконечная: 0.3333… А в двоичной системе бесконечной оказывается привычная 0.1. Компьютер хранит её с крошечной ошибкой, и:
print(0.1 + 0.2)print(0.1 + 0.2 == 0.3)0.30000000000000004FalseЭто не баг Python — так работают дробные числа во всех языках. Вывод для практики: дробные числа сравнивают
не через ==, а «с допуском» (как именно — в уроке 0.2.1).
Сколько байт на число: FP32, FP16, BF16, FP8
Заголовок раздела «Сколько байт на число: FP32, FP16, BF16, FP8»Чем больше байт отвести на число, тем оно точнее, но тем больше памяти занимает. Вот как разные форматы хранят одно и то же число 0.1:
| Формат | Байт | Как хранится 0.1 | Максимум | Где в ИИ |
|---|---|---|---|---|
FP64 (обычный float в Python) | 8 | 0.1000000000000000055… | научные расчёты | |
| FP32 | 4 | 0.10000000149… | классическое обучение нейросетей | |
| FP16 | 2 | 0.0999755859375 | 65 504 | обучение и запуск моделей |
| BF16 | 2 | 0.10009765625 | стандарт обучения LLM | |
| FP8 (E4M3) | 1 | 0.1015625 | 448 | обучение DeepSeek-V3 |
FP — от floating point, число — сколько бит отведено на число: FP32 — 32 бита (4 байта), FP16 — 16 бит (2 байта). BF16 — тоже 16 бит, но поделены они иначе: больше бит на порядок, меньше на мантиссу. Поэтому максимум у BF16 огромный, как у FP32, а точность грубее, чем у FP16. E4M3 — разновидность FP8: 4 бита на порядок, 3 на мантиссу.
Чем меньше байт, тем грубее число. В FP16, например, 1000.3 превращается в 1000.5, а 2049 — в 2048: для числа 2049 просто не хватает значащих цифр. Проверить это можно кодом ниже: допишите его в конец кода в окне задания из раздела «Практика» и нажмите «▶ Запустить».
import struct
def to_fp16(x): # упаковать число в 2 байта (формат FP16) и сразу распаковать обратно return struct.unpack("e", struct.pack("e", x))[0]
print(0.1 + 0.2)print(to_fp16(0.1))print(to_fp16(1000.3))print(to_fp16(2049.0))0.300000000000000040.09997558593751000.52048.0Зачем же жертвовать точностью? Ради памяти и скорости. Прикинуть вес модели легко: число параметров × байт на параметр.
| Модель | BF16 (2 байта) | FP8 (1 байт) | 4 бита (0.5 байта) |
|---|---|---|---|
| 7 млрд параметров | 14 ГБ | 7 ГБ | 3.5 ГБ |
| 70 млрд параметров | 140 ГБ | 70 ГБ | 35 ГБ |
У вас 4 × 32 = 128 ГБ видеопамяти. Модель на 70 млрд параметров в BF16 (140 ГБ) не поместится, а в 4 битах (35 ГБ) — легко, ещё и место останется. Это прикидка только для весов: при работе модели нужна ещё память на промежуточные вычисления, поэтому всегда держите запас. Вот почему вся индустрия борется за каждый бит: обучение в смешанной точности — модуль 5.4, квантование для запуска — модуль 7.2.
Практика
Заголовок раздела «Практика»Пора написать первые строки. Ниже — окно с кодом на Python. Как с ним работать:
- ▶ Запустить выполняет код и показывает, что напечатал
print. ✓ Проверить запускает автотесты. 💡 Подсказка открывает подсказки по одной, ↺ Сбросить возвращает исходный код. - Строки после
#— комментарии для людей, Python их пропускает. print(...)печатает то, что в скобках. Текст берут в кавычки:"Привет".- Запись
имя = выражениезначит: «посчитай то, что справа, и запомни результат под именем слева». Подробно о таких именах (переменных) — в модуле 0.2. ord("я")даёт номер символа,chr(1103)— символ по номеру."текст".encode("utf-8")превращает строку в байты, аlen(...)считает длину: символы у строки, байты у байтов.**— возведение в степень:2 ** 3= 8.
В каждом задании замените ... (многоточие) на выражение. Над заданиями есть готовые примеры — опирайтесь на них.
Пока вместо ответа стоит многоточие, print печатает слово Ellipsis («многоточие» по-английски) — это нормально.
Увидите красное сообщение об ошибке — не пугайтесь: в следующем уроке научимся их читать.
# Первые строки на Python.
# Строки, которые начинаются с #, — комментарии: Python их пропускает, они для людей.
# Нажмите «▶ Запустить» — и посмотрите, что напечатает print.
print("Привет, мир! Hello, world! 🌍")
print(2 + 3 * 4) # умножение раньше сложения, как в школе: 14
print((2 + 3) * 4) # скобки меняют порядок: 20
# ─── Ваши задания ────────────────────────────────────────────────────────────
# Запись «имя = выражение» значит: «посчитай то, что справа, и запомни под именем слева».
# В каждом задании замените ... (многоточие) на выражение Python.
# Над каждым заданием есть готовый пример — смотрите на него.
# 1. Сколько секунд в сутках? Пример: минут в сутках = 24 * 60
minutes_in_day = 24 * 60
seconds_in_day = ...
# 2. Сколько всего видеопамяти (ГБ) у четырёх видеокарт по 32 ГБ?
total_vram = ...
# 3. Сколько разных значений помещается в 1 байт = 8 бит?
# Пример: в 2 битах — 2 ** 2 = 4 значения (00, 01, 10, 11). ** — это степень.
values_in_2_bits = 2 ** 2
byte_values = ...
# 4. Номер символа в Юникоде даёт ord(...), символ по номеру — chr(...).
code_A = ord("A") # 65
code_ya = ... # номер русской буквы «я»
char_8364 = ... # какой символ имеет номер 8364?
# 5. Сколько байт занимает слово в кодировке UTF-8?
bytes_en = len("Hello".encode("utf-8")) # 5 — готовый пример
bytes_ru = ... # то же для "Привет"
bytes_emoji = ... # то же для "🙂👍"
# 6. Фраза из русских букв и эмодзи: сколько в ней символов и сколько байт?
phrase = "Привет, 🌍🙂"
n_chars = ... # число символов: len(phrase)
n_bytes = ... # число байт в UTF-8
# 7. Дробные числа: чему равно 0.1 + 0.2 и совпадает ли это с 0.3?
float_sum = ...
is_exact = ... # сравнение: float_sum == 0.3 (ответ — True или False)
# Нажмите «▶ Запустить», чтобы увидеть свои ответы, и «✓ Проверить», чтобы запустить тесты.
# Пока в задании стоит ..., print напечатает на его месте слово Ellipsis («многоточие») — это нормально.
print(seconds_in_day, total_vram, byte_values)
print(code_ya, char_8364)
print(bytes_en, bytes_ru, bytes_emoji)
print(n_chars, n_bytes)
print(float_sum, is_exact)
Проверь себя
Заголовок раздела «Проверь себя»- Компьютер — кухня: процессор — шеф-повара, оперативная память — рабочий стол, диск — кладовая, видеокарта — цех из тысяч поварят со своим столом (VRAM).
- Нейросети обучают на GPU, потому что их работа — миллиарды независимых умножений, которые тысячи ядер делают одновременно.
- Программа — рецепт из инструкций. Python — интерпретируемый язык: пишете код и сразу запускаете, а тяжёлую математику выполняют библиотеки на C++ и CUDA.
- Текст — это номера символов (Юникод), записанные байтами (UTF-8): латиница — 1 байт, кириллица — 2, знак € (как и китайский иероглиф) — 3, эмодзи — 4.
- Дробные числа хранятся приближённо:
0.1 + 0.2 ≠ 0.3. Чем меньше байт на число (FP16, FP8, 4 бита), тем меньше памяти и ниже точность.
Дальше: как учиться программированию с нуля — читать сообщения об ошибках, правильно спрашивать ИИ-помощника и не бросить на полпути. С китайскими практиками «тетради ошибок» и ежедневной отметки о занятиях.