Журнал «Компьютерра» №41 от 08 ноября 2005 года, стр. 11

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

ТЕМА НОМЕРА: 64 бита для всех

История знает много разных компьютеров и много разных технологических решений, применявшихся в них. Лампы, транзисторы, ИС, БИС и СБИС; CISC, RISC и VLIW; компьютеры большие и маленькие; процессоры удачные и неудачные. Компьютеры на троичной логике, аналоговые машины, стохастические вычислители и компьютеры с «байтом» из девяти битов - бывало всякое. Однако конечный результат эволюции известен всем - это «тьюринговые» компьютеры с процессором, линейной оперативной памятью и средствами ввода-вывода и накопления информации, основанные на детерминированных вычислениях, двоичной логике и восьмибитных «неделимых» атомах информации - байтах. Но поскольку в один байт много не запишешь, то собственно байтами процессоры оперируют редко (разве что совсем уж простые 8-битные микропроцессоры), используя гораздо более крупные объекты - машинные слова[По традиции, идущей от первого процессора семейства x86 - CPU Intel 8086, который оперировал 16-разрядными числами, словом (word) обычно называют два байта. Потом, когда x86-процессоры получили возможность работать и с 32-разрядными данными, для совместимости со старым программным обеспечением эти 32 бита стали представлять в виде двух 16-битных слов - вот и получилось четырехбайтное двойное слово (double word). Таким образом, четверное слово (quad word) соответствует 64-битным данным (8 байтам) и т. д.]. При этом самые популярные сегодня x86-процессоры прошли почти весь путь усложнения объектов, с которыми они работали, начав с 8 битов (Intel 8008, 8080, 8085), «выбившись в люди» на 16 битах (8086 и 80286), надолго застряв на 32 битах и вот наконец, два года назад, обретя 64-битность. Но что это такое, как оно устроено, как его использовать и что это дает обычному пользователю? Об этом - наш сегодняшний рассказ.

8, 16, 32, 64…

Что вообще такое «разрядность процессора»? Как ни странно, это отнюдь не максимальный размер обрабатываемых данных. Складывать и вычитать 64-битные числа x86-процессоры умеют еще со времен Intel Pentium MMX; более того - даже i486 мог работать не только с 64-битными, но и с 80-битными числами, записанными в формате длинной двойной точности с плавающей запятой (long double). И если уж проводить аналогию дальше, то обрабатываемые инструкциями SSE-наборов операнды (регистры XMM) вообще имеют длину 128 бит. Но поддержка инструкций MMX, x87 и SSE 1/2/3 отнюдь не делает процессор 64-, 80- или 128-битным. Грубо говоря, по возможностям вычислений 64-битный процессор теоретически почти ничем не отличается от 32-битного, но достаточно продвинутого собрата[На самом деле, 32-разрядные процессоры, например, не умеют перемножать целочисленные 64-битные числа и делить 128-битные целые числа на 64-битное число, но это уже детали]. Да, работать с ним не так удобно, но при желании можно. В любом случае, соответствующие данные (long long integer или __int64, в общепринятой терминологии языка C) в программах встречаются нечасто.

Так в чем же дело?

А в том, что и x87, и SSE - расширенные наборы инструкций, работающие со специализированными регистрами процессора. Они никак не затрагивают сердце процессора - его базовый набор инструкций (Instruction Set Architecture, ISA) и базовые регистры общего назначения (General Purpose Registers, GPR), равно как и некоторые «представления» процессора об окружающем его мире. Лирик, наверное, не упустил бы здесь возможности немного пофилософствовать на тему подобных «неощутимых» с первого взгляда, но очень глубоких по своей сути различий, но я не философ, а математик, и потому просто скажу, что на практике главное отличие GPR-регистров от всех остальных в том, что их можно использовать для адресации оперативной памяти. То есть 64-битный процессор - это не тот, который в принципе может работать с 64-битными числами (хотя это он тоже должен уметь делать, выполняя с 64-битными целыми числами все базовые арифметические операции), а тот, который способен этими числами «нумеровать» ячейки памяти.

Чтобы было понятнее, о чем идет речь, поясняю: стандартная модель записи целочисленных чисел позволяет записать в 32-разрядный GPR-регистр процессора архитектуры IA-32 любое целое число от 0 до 232-1. Оперативная память с точки зрения прикладных приложений представляется здесь в виде эдакой длинной ленты из ячеек определенного размера (1 байт в x86), причем все они «пронумерованы» - ячейка 0, ячейка 1 и так далее, вплоть до ячейки 4.294.967.295. Какие-то ячейки могут «отсутствовать» - в этом случае обращение к ним будет вызывать ошибку, однако потенциальная возможность обратиться к этой ячейке существует всегда. А вот у 32-разрядного процессора возможности обратиться к ячейке 4.294.967.295 нет в принципе - просто потому, что он не сможет «дать ей название».

Что это означает на практике? Только то, что ни одна «классическая» 32-битная программа не может использовать больше 4 Гбайт (232/210*210*210) памяти. Поэтому если вы спросите продавца о преимуществах 64-разрядного процессора, то именно эту сакральную фразу о «поддержке большого объема оперативной памяти» (вместе с вопросом «а оно вам надо?») и услышите. Но все-таки не спешите сводить эту возможность к установке в систему четырех двухгигабайтных планок SDRAM. Все далеко не так просто.

64-разрядность и оперативная память

Первая «особенность», о которой часто забывают, рассматривая 64-разрядные процессоры, - это то, что во всех современных компьютерах программы работают не с физической, а с виртуальной оперативной памятью, то есть программная адресация памяти может не совпадать с действительным расположением этой памяти в компьютере. В нашей модели длинной ленты ячеек мы можем нумеровать их в произвольном порядке (0, 6533, 21, 554, 54223563, 2, …). Это очень удобно в многозадачных операционных системах: по-разному пронумеровав ячейки и раздав их разным приложениям (после чего в памяти образуется каша, когда данные разных программ лежат вперемешку), на логическом уровне мы сохраняем линейность и стройность, поскольку каждая программа работает не с этой кашей, а с виртуальным пространством адресов, в которое попадают данные только этой программы, и расположенные именно так, как программе привычно.

Впрочем, перенумерацией дело не ограничивается, поскольку вместе с номерами указываются всяческие атрибуты - «только для чтения», «только для операционной системы» и пр. Вдобавок для некоторых ячеек можно указать, что они в оперативную память «пока не загружены». Встретив такую пометку, CPU генерирует специальную системную ошибку (Page Fault) и обращается за помощью к операционной системе, которая может, к примеру, загрузить данные для этой ячейки с жесткого диска (техника своппинга). Поэтому всегда следует помнить, что «ограничение 4 Гбайт» в первую очередь относится не к физической, а к виртуальной оперативной памяти, доступной процессу. А вот что стоит за этими четырьмя гигабайтами адресного пространства - скромные ли 128 Мбайт памяти SDRAM или кусочек от пары терабайтов дискового массива - неважно: собственно процессор этот «реальный мир» почти ничем не ограничивает.

Но все же - что дает разрядность? Если процессор поддерживает длинные физические адреса (в архитектуре x86 соответствующий режим называется Physical Address Extension, PAE[Если подробнее, то в PAE используется 52-битная адресация, позволяющая адресовать до четырех петабайт данных]), то мы можем поставить на сервер хоть 64 Гбайт оперативной памяти и выделять ее разным приложениям. Условия вроде «не более двух гигов для чипсета такого-то» - это ограничения именно чипсета, не умеющего обслуживать большой объем памяти, а не 32-разрядной системы. Поэтому в серверных приложениях, когда на одном сервере, как правило, запущено несколько десятков одновременно работающих приложений, пресловутый «барьер в 4 Гбайт» практически не ощущается. Но означает ли это, что сегодня 64-разрядный x86 никому не нужен?