19/02/2020

Интересно о размерах (2): модели данных

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

Соотношение разрядности машины и разрядностей типов данных (на самом деле просто отношения разрядностей типов друг к другу) называется моделью данных. И на самом деле модель данных задаётся компилятором, а не разрядностью машины, ровно, как и не операционной системой. То есть, даже на одной ОС, используя разные компиляторы, можно получить разные соотношения (которые мы косвенно рассмотрели в предыдущей статье на примере программы). Моделей данных существует много, но обычно в распространённых связках разрядность машины/ОС/компилятор используется ограниченное количество.

Принятый (сокращённый) формат названия модели данных состоит из перечисления типов, которые относятся к максимальной разрядности и значения самой разрядности.

Типы это (в порядке возрастания): S  короткое целое число (short), I  целое число (int), L  длинное целое число (long), LL  двойное длинное целое число (long long), P  указатель (void *). Разрядность указывается в битах  32, 64, 128.

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

Пример, макрос которого мы использовали в предыдущей статье LP64, означает что компилятором задана следующая модель данных — 64-битными являются типы начиная с L (long), а именно — long и pointer. Указание LL излишне, так как он стоит рядом с указателем, и в таком случае считается равным ему. Если бы он был больше чем указатель, в конце было бы дописано LL128 (LP64LL128). Реальный пример ILP32LL64 (int, long и pointer — 32-битные, long long — 64-битный), эта модель использовалась в Win32 и некоторых UNIX'ах в 90-ые года. Можно задаться вопросом — как машина, разрядностью менее разрядности максимального типа вообще может оперировать такими типами? Верно — на операции с этими типами уходит более одной инструкции (такта), что крайне неэффективно с точки зрения вычислительных мощностей. 

Все типы, определённые до типов, указанных в названии модели считаются 32-битными, за исключением типа short — пока он, начиная с PDP-11 является 16-битным всегда. Это подразумевается, хотя возможна и полная запись: I32LP64 (и даже S16L32P64— эта модель данных и принята в стандартах Open System (UNIX является ОС относящейся к этому стандарту). В конце 90-х годов эта модель была согласована как основная для UNIX-систем совместным решением компаний, в том числе DEC, IBM, Sun Microsystems, HP, Intel, NCR.

Есть и отличный от предыдущих пример. В системах UNICOS (UNIX-подобная ОС для линейки суперкомпьютеров Cray) все типы являются 64-битными, и модель данных на этих машинах используется SILP64. И здесь используется символ S, так как даже short здесь 64-битный.

Ну и чтобы наше описание было полным, укажем какая модель данных была в Win16 и Win64. В Win16 использовалась LP32, что означает — 32-битные long и ponter, а int был 16-битным. А в Win64 используется LLP64, то есть, все типы до long long оставлены 32-битными. Сделано это из-за проблем с совместимостью и переписыванием WinAPI при переходе на 64-разрядные системы.

Для большинства UNIX-разработчиков ещё знакомы 32-разрядные системы, там принята модель данных ILP32, что означает что все типы, кроме short, являются 32-битными. И, собственно, единственным отличием 32-разрядных машин (компиляторов) от 64-битных является то, что pointer и long стал 64-битным. Что я и рассмотрел и доказал как один из методов определения разрядности машины в предыдущей статье. Все остальные типы остаются таких же размерностей, что и на 32-битных системах. Сделано это для совместимости кода. Но здесь стоит быть осторожным. В некоторых 32-битных программах типы int, long и pointer используются как синонимы, полагается, что их разрядности равны. Но так как размеры long и указателя в модели данных LP64 стали 64-битными мы должны помнить, что это изменение может вызвать много проблем при переносе кода с 32-разрядной платформы на 64-битную.
Поиск оптимальной модели данных, при каждом переходе на более высокую разрядность системы, является основополагающим моментом в обеспечении качественного процесса разработки ПО. Можно сказать, что модель данных является инструментом разработчика. Так как влиять мы на неё (модель) не можем, наша задача хорошо в них разбираться.

На этом пока всё.