Сколько операций в секунду выполняет python
Перейти к содержимому

Сколько операций в секунду выполняет python

  • автор:

Сколько операций в секунду выполняет python

Cipesta. → The Hidden Impact of CP

Le_Gusto → Thoughts on Round 928 (Div. 4)

macaquedev → Cheating

tiger2005 → Introduction to CPLib — Modern C++ Library for Test Data in CP

mesanu → Codeforces Round 928 (Div. 4) Editorial

Некропост

awoo → Разбор Educational Codeforces Round 70

Sergio86 → Идея решения?

L_Wave → Calculating Riordan Array T(n,k) In O(1) Time

FairyWinx → Codeforces Round #926 (Div. 2) Разбор.

optimize_ofast → My tutorial of «Codeforces Round 927 (Div. 3) A. Thorns and Coins»

wasif1607 → Issue in question A. Lucky Numbers (1808A)

Imtiaz.axi → Long long division.

Vlad_-_null_vampir_best_ → как вам регион по математике?

pashka → Codeforces Round 927 (Div. 3)

secret_name → Is 26 year old late to start CP?

pvtr → Invitation to Alkhwarizm and Starters 122 (Rated till 6-Stars) — 21st February

Некропост

saar2119 → unordered_map vs map in C++ — Complexity Analysis

satyam343 → think-cell Round 1 Editorial

JiaY19 → Rated winner of last round cheated

flamestorm → Codeforces Round 928 (Div. 4)

Vladosiya → Codeforces Round #925 (Div. 3) Разбор

Wasif_Shahzad → Desperate need of help and motivation

G eothermal → I’m Geothermal. AMA!

E legia → How to composite (some) polynomials faster?

BucketPotato → Bay Area Programming Contest 2024

Блог пользователя IlyaCk

О быстродействии Python на олимпиадных проверялках

Автор IlyaCk, история, 4 года назад ,

Заранее прошу прощения, если вопрос быстродействия Python на олимпиадных проверялках где-то уже обсуждался достаточно подробно и относительно недавно; в таком случае, прошу указать места таких обсуждений.

Сразу уточню, что вопрос меня интересует не столько в применении к CF, сколько в разрезах «как правильно настраивать ту копию ejudge, которую я со-админю» и «что делать мне как тренеру, когда есть ученики, которые лучше всего знают Python (и непонятно, стОит ли заставлять/убеждать их выучить C++), которых надо хоть как-то подготовить к вряд ли победному, но хоть не слишком провальному выступлению на некоем (скажем, областном) туре, проводимом на централизованном (не моём) сервере».

По моим наблюдениям, В_СРЕДНЕМ Python оказывается медленнее C++ в 1,2—3 раза, и это относительно терпимо, если ставить time limit в 3—5 раз выше времени авторского решения.

Однако, ИНОГДА (в частности, в задачах, где очень-очень много используется операция %, называемая также mod) Python оказывается медленнее C++ в добрых 10—20 раз. Увеличивать TL аж настолько я не_хочу, даже когда имею такую административную (техническую) возможность. (Или, может, дело не в mod. Если кто-то (значительно более, чем я, шарящий) захочет помочь, начиная с выяснения первопричины — дам права на своей копии ejudge; judge set — вообще без проблем, более глубокие — смотря по обстоятельствам.)

Настолько резкие проседания на конкретных задачах — они вообще лечатся на стороне сервера? Если да, то как? (вроде есть какой-то специальный Python? Кажется, pypy? А он нормально взаимодействует с ejudge? есть какие-то особенности, которые надо изучить перед тем, как его ставить?) И принято ли их лечить на именно тех серверах, которые используются на украинских областных (в централизованном варианте) и финальных этапах? (Не_окажутся ли усилия по нивелированию этой проблемы на нашем сервере жесточайшей медвежьей услугой тем участникам, которые потом будут писать на другом сервере?)

Теги

python, производительность, ejudge

Комментарии (10)

4 года назад , # |

← Rev. 3 → Проголосовать: нравится +27 Проголосовать: не нравится

TL;DR Конкретно для спортивного программирования CPython (стандартный интерпретатот Патона) медленный, PyPy в несколько раз быстрее CPython, но оба всё еще проигрывают C++.

Почему CPython «так плох»?

CPython — это интерпретатор, что значит, что при каждом запуске программы ему приходится токенизировать исходный код, потом строить AST и т.д. — помимо непосредственно выполнения программы. Уже из-за одного этого факта получаем время старта предельно простой программы на Python примерно на уровне 20мс — не очень много, но не прям «незаметно» (особенно на фоне TL в, скажем, 100мс). Как только мы подключаем какой-то модуль — скажем, import itertools — незамедлительно получим увеличение времени старта на 10-15мс. Это не касается модулей, написаных на Си ( math , к примеру) — их подключение влечёт увеличение времени выполнения в худшем случае на пару милисекунд.

Кроме того, с точки зрения интерпретатора, любая переменная (даже примитив — число или булево значение) является объектом. Даже функция! А для объекта приходится хранить и ссылку на тип, и ссылку на непосредственно данные, и много-много прочего. Целое число «0» занимает 24 байт в CPython, целое «1» — уже 28 (как и любое другое натуральное число до 2**30 — 1 ). Очевидно, что это немыслемое расточительство, поэтому в CPython хранится таблица с использованными значениями целых чисел — что значит, что если у вас недавно уже была где-то «77» в качестве результата чего-либо, то новая «77» будет ссылкой на тот же объект. Получается, что памяти на «старые» числа мы используем поменьше (ну, как указатель 32/64-битный указатель), но жертвуем при этом быстродействием — нам ведь для каждого нового числа придётся искать в таблице «а не было ли у нас уже такого числа». Реализация, само собой, отличается от «просто таблицы» — но это не существенно. Важно, что это спортивному программисту мало помагает.

Очевидно, что, работая с объектами, нам еще и приходится мириться с дополнительными расходами на работу с ними — к примеру, посчитать 1 + 2 — значит вызвать метод объекта для суммирования с другим объектом. А поскольку оба имеют тип int, то мы получим еще и дополнительные проверки «а длинное ли это число?», «а при суммировании не получится ли длинное число?» — спасибо нативной длинной арифметике 🙂

Можно приводить еще очень много примеров особенностей — от генерации range(n) списка из n чисел (UPD: касается Py2) до необходимости проверки существования оператора [] при каждом обращении к list — что особенно больно при наличии чего-то вроде двумерного списка.

Каким образом решает проблему PyPy?

Всё достаточно просто. Во-первых, PyPy не интерпретирует программу — он её, фактически, компилирует на лету (JIT). Из-за этого время старта у PyPy еще больше, чем у CPython. Лично у меня на ПК время запуска достаточно простой программы составляет примерно 150мс, а подключая тот же itertools — так и вовсе 210мс.

Однако, эта «100-милисекундная слабость» компенсируется действительно возросшим в разы быстродействием в обычных для спортивного программирования операциях. К примеру, $$$\sum_^ (1 + 1/i)$$$ считается 20 секунд на CPython и «всего» 1.2с на PyPy. А вот, скажем, $$$\sum_^(gcd(i, \lfloor \frac \rfloor ))$$$ уже не настолько радует — 255мс PyPy против 474мс (но тут у PyPy половина времени ушла реально на запуск).

Если что, код вот:


n = int(input()) n = 10**n res = 0 def gcd(a, b): while a: a, b = b%a, a return b for i in range(1, n): res += gcd(i, n//i) print(res)
Что там с делением по модулю

Есть подозрение, что программа использовала деление по модулю в контексте «вывести остаток от деления ответа на 10^9 + 7». Если так, то тут у C++ явное преимущество, и вот почему. Прежде всего, по моему скромному опыту, операция умножения в несколько раз дешевле операции деления/взятия по модулю. Кроме того, просто посмотрите, как gcc оптимизирует деление по модулю при флаге компиляции -О2 — там нет никакого деления, только умножение! А если вместо 1’000’000’009 у нас вдруг степень двойки — то компилятор и вовсе оставляет всего лишь один «AND». Пайтон такого не умеет — у него, увы, умножение — всегда умножение (а никак не битовый сдвиг), а деление — всегда деление.

У С++ (как и у любого компилируемого языка) в спортивном программировании есть огромная фора — время компиляции никак не учитывается в оценивании (кроме того, что оно не должно превосходить условных 20 секунд — но это уже целая вечность!). Та оптимизация, которую я привёл — лишь одна из многих, которые компилятор способен сделать еще до запуска программы. Выкидывать вызовы функции, разворачивать циклы и многое другое — этого не сделаешь на лету за 100мс при интерпретации программы, как бы не хотелось.

По поводу медвежьей услуги. Я скажу очевидное: тут очень тонкий вопрос. На UOI существование решения на Python не гарантируется, это с одной стороны. С другой — заставлять переходить «питонистов» на C++ перед олимпиадой, принуждая набивать шишки на новом языке и потенциально создавать вероятность провала на олимпиаде из-за плохого знания тонкостей языка (а у плюсов их, очевидно, хватает) — тоже не очень бы хотелось.

Производительность C++ vs. Java vs. PHP vs. Python. Тест «в лоб»

/update/ Статья обновлена по результатам обсуждения. Поправлен код Python (около 40% ускорения), написан код на Perl и Ruby (но меня терзают смутные сомнения, что с ruby я что-то сделал неправитьно), поправлен код на Java (на моей машине корректнее тестировать int, а не long. к тому же int в Java эквивалентен long в C++).

Вопрос производительности (скорости работы) различных языков часто всплывает в комментариях, на форумах, часто необоснованные :). Встречаются статьи, в которых авторы приводят примеры, где выигрывает реализация на том или ином языке.

После прочтения очередной статьи мне захотелось самому разобраться «здесь и сейчас». Сначала захотелось сравнить Java и C++ (не верил я, что в вычислительных тестах ява может догнать и обогнать cpp). 10 минут и простой код на C++ и яве готов: простой цикл и математические операции. После написания теста подумал и перевёл их на php и python. Позже добавился код на perl и ruby.

Итак, пару слов о тесте:
Алгоритм синтетический, долгий цикл (двухуровневый) и в нём вычисление математического выражения. Таким образом оценивается вычислительная производительность самого языка (интерпретатора или скомпилированного кода), никаких привязок к качеству реализации тех или иных библиотек, никаких внешних сервисов, никаких системозависимых операций (диск, сеть, графика).

1) Мне нравится ява и я честно предполагал, что результаты будут лучше. Обновлено: long в 64-х битных системах работает значительно быстрее. При работе с int в 32-х битных системах Java значительно ускоряется (на моей машине быстрее, чем C++, видимо, JVM оптимизирует исполнение по умолчанию)
2) Я догадывался, что php будет медленней C++ и Java, но не думал, что он окажется быстрее Perl.
3) Предполагал, что Python будет сопоставим с PHP, но ошибся. Видимо, стандартная поставка PHP лучше оптимизирует исполнение кода.
4) Я совсем не знаком с Ruby, код взят из одного из комментариев. Причём использован код 1, так как у меня он работает быстрее чем код 2. Возможно, это также связано с тем, что у меня 32bit-система.
5) Я достаточно уважительно отношусь к различным языкам программирования, эта статья ни одним из углов не нацелена на разжигание холиваров. Каждый язык имеет свою нишу и своих поклонников.

Тесты запускались по 5 раз минимум, чтобы избежать случайных всплесков. Запускались из консоли и как «nice -n -9», то есть с максимальным на данный момент приоритетом в системе.

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

Диаграмма (обновленная):

Старый вариант здесь
На диаграмме слолбец с Ruby частично прозрачен по причине того, что на моей машине скрипт Ruby исполнялся неприлично долго, в то время как в комментарии указано, что скрипт исполняется в 4 раза быстрее скрипта на Python — я в замешательстве.
Столбец с Python прозрачен, так как при включении psyco скрипт ускоряется более чем в 10 раз. Проверил на своей машине. Но это, с моей точки зрения, хак, не отражающий собственную производительность языка.
Столбец с PERL, как могут заметить старожилы, теперь идёт вровень с Python 2.6. Причиной этому послужила смена кода с C-подобного синтаксиса на использование range. Дополнительную производительность (около 12%) можно получить использовав директиву «use integer;», но это, по-моему, тоже хак.

В виде таблицы (тоже обновлённой):

Язык Java Java -server C++ C++, -O2 PHP Python 2.6 Python 3.1 Perl 5.8 Ruby 1.8 Ruby 1.9(?)
Время исполнения, сек 5,3 2,8 8,5 2,6 62 91 145 91 207 ~30
Производительность, % 160 303 100 327 14 9 6 9 4.11 28

Время исполнения — на P4-1.8Ггц.
Производительность — относительно производительности базового кода на C++.

Добавлен столбец с запуском Java-кода с ключём «-server». После перехода с «long» на «int» (повторюсь, int в java такой же как и long в c++ на 32bit-arch) он начал давать прирост в производительности почти вдвое.
Столбец с Ruby 1.9 на моём железе не тестировался, результат перенесён через сравнение с производительностью Python’а на той же машине.

И, чтобы не быть голословным, тестовый код.

Java, Test01.java (int в Java то же что и long в C++):

package ru.dchekmarev.test.performance;
public class Test01 public static void main(String[] args) // long start = System.currentTimeMillis();
int r = 0;
for ( int i = 0; i < 10000; i++) for ( int j = 0; j < 10000; j++) r = (r + (i * j) % 100) % 47;
>
>
System.out.println( «answer: » + r);
// закомментировано, т.к. замеры делаются из командной строки
// System.out.println(«run time (millis): » + (System.currentTimeMillis() — start));
>
>

Python, Test01.py (вынос кода в функцию ускоряет работу кода почти вдвое, отдельная же инициализация range() на моей машине даёт порядка 5% производительности):

def test():
r = 0
for i in range(0, 10000):
for j in range(0, 10000):
r = (r + (i * j) % 100) % 47
test()
print ( «answer: » , r)

Perl, Test01.pl (обновлено, с range работает на 25% быстрее против c-подобного синтаксиса for):

$r = 0;
# старый вариант, C-подобный синтаксис
# for ($i = 0; $i < 10000; $i++) # for ($j = 0; $j < 10000; $j++) <
for my $i (0..9999) for my $j (0..9999) $r = ($r + ($i * $j) % 100) % 47;
>
>
print «answer: $r\n»;

Вот здесь приведён красивый пример на Perl, но, мне кажется, такой вариант уже слишком специфичен.

r = 0
for i in 0..10_000 do
for j in 0..10_000 do
r = ( r + ( i * j ) % 100) % 47
end
end
puts «answer: #»

Вот здесь в комментариях обсуждают решение на erlang.

Как видите, ничего сложного: два цикла и математическое выражение. Вычислительная задача в чистом виде.

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

Ещё раз повторюсь: каждый язык имеет свою нишу, своих поклонников и свои задачи, с решением которых он справляется лучше других.

PS: а вообще, нет смысла загоняться и меряться чем бы то ни было, производительность самого языка важна для достаточно узкого круга задач, т.к. в общем случае, системы, библиотеки и прочая обвязка нынче несоизмеримо тяжелее самой вычислительной задачи.

Сравнение скорости Python и C++

Автор этой статьи делает сравнение скорости выполнения одной и той же программы на Python и C++. С++ естественно быстрее, но насколько?

Прим. ред. Это перевод статьи Назера Тамими. Мнение редакции может не совпадать с мнением автора оригинала.

Есть миллион причин любить Python (особенно если вы дата-сайентист). Но насколько Python отличается от низкоуровневых языков, таких как Си и C++? В этой статье я собираюсь сделать сравнение скорости Python и C++, на очень простом примере.

Мы будем генерировать все возможные k-меры ДНК, для фиксированного
значения “k”. О том, что такое k-меры, я расскажу чуть позже. Этот пример был выбран потому, что многие задачи обработки и анализа данных связанные с геномом, считаются ресурсоёмкими. Поэтому, многие дата-сайентисты связанные с биоинформатикой, интересуются C++ (в дополнение к Python).

Важное замечание: цель этой статьи не сравнить скорость С++ и Python когда они наиболее эффективны. Код предлагаемых программ можно сделать гораздо более быстрым. Цель этой статьи — сравнить два языка, используя один и тот же алгоритм и код.

Введение в k-меры ДНК

ДНК — это длинная цепь нуклеотидов. Эти нуклеотиды могут быть четырёх типов: A, C, G и T. У вида Homo Sapiens около 3 миллиардов пар нуклеотидов. Вот небольшой кусок ДНК человека:

ACTAGGGATCATGAAGATAATGTTGGTGTTTGTATGGTTTTCAGACAATT 

Чтобы получить из него k-меры нужно разбить строку на части:

ACTA, CTAG, TAGG, AGGG, GGGA и т. д. 

Эти последовательности из четырех символов называются k-меры длина которых равна четырём (4-меры).

Задача

Мы сгенерируем всё возможные 13-меры. Математически — это перестановка с проблемой замены. Следовательно мы имеем 4 в степени 13 (67 108 864) вариантов 13-меров.

Сравнение скорости Python и С++

Мы будем использовать один и тот же алгоритм для двух языков. Код на обоих языках намеренно написан аналогично и просто. Я не использовал сложные структуры данных и сторонние библиотеки. Вот код программы на Python:

def convert(c): if (c == 'A'): return 'C' if (c == 'C'): return 'G' if (c == 'G'): return 'T' if (c == 'T'): return 'A' print("Start") opt = "ACGT" s = "" s_last = "" len_str = 13 for i in range(len_str): s += opt[0] for i in range(len_str): s_last += opt[-1] pos = 0 counter = 1 while (s != s_last): counter += 1 # Следующая строка выводит результаты # print(s) change_next = True for i in range(len_str): if (change_next): if (s[i] == opt[-1]): s = s[:i] + convert(s[i]) + s[i+1:] change_next = True else: s = s[:i] + convert(s[i]) + s[i+1:] break # Следующая строка выводит результаты # print(s) print("Number of generated k-mers: <>".format(counter)) print("Finish!") 

Выполнение этой программы займет 61.23 секунды. За это время сгенерируется 67 миллионов 13-меров. Чтобы не увеличивать время работы программы я закомментировал код выводящий результаты (25 и 37 строки). Если вы захотите запустить этот код и отобразить результаты, имейте ввиду, что это будет очень долго. Чтобы остановить выполнение программы вы можете нажать на клавиатуре CTRL+С.

Теперь посмотрим тот же алгоритм на языке C++:

#include #include using namespace std; char convert(char c) < if (c == 'A') return 'C'; if (c == 'C') return 'G'; if (c == 'G') return 'T'; if (c == 'T') return 'A'; return ' '; >int main() < cout for (int i=0; i int pos = 0; int counter = 1; while (s != s_last) < counter ++; Следующая строка выводит результаты: cout else < s[i] = convert(s[i]); break; >> > > Следующая строка выводит результаты: "Number of generated k-mers: " counter

Сравнение скорости Python и C++ 1

В таблице указаны результаты тестов для 13, 14, и 15-меров.

После компиляции, этот код выполнится за 2.42 секунды. Получается что Python требуется в 25 раз больше времени на эту задачу. Я повторил эксперимент с 14 и 15-мерами (это можно указать на 12 строке в Python и на 22 в C++) Теперь мы видим, что производительность этих двух языков, при выполнении одной и той же задачи, значительно различается.

Я повторюсь, обе программы далеки от идеала и могут быть значительно опимизированы. Например, мы не использовали параллельные вычисления на CPU или GPU. Но для таких задач это необходимо. Также мы не храним результаты. Хотя управление памятью в Python и C++ значительно влияет на производительность.

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

Как работает компьютер?

В современном мире мы постоянно имеем дело с компьютерами. Чаще всего под этим словом мы подразумеваем ноутбук или настольный ПК, стоящий у нас дома за рабочим столом, но на самом деле понятие компьютер гораздо шире.

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

Компьютер — электронное устройство, которое работает по-разному, в зависимости от заложенной в него программы. Программу можно менять, не изменяя само устройство.

Электронные устройства, которые всегда работают одинакового, мы будем называть аналоговыми.

Например, следующие устройства являются компьютерами:

  • мобильные телефоны;
  • bluetooth-наушники;
  • веб-камеры;
  • сим-карты;
  • цифровой телевизор;
  • умные часы.

А вот несколько примеров аналоговых устройств:

  • электрический чайник;
  • проводная колонка;
  • аналоговый синтезатор;
  • проводные наушники;
  • пленочный фотоаппарат (он, кстати, может быть и не электронным).

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

Выходит, управляем компьютерами — управляем миром! ��

Что внутри коробки?

Несмотря на то, что современные компьютеры внешне очень непохожи, внутри почти все они устроены одинакого.

Внутри каждого современного компьютера есть:

  • вычислительное устройство — процессор;
  • кратковременная память;
  • долговременная память;
  • вспомогательные устройства, датчики, устройства ввода и вывода.

Процессор

Сердце компьютера — это его центральное вычислительное устройство — процессор (CPU). Именно процессор является исполнителем команд, которые мы даем компьютеру.

Современные процессоры различаются тактовой частотой и числом ядер.

Тактовая частота — число примитивных операций (или тактов), которое процессор выполняет за секунду. Например, процессор с частотой 3 мегагерца может выполнять три миллиона операций в секунду. Примитивных, потому что для выполнения некоторых операций (умножения, например) требуется несколько тактов.

Внутри современных процессоров на самом деле часто помещается несколько вычислительных устройств, которые работают параллельно — ядер. Например, шестиядерный процессор может выполнять шесть действий одновременно.

Но, кстати говоря, добавление дополнительных ядер не всегда ускоряет компьютер, все зависит от решаемой задачи. Представь, что ты чистишь картошку: если позвать на помощь еще 10 друзей, скорее всего вместе вы управитесь гораздо быстрее. А вот если ты пишешь сочинение по русскому языку, поручить разные части разным людям будет уже сложнее.

Иначе говоря, некоторые задачи можно распараллелить, а некоторые нет.

Память

В современных персональных компьютерах обычно находится сразу два вида памяти — кратковременная и долговременная.

Кратковременная, или оперативная, память — это относительно небольшая по объему, энергозависимая (при отключении питания данные теряются) память, которая работает очень быстро.

В персональных компьютерах такая память обозначается, как RAM — random access memory, память, в которой можно за несколько тактов обратиться к любой ячейке (поэтому он и быстрая).

Средний объем оперативной памяти в современном компьютере — 8 гигабайт.

Долговременная память в современных компьютерах — это SSD (Solid State Drive) или HDD (жесткий диск). Эти устройства не теряют данные при отключении питания, хранят большой объем данных, но работают медленее оперативной памяти.

Типичный размер современного жесткого диска — 1 терабайт.

Зачем нужная разная память? Представь ученика на уроке. Сейчас идет урок математики, и на парте лежит открытый учебник по алгебре. Все остальные учебники — по русскому и другим предметам лежат в рюкзаке. Все учебники сразу на парту не поместятся, а каждые пять минут доставать учебник из рюкзака долго.

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

Как устроены процессор и память?

Итак, процессор и память — это два основных компонента любого компьютера. Но как они устроены внутри?

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

Если мы обозначим «заряженный» бит единицей, а «разряженный» — нулем, получится, что оперативная память состоит из маленьких ячеек, в каждой из которых может лежать 0 или 1.

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

Отсюда возникает понятие бинарного кода (кода из 1 и 0).

Выходит, что все программы и данные в компьютере — это последовательности из единиц и нулей. Кажется, что этого должно быть мало, но с другой стороны, четырех аминокислот природе хватает чтобы описать все разнообразие жизни на земле (речь про ДНК). А значит и для компьютера как-нибудь получится.

А вот как с помощью двух символов описать все что угодно, мы рассмотрим далее.

Бинарный код

Как общаться с устройством, которое понимает только цифры? Как положить в оперативную память текст, если нам доступны только нули и единицы? Нам на помощь приходит двоичная система счисления.

Используя двоичную систему счисления можно записать любое число в виде последовательности единиц и нулей, например число 123 (в привычной нам десятичной системе) — это 1111011 в двоичной системе счисления.

Как сохранить в памяти число? Перевести его в двоичную систему счисления!

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

Как передать команду процессору? Договориться, что у каждой команды будет номер, и перевести номер команды в двоичную систему счисления. Последовательность 1 и 0 передать процессору в виде напряжений на разных контактах.

Иными словами и данные (числа, буквы, графика. ) и программы (указания, что нужно сделать с данными) внутри компьютера представляются в виде бинарного кода — больших последовательностей из 1 и 0 .

Перевод в двоичную систему

В обычной жизни мы привыкли использовать десятичную систему счисления. В ней нам доступны десять цифр: 0, 1, 2 . 8, 9. Если девяти нам уже не достаточно, мы используем перенос через разряд — дописываем слева единицу и продолжаем считать.

Например, как ты знаешь из начальной школы, 9 + 1 = 10 , т.е. когда цифры закончились, мы дописали единицу левее и начали считать с нуля. По аналогии, 10 + 1 = 11 , 19 + 1 = 20 , а 99 + 1 = 100 .

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

Но принцип сложения точно такой же: 0 + 1 = 1 , 1 + 1 = 10 (т.к. цифры два нет, мы переносим через разряд), 10 + 1 = 11 , 11 + 1 = 100 .

Есть несколько алгоритмов, как можно просто переводить числа из одной системы счисления в другую, о них можно прочитать здесь: wikiHow.

Единицы измерения информации

Итак, оперативная память состоит из маленьких ячеек, битов, который могут содержать или 1 или 0.

Исходя из предыдущих размышлений про системы счисления, чтобы сохранить в память число больше чем 2, нам понадобится сразу несколько битов.

  • Группу из 8 бит называют байтом. Один байт может принимать значения от 00000000 до 11111111 , а значит хранить число от 0 до 255 .
  • 1024 (два в десятой степени) байта называются килобайтом. Обратите внимание, что в отличие от физики, приставка кило означает не 1000, а 1024 (на чем, кстати, любят спекулировать производители жестких дисков).
  • 1024 килобайта — это 1 мегабайт.
  • 1024 мегабайта — это 1 гигабайт.
  • 1024 гигабайта — это 1 терабайт.

Кстати, интернет провайдеры часто указывают скорость подключения не в килобайтах, а в килобитах (1024 бита), поэтому скорость и оказывается в 8 раз меньше ожидаемой. ��

Пробуем писать машинный код

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

По ссылке https://calc.geekclass.ru/ находится «пещерный калькулятор» — модель компьютера, который умеет совершать основные математические операции, но понимает только бинарный код. И сам калькулятор, и систему команд придумал я (не благодари!), она описана в инструкции по ссылке.

Пропробуй на нем что-нибудь посчитать, например, (45 — 13) * 15 / 24.

Сперва, конечно, можно мозг сломать, но в итоге — не так уж и страшно. Именно так и писали код программисты в во второй половине 20го века.

Как создать программу?

Итак, процессор понимает только фиксированное количество команд, которые записываются в виде последовательности 1 и 0 . Они специфичны для конкретного семейства процессоров (или архитектуры) и называются машинными кодами. Например, у моего «пещерного калькулятора» одна система команд, а у процессоров Intel — совсем другая.

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

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

Код на ассемблере для Intel, который выводит на экран надпись «Привет, мир!», выглядит вот так:

SECTION .text org 0x100 mov ah, 0x9 mov dx, hello int 0x21 mov ax, 0x4c00 int 0x21 SECTION .data hello: db "Hello, world!", 0xD, 0xA, '$'

Согласитесь, мало что понятно. А главное — это долго и неудобно писать.

Как мы еще ни раз увидим в процессе работы, двигатель всей ИТ индустрии — это лень. Если кто-то придумает, как сделать задачу проще и быстрее, все в дальнейшем будут делать именно так.

Чтобы решить проблему сложности ассемблера, были придуманы языки высокого уровня. Идея в том, чтобы писать программы на языке, который будет более понятен человеку, а затем переводить их в ассемблер/машинный код с помощью программы «переводчика» — транслятора. Сегодня 99.999% всех программ пишется именно так, а ассемблер тебе пригодится разве что в разработке железа или анализе программ без исходного кода (это про хакеров). ��️‍♂️

Например, на одном из таких языков, питоне, тот же самый код записывается так:

print("Hello, world!")

Согласись, это куда короче, понятнее и удобнее!

Более того такой подход решает вопрос привязки к конкретному процессору: одну и туже программу высокого уровня можно перевести (или транслировать) в ассемблер разных процессоров с помощью разных переводчиков. Один раз пишем — много раз используем. Именно поэтому программы на питоне можно запускать как на windows, так и на маке или линуксе (процессоры там могут быть и одинаковые, но у каждой операционной системы тоже есть свои особенности).

Далее на этом курсе мы познакомимся с одним из самых популярных языков высокого уровня — python 3.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *