Экзотические архитектуры, о которых заботятся комитеты по стандартам

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

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

  • CHAR_BIT != 8
  • signed это не дополнение к двум (я слышал, у Java были проблемы с этим).
  • Плавающая точка не соответствует IEEE 754 (Правка: я имел в виду "не в двоичном кодировании IEEE 754").

Причина, по которой я спрашиваю, состоит в том, что я часто объясняю людям, что хорошо, что C++ не требует никаких других низкоуровневых аспектов, таких как типы фиксированного размера. Это хорошо, потому что, в отличие от "других языков", он делает ваш код переносимым при правильном использовании (Edit: потому что он может быть перенесен на большее количество архитектур, не требуя эмуляции низкоуровневых аспектов машины, таких как, например, арифметика двух дополнений в архитектуре знак + величина), Но мне плохо, что я сам не могу указать на какую-то конкретную архитектуру.

Таким образом, вопрос заключается в следующем: какие архитектуры обладают вышеуказанными свойствами?

uint*_tс не являются обязательными.

7 ответов

Решение

Взгляни на этот

Серверы Unisys ClearPath Dorado

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

Ключевые моменты:

  • 36-битные слова
  • CHAR_BIT == 9
  • свое дополнение
  • 72-битная не-IEEE с плавающей точкой
  • отдельное адресное пространство для кода и данных
  • слово-имя
  • нет выделенного указателя стека

Не знаю, предлагают ли они компилятор C++, но могли бы.


И теперь появилась ссылка на недавний выпуск их руководства по Си:

Справочное руководство по программированию компилятора Unisys C

Раздел 4.5 содержит таблицу типов данных с 9, 18, 36 и 72 битами.

размер и диапазон типов данных в компиляторе USC C

Ни одно из ваших предположений не относится к мэйнфреймам. Для начала, я не знаю мэйнфрейма, который использует IEEE 754: IBM использует базовую 16 с плавающей запятой, а оба мейнфрейма Unisys используют базовую 8. Машины Unisys немного особенные во многих других отношениях: Бо упомянул 2200 архитектура, но архитектура MPS еще более странная: 48-битные слова с тегами. (Является ли слово указателем или нет, зависит от бита в слове.) И числовые представления составлены таким образом, что нет реального различия между плавающей точкой и целочисленной арифметикой: с плавающей точкой - основание 8; он не требует нормализации и, в отличие от любой другой плавающей запятой, которую я видел, ставит десятичную дробь справа от мантиссы, а не слева, и использует знаменательную величину для показателя степени (в дополнение к мантиссе). С результатами, что интегральное значение с плавающей запятой имеет (или может иметь) точно такое же битовое представление, что и целое число со знаком. И нет никаких арифметических инструкций с плавающей запятой: если показатели двух значений равны 0, инструкция выполняет интегральную арифметику, в противном случае она выполняет арифметику с плавающей запятой. (Продолжение философии тегирования в архитектуре.) Что означает, что пока int может занимать 48 бит, 8 из них должны быть 0, иначе значение не будет рассматриваться как целое число.

Я нашел эту ссылку со списком некоторых систем, где CHAR_BIT != 8, Они включают

некоторые TI DSP имеют CHAR_BIT == 16

Чип BlueCore-5 (Bluetooth-чип от Cambridge Silicon Radio), который имеет CHAR_BIT == 16,

И, конечно же, возникает вопрос о переполнении стека: на каких платформах есть что-то кроме 8-битных символов

Что касается систем, не являющихся дополнениями к двум, есть интересное чтение на модерируемом comp.lang.C++. Подводя итог: есть платформы, имеющие свое дополнение или знак и представление величины.

Полное соответствие IEEE 754 редко встречается в реализациях с плавающей запятой. И ослабление спецификации в этом отношении позволяет много оптимизаций.

Например, поддержка subnorm отличается между x87 и SSE.

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

Или на x86 строгое соответствие IEEE может потребовать установки определенных флагов или дополнительных передач между регистрами с плавающей запятой и обычной памятью, чтобы заставить его использовать указанный тип с плавающей запятой вместо своих внутренних 80-битных операций с плавающей запятой.

А некоторые платформы вообще не имеют аппаратного обеспечения и поэтому должны эмулировать их в программном обеспечении. А некоторые требования IEEE 754 могут быть дорогостоящими для реализации в программном обеспечении. В частности, могут быть проблемы с правилами округления.

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

Я уверен, что системы VAX все еще используются. Они не поддерживают IEEE с плавающей точкой; они используют свои собственные форматы. Alpha поддерживает форматы с плавающей точкой VAX и IEEE.

Векторные машины Cray, такие как T90, также имеют свой собственный формат с плавающей запятой, хотя в более новых системах Cray используется IEEE. (T90, который я использовал, был выведен из эксплуатации несколько лет назад; я не знаю, находятся ли еще в активном использовании.)

T90 также имел / имеет некоторые интересные представления для указателей и целых чисел. Собственный адрес может указывать только на 64-битное слово. Компиляторы C и C++ имели CHAR_BIT==8 (необходимо, потому что он запускал Unicos, разновидность Unix и должен был взаимодействовать с другими системами), но собственный адрес мог указывать только на 64-битное слово. Все операции на уровне байтов были синтезированы компилятором, и void* или же char* хранится смещение байта в старших 3 битах слова. И я думаю, что у некоторых целочисленных типов были биты заполнения.

Мэйнфреймы IBM являются еще одним примером.

С другой стороны, эти конкретные системы не обязательно должны исключать изменения в языковом стандарте. Cray не проявил особого интереса к обновлению своего компилятора C до C99; предположительно то же самое применимо к компилятору C++. Возможно, было бы разумно ужесточить требования к размещенным реализациям, таким как требование CHAR_BIT==8, с плавающей запятой формата IEEE, если не полная семантика, и дополнение 2 без дополнительных битов для целых чисел со знаком. Старые системы могли продолжать поддерживать более ранние языковые стандарты (C90 не умер, когда вышел C99), и требования могли быть более свободными для автономных реализаций (встроенных систем), таких как DSP.

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

CHAR_BITS

Согласно исходному коду gcc:

CHAR_BIT является 16 биты для 1750a, архитектуры dsp16xx.
CHAR_BIT является 24 биты для архитектуры dsp56k.
CHAR_BIT является 32 биты для архитектуры c4x.

Вы можете легко найти больше, выполнив:

find $GCC_SOURCE_TREE -type f | xargs grep "#define CHAR_TYPE_SIZE"

или же

find $GCC_SOURCE_TREE -type f | xargs grep "#define BITS_PER_UNIT"

если CHAR_TYPE_SIZE правильно определен.

Соответствие IEEE 754

Если целевая архитектура не поддерживает инструкции с плавающей запятой, gcc может генерировать программный резерв, который по умолчанию не соответствует стандарту. Более чем, специальные опции (например, -funsafe-math-optimizations Ведьма также отключает сохранение знака для нулей).

До недавнего времени двоичное представление IEEE 754 было необычным для графических процессоров, см. Паранойя с плавающей запятой для графических процессоров.

РЕДАКТИРОВАТЬ: вопрос был поднят в комментариях, относится ли с плавающей запятой GPU к обычному компьютерному программированию, не связанному с графикой. Да, черт возьми! Самые высокопроизводительные вычисления, производимые сегодня, выполняются на графических процессорах; список включает AI, интеллектуальный анализ данных, нейронные сети, физическое моделирование, прогноз погоды и многое другое. Одна из ссылок в комментариях показывает почему: преимущество графических процессоров с плавающей запятой на порядок.

Я хотел бы добавить еще одну вещь, которая более актуальна для вопроса OP: что делали люди 10-15 лет назад, когда плавающая точка GPU не была IEEE и когда не было API, такого как OpenCL или CUDA для программирования GPU? Хотите верьте, хотите нет, но первые пионеры вычислений на GPU смогли программировать GPU без API для этого! Я встретил одного из них в моей компании. Вот что он сделал: он кодировал данные, необходимые для вычисления, в виде изображения с пикселями, представляющими значения, над которыми он работал, затем использовал OpenGL для выполнения необходимых операций (таких как "размытие по Гауссу", чтобы представить свертку с нормальным распределением). и т. д.) и декодировал полученное изображение обратно в массив результатов. И это все еще было быстрее, чем при использовании процессора!

Именно это побудило NVidia наконец-то сделать свои двоичные данные внутренними, совместимыми с IEEE и представить API, ориентированный на вычисления, а не на манипуляции с изображениями.

Другие вопросы по тегам