Computer Science

Пишем про компьютеры и их строение для программистов, инженеров и компутерщиков.
Статьи выходят раз в неделю по пятницам или субботам.
По всем вопросам — в телеграм.

SICP. Основы

Начинаем проходить СИКП — это курс из университета МИТ. Он объясняет вычислительные процессы, как они развиваются и управляют разными данными, проще говоря — смысл абстракции в компутере.

Введение

Процессы создаются и управляются командами на языке программирования. Эти команды складываются в последовательность и получается программа.
Основными инструментами всех ЯПшек являются простейшие математические действия на два объекта: 4+5, 9/3, 200×5, 0-0
Из маленьких действий получаются и надстраиваются конструкции сложнее и сложнее:
$$ \left( \frac{3^{-\frac{5}{7}} \cdot 5^{-\frac{5}{7}}}{15^{-1} \cdot 2^{\frac{2}{7}}} \right)^{-7} $$
Всё раскладывается до простых арифметических, а потом и до логических действий.

Базовые элементы

Оригинальный курс изучается на языке Scheme, по-русски — Ским. Его особенность в том, что сначала пишется операция, а потом операнды и всё это в скобках. Это нужно для наглядности: что с чем складывается или умножается, на картинках они будут чёрного цвета.
Порядок действий такой же как и в обыкновенной математике: сначала возведение в степень и корни, потом умножение и деление, потом сложение и вычитание. Математические скобки будут зелёного цвета.

(+ 3 5)
(× 5 6)
(×(+ 3 5) 9) ; 8×9

Если решать на скиме комбинированные выражения, то сначала нужно пройтись по примеру и разметить порядок действий. Для примера, сейчас разберём длинное выражение и разложим в дерево вычислений.

2 × ( (2+18+13-3) / (7+3-7) ) – В математике
(* 2 (/ (- (+ (+ 2 18) 13) 3) (- (+ 7 3) 7))) – На скиме

Абстракция

Объявление переменных — самое простое средство абстракции. То есть сейчас мы говорим компьютеру: на это слово делай вот это. На переменную с этим именем, ты достаёшь из памяти вот это значение.

У нас недавно был курс по пайтону и мы решили, что СИКП мы будем описывать то на скиме, то на пайтоне.

На скиме
(define pi 3.14159)
(define radius 4)
(define height 8)
(define cylinder_capacity (* radius radius pi height))

На пайтоне
pi = 3.14159
radius = 4
height = 8

cylinder_capacity = radius ** 2 * pi * height

Развиваем абстракцию

Объявление функции — тоже средство абстракции, но оно мощнее объявления переменной, потому что там происходят дополнительные операции. Мы рассказывали о функциях в статье про функции и библиотеки.

Функция работает как маленькая подпрограмма: получает данные на вход, шаманит и выдаёт результат. Чтобы она работала, её нужно объявить, дать имя и задать формальные параметры входных данных. Это переменные для входных данных.

Для примера возьмём квадратный корень с формальным параметром: \(\sqrt n\)
Буква n показывает, что сюда нужно подставлять значения.

Так как это функция, пользоваться ей можно неограниченное число раз

Ещё абстрактней

Функции можно комбинировать, после этого получится функция с большей абстракцией.

# Функция для вычисления квадрата числа  
def square(num):
    return num * num

  # Функция для вычисления суммы квадратов чисел
def sum_square(a, b):
    return square(a) + square(b)

print(sum_square(2, 4))  # => 20

Чтобы понять, как будет работать цепочка вызовов функций, используют подстановочную модель вычислений.

  1. Вызов функции sum_square(2, 4) в строке print(sum_square(2, 4)). Двойка подставляется на место a, четвёрка на место b
  2. Смотрим на функцию: вместо a подставляется 2, вместо b — 4. Получается square(2) + square(4)
  3. Теперь вызывается функция square. Первый вызов с 2, второй с 4. Первый возвращает 4, второй 16
  4. Возвращаемся в тело sum_sqaure, выражение square(a) + square(b) вычисляется в 4 + 16
    Это выражение вычисляется в число 20 и возвращается из функции sum_square

Тут всё линейно и понятно, но обычно интерпретаторы не работают с подстановочной моделью. Для них существуют два порядка вычисления: аппликативный и нормальный.

Аппликативный и нормальный

Аппликативный — пробегает по всему коду и вычисляет всё, что попалось ему на пути, если это и не нужно по ходу программы.

Нормальный — интерпретатор не будет вычислять операнды пока они не понадобятся.

В МИТе придумали тест для интерпретатора. После его выполнения становится понятно с каким порядком вычислений работает интерпретатор.

def p():
    p()


def test(x, y):
    if x == 0:
        return 0
    return y

test(0, p())

Суть проверки в том, что при аппликативном порядке вычисления интерпретатор уйдёт в бесконечную рекурсию, потому что сначала будет вычислять аргументы, а второй аргумент — функция которая вызывает сама себя.

Интерпретатор остановил функцию потому что она ушла в слишком глубокую рекурсию

Некоторые интерпретаторы работают с нормальным порядком. Например интерпретатор Хаскеля, код для проверки будет выглядеть так

-- Объявляем функцию с бесконечной рекурсией
p = p
-- Объявляем функцию для проверки порядка вычисления
test x y = if x == 0 then 0 else y

-- Вызываем функцию проверки
main = print( test 0 p )

При запуске код вернёт ноль, а не упадёт от бесконечной рекурсии.

Нормальный порядок ещё называют ленивыми вычислениями
 5   1 ч   sicp

Архитектура. Блок питания

Этой статьёй про БП мы закрываем архитектуру и начнём проходить СИКП. Это курс и книга преподавателей Массачусетского технологического института про программирование, железо, математику, абстракции и как это всё взаимодействует друг с другом.

Блок питания

В обыкновенных розетках живёт переменный ток с напряжением до 220 вольт. «Переменный» потому что напряжение тока постоянно меняется, плюс и минус в розетке тоже постоянно меняются местами.
Для компьютера это вредно, потому что скачки напряжения могут спалить материнку или вообще всё железо.

Чтобы нормализовать и сдерживать напряжение, есть блок питания или же по-технически: вторичный источник электроэнергии. Вторичный, потому что он преобразовывает переменный 220 вольтовый ток в постоянный, с более меньшим напряжением.

t — время, i — сила тока, v — напряжение
Картинка с сайта Сам электрик

Упрощённо, алгоритм преобразования такой

  1. На входе фильтруются помехи сети.
  2. Ток выпрямляется и теряет напряжение, этим занимается диодный мост. Из моста выходит постоянный пульсирующий ток, это значит, что небольшие скачки ещё есть.
  3. Ток пропускается через фильтры, чтобы полностью выпрямиться. Самый простой фильтр — конденсатор. Чтобы конденсатор отдавал выпрямленный ток, ему нужно медленно заряжаться и разряжаться, так умеют только конденсаторы с большой ёмкостью.

После преобразования, ток расходится по компьютеру. Оперативка, порты и кнопки включения-перезагрузки питаются от материнской платы, остальные подключаются напрямую через пины. Чем больше напряжения надо передавать, тем шире получается пин.

  • 3.3 вольт — материнка, оперативка, usb порты и кнопки на корпусе. Кнопки включения работают всегда.
  • 5 вольт — жёсткие диски и дополнительные платы, которые подключаются через PSI. Например дополнительная звуковая или сетевая карта.
  • 12 вольт — процессор и видеокарта.

Запуск компьютера

Нажимаем на кнопку питания, ток пошёл будить биос → начинается проверка железа, в видеокарте проснулся свой биос и проверяет её → если всё нормально, биос отдаёт управление процессору, он выгружает ОСку в оперативку → управление получает ОС, выставляются системные настройки и появляется рабочий стол.

Если биос запищал, то нужно посмотреть на чипе версию и гуглить таблицу сигналов. Обычно проблемы бывают с оперативкой, диском или видеокартой. Отключение-подключение и танцы с бубном иногда помогают, но лучше нести в ремонт.

Архитектура. Виды памяти

В компьютерах работа идет с данными. Одни данные используются прямо сейчас, какие-то потребуются через месяц. Чтобы отделять востребованные данные от ненужных, существует три основных типа памяти:

Кэш процессора — чуть-чуть памяти для активных вычислений недалеко от процессора.
Оперативная память — планки по 4, 8, 16 или 32 Гб для хранения всего, что сейчас используется.
Постоянная память — жёсткие диски, ССДшники, флешки. Там хранятся все фотки, игры и приложения. Когда они потребуются, их выгружают в оперативку.

КЭШ

Чтобы процессор быстро вычислял нужные данные, нужно быстро давать ему исходные. Для этого у ядер расставляют блоки памяти и обозначают их Level 1, L2, L3.

Самый первый — самый маленький и быстрый. L1 разделён на два блока: один для следующей команды конвейера, другой для данных под эту команду. Такое разделение команд и данных называют Гарвардской архитектурой.

Чтобы процессор понимал, что ему дальше делать, нужно давать ему следующую команду: делай это с вот этим. Команды и данные для обработки лежат в L1.

С большой кэш-памятью легче вычислять глубокую рекурсию

Распределением данных по памяти занимается контроллер, он тоже в процессоре. Он анализирует входной поток и отправляет в L1 самые востребованные данные.
Например, нам нужно посмотреть все степени двойки до десятого разряда. Контроллер отправляет число 2 в L1, потому что оно используется везде. В L2, он отправит следующее число для возведения, а в L3 будут лежать остальные числа до десятки.

Оперативка

Это тоже активная память, но в ней лежат фоновые процессы. Пока компьютер включен, в оперативке лежит ОСка, драйвера и пользовательские программы.

Вся программа не поместится в кэш, поэтому ненужный сейчас кусок программы откладывается в оперативку. Когда подойдёт очередь, этот кусок загружается в L3.
Если этот кусок больше объема оперативки, то компьютер начинает тупить, лагать или вообще отрубается.
Такое происходит из-за переполнения памяти: данные для вычислений выталкивают ОСку и нажатия с клавиатуры или мышки создают очередь, или вообще не доходят до ядер.

Оперативка хранит данные только пока компьютер активен. Это потому что оперативная память зависит от постоянной энергии — пока компьютер включен, у оперативки есть ток и она работает. Когда компьютер выключается и тока больше нет, ячейки не подпитываются и разряжаются.

Постоянная память

Это жёсткие диски, ССДшники и флешки. Тут хранится всё: ОСка, программы, драйвера и другие файлы.

Эта память отличается от оперативки способом сохранения заряда. В жёстких дисках это ячейки на магнитных блинчиках из которых и состоит ХДД.
ССДшники и флешки используют специальные защёлки, которые запирают ячейку с зарядом, чтобы он не вышел или наоборот не вошёл.

И вот какой момент: на оперативку данные переносятся с жесткого диска, но оттуда не удаляются. Например, вы работаете в фотошопе. Делаете что-то и он крашится, но не удаляется с компьютера, потому что исходный и рабочий код лежит на ХДД. Кликаете по иконке и он снова загружается в оперативку.

Результаты от ядра возвращаются сразу в нужное место: оперативку, жёсткий диск или какой-то уровень кэша
Иконки с сайта flaticon
Ранее Ctrl + ↓