Екзотична архітектура, про яку піклуються комітети зі стандартів


154

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

Я знаю, що 40 років тому будь-який комп'ютер мав свою унікальну специфікацію. Однак я не знаю жодної архітектури, яка використовується сьогодні, де:

  • CHAR_BIT != 8
  • signed не є доповненням двох (я чув, що у Java були проблеми з цим).
  • Плаваюча точка не відповідає IEEE 754 (Редагувати: я мав на увазі "не в двійковому кодуванні IEEE 754").

Причина, про яку я питаю, полягає в тому, що я часто пояснюю людям, що добре, що C ++ не надає жодних інших аспектів низького рівня, таких як типи фіксованого розміру . Це добре, тому що на відміну від "інших мов", він робить ваш код переносним при правильному використанні (Редагувати: тому, що він може бути перенесений до більшої кількості архітектур, не вимагаючи емуляції аспектів низького рівня машини, як, наприклад, арифметика двох доповнення на архітектурі знака + величини) . Але мені погано, що я сам не можу вказати на якусь конкретну архітектуру.

Тож питання: які архітектури виявляють вищевказані властивості?

uint*_ts необов’язкові.


9
Я думаю, ти маєш це назад. Якби C ++ мав призначити, скажімо, доповнення для подвійних цілих чисел, це зробило б код C ++ більш портативним не менше. Питання, чому комітет зі стандартів C ++ не надає цього завдання, - це вже інше питання. Тим більше, що, незважаючи на те, що ви говорите, не було б неможливо написати компілятор для нестандартної архітектури, ви завжди зможете імітувати 8-бітні символи чи доповнення арифметики, навіть коли ваша платформа не підтримує це безпосередньо.
Джон

8
@john: тоді це було б недоцільно, тому нестандартний відповідний компілятор генерував би швидший код, ніж відповідний. І я досі не бачу, як це зробить ваш код більш портативним.
Яків Галка

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

4
@john: Я сумніваюся, що "полегшення для авторів-компіляторів" є пріоритетним завданням при створенні стандарту C ++ (якби вони виконували жахливу роботу, якби це було, оскільки C ++ є однією з найважчих мов для розбору та інших аспектів мова також не дуже спрощує і авторів-компіляторів). Продуктивність, широка підтримка платформи та зворотна сумісність є досить важливими. І всі ці три страждали б, якщо обмеження, яке ви згадуєте, буде додане до стандарту.
Сандер Де Дікер

5
Йдеться не про компілятор, а про апаратне забезпечення. C ++ залишає деякі речі не визначеними, щоб дозволити безпосередньо використовувати апаратні функції. Ваші телефонні програми все одно не працюватимуть на мейнфреймі, тому немає портативності, однак відповідний код.
Бо Персон

Відповіді:


114

Погляньте на цей

Сервери Unisys ClearPath Dorado

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

Ключові моменти:

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

Не знаю, чи пропонують вони компілятор C ++, але вони могли .


А тепер з'явилося посилання на останнє видання їх посібника С:

Посібник із програмування для компілятора Unisys C

У розділі 4.5 є таблиця типів даних з 9, 18, 36 та 72 бітами.

розмір та діапазон типів даних у USC компіляторі


13
Я думаю, що void * має бути пекельним для використання в цій архітектурі.
luiscubal

13
@ybungalobill - Я вважаю , що char*і void*повинні бути однакового розміру, і досить великий , щоб тримати будь-який інший покажчик. Решта - до реалізації.
Бо Персон

22
@ybungalobill: На старих компіляторах Win16 регулярні вказівники знаходилися поблизу покажчиків і містили лише 16-бітове зміщення sizeof(int*) == 2, але, але далеко вказівники також мали 16-бітний селектор, так sizeof(void*) == 4.
Адам Розенфілд

10
Існує або використовувався он-лайн посібник для їх компілятора C ++. Варто також зазначити, що це лише одна з архітектур мейнфреймів Unisys: інша - це архітектура з 48-бітовою підписаною величиною (для якої я знайшла лише керівництво C, а не C ++). Щодо решти: я не думаю, що цеsizeof(int*) != sizeof(char*) тут: обидва - це 36 біт. Але селектор байтів у значенні " char*біт" знаходиться у високому порядку, і в ньому ігнорується int*. (Однак я використовував інші машини, де `sizeof (char *)> sizeof (int *).)
Джеймс Канзе

16
@Adam Rosenfield У 16-бітових компіляторах MS / DOS у вас були різні "режими", а покажчики даних не завжди були такого ж розміру, як покажчики функцій. Але принаймні на тих, які я використовував, усі покажчики даних (у тому числі void*) завжди мали однаковий розмір. (Звичайно, ви не змогли перетворити покажчик функції на void*, оскільки він void*може бути меншим. Але згідно зі стандартом, ви не можете цього зробити і сьогодні.)
James Kanze

51

Жодне з ваших припущень не стосується мейнфреймів. Для початку я не знаю мейнфрейму, який використовує IEEE 754: IBM використовує плаваючу точку бази 16, а обидві основні рамки Unisys використовують базу 8. Машини Unisys дещо особливі у багатьох інших аспектах: Бо згадав 2200 архітектура, але MPS-архітектура навіть незнайома: 48 бітових тегів. (Чи є слово вказівником чи ні, залежить від біта у слові.) А числові подання побудовані так, щоб не було реального розмежування між плаваючою точкою та інтегральною арифметикою: плаваюча точка є базовою 8; вона не вимагає нормалізації, і на відміну від усіх інших плаваючої точки, яку я бачив, вона ставить десятковий правий від мантіси, а не лівий, і використовує підписану величину для експонента (крім мантіси). За результатами, що інтегральне значення з плаваючою комою має (або може мати) точно таке ж бітове подання, як ціле число підписаної величини. І немає арифметичних вказівок з плаваючою комою: якщо експоненти двох значень обидва 0, інструкція робить інтегральною арифметикою, інакше вона має арифметику з плаваючою комою. (Продовження філософії мітки в архітектурі.) Що означає, що покиint може займати 48 біт, з них 8 має бути 0, або значення не розглядатиметься як ціле число.


4
Основні рамки IBM (z / Architecture) підтримують плаваючу точку IEE754.
Микита Немкін


6
@Nikita - Вони зараз . Спочатку це був (дорогий) додаток для підтримки Java.
Бо Персон


42

Повна відповідність IEEE 754 зустрічається рідко в реалізаціях з плаваючою комою. І ослаблення специфікації в цьому плані дозволяє безліч оптимізацій.

Наприклад, підтримка субнорми відрізняється між x87 та SSE.

Оптимізації, такі як злиття множення та додавання, які були окремими у вихідному коді, теж трохи змінюють результати, але приємна оптимізація для деяких архітектур.

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

А деякі платформи взагалі не мають апаратних плаваючих механізмів, і тому їх потрібно емулювати в програмному забезпеченні. І деякі вимоги IEEE 754 можуть бути дорогими для впровадження в програмному забезпеченні. Зокрема, можуть бути проблемою правила округлення.

Мій висновок полягає в тому, що вам не потрібні екзотичні архітектури, щоб потрапити в ситуації, якщо ви не завжди хочете гарантувати суворе дотримання IEEE. З цієї причини мало мов програмування гарантували чітке дотримання IEEE.


7
Інший "екзотичний" набір апаратних засобів - це мейнфрейми IBM, де формат з плаваючою комою передує стандарту IEEE. На відміну від Java, C ++ все ще може використовувати наявне обладнання.
Бо Персон

5
IEEE 754 не підтримується повністю графічними процесорами.
керем

3
Відсутність суворого дотримання IEEE 754 викликає занепокоєння для деяких, але я не думаю, що це цілком в обсязі питань, які дійсно хвилюють ОП.
всезнайко

3
@Matthieu Оскільки це також позначено "C", я повинен зазначити аналізатор C, який може повідомити вам всі значення, які може взяти ваша програма з плаваючою комою, з 80 бітами регістрів з плаваючою комою, що пролилися на пам'ять за примхою компілятора C. blog.frama-c.com/index.php?post/2011/03/03/cosine-for-real
Паскаль Куок

2
@MatthieuM: Це занадто погано ISO / ANSI не дозволяло варіаційним параметрам визначати мінімальні / максимальні розміри для аргументів з плаваючою комою та цілими числами; якби вони були, 80-бітний long doubleміг би бути корисним і довгоживучим типом, оскільки одна з справжніх проблем з ним полягала в тому, що він погано працює printf. Той факт, що розширений подвійний склад зберігає провідну 1, явно прискорює обчислення в системах, що не належать до ППУ, а також усуває необхідність спеціального поводження з деннормалами в будь-якому контексті, окрім перетворення в / з інших типів. Шкода, що С printfзіпсував усе.
supercat

40

Я знайшов це посилання з переліком деяких систем, де CHAR_BIT != 8. Вони включають

деякі TI DSP є CHAR_BIT == 16

Чип BlueCore-5 (чіп Bluetooth від Cambridge Silicon Radio), який має CHAR_BIT == 16.

І, звичайно, є питання щодо Stack Overflow: Які платформи мають щось інше, ніж 8-бітовий char

Щодо систем, що не доповнюють двох, є цікаве прочитання на модерації comp.lang.c ++ . Узагальнено: є платформи, що мають доповнення або знак та величину.


5
Аналогові пристрої мають 32-розрядний DSP SHARC, а DSP компанії CHAR_BIT=32Texas Instruments від TMS32F28xx CHAR_BIT=16. GCC 3.2 для PDP-10 має CHAR_BIT=9. Я думаю, S / 360 теж може мати не 8 біт.
osgx

1
Я все-таки хотів би приклад архітектури "не два доповнення". Тим більше, що сталося, що CHAR_BITSце частковий дублікат.
Яків Галка

TI DSP мають 16-бітні символи лише тому, що реалізатори обрали його (було б трохи більше роботи, щоб змусити його працювати правильно, але не нерозумно жорсткий IIRC - можливо, це лише деякі "дірки" в скелеті кодена в базовому компіляторі) . Тож це не якась глибока архітектурна причина. Код С працює на абстрактній машині. Якщо у вас є 16-бітні INT, збережіть по два символи в кожній і додайте зчитування-модифікування-записування злиття в оптимізатор видовища (як мінімум). Звичайно, це більше роботи, але просто подивіться, наскільки більше роботи для того, щоб усі мали справу з такими дивними типами в місцях, де вони ніколи не з’являться. Гидота.
Відновіть Моніку

24

Я досить впевнений, що системи VAX досі використовуються. Вони не підтримують IEEE з плаваючою точкою; вони використовують власні формати. Альфа підтримує формати з плаваючою точкою 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's-комплемент без заповнення біт для цілих чисел. Старі системи могли продовжувати підтримувати більш ранні мовні стандарти (C90 не загинув, коли з'явився C99), і вимоги можуть бути слабкішими для самостійно реалізованих реалізацій (вбудованих систем), таких як DSP.

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


6
Хороший момент наприкінці про те, як надто суворі стандарти перешкоджають інноваціям. Коли ми отримаємо квантові (або органічні) комп’ютери з тринаціональними станами, вимоги до арифметики модуля для unsignedінтегральних типів будуть головними болями, тоді як підписана арифметика буде просто чудовою.
Бен Войгт

@BenVoigt Чому ця непідписана арифметика - це біль? Чи не можливі модулі 3 ^ n додавачів на цих комп’ютерах?
phuclv

2
@ LưuVĩnhPhúc: Саме в цьому справа, коли апаратні операції виконуються за модулем 3 ** n, забезпечуючи C ++ типи без підпису, операції яких визначені модулем 2 ** n, буде складно.
Бен Фогт

2
Я знаю про один VAX 11/780, який все ще використовується як хост для перехресного компілятора, орієнтованого на спеціалізовану вбудовану систему з власною архітектурою. Щоб підтримувати саме цей VAX, зберігачі зверталися до музеїв за запчастинами.
Петро

2
@Keith - технічно єдиною перешкодою є проходження процесу надання доказів, які задовольнять нормативні вимоги, оскільки цільова вбудована система - це висока критичність. Однак існує маса нетехнічних перешкод (організаційна політика тощо), які на сьогодні були непереборними. Наразі простіше здійснити набіги на музеї, ніж оновити господаря.
Петро

16

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відьма також вимикає збереження знаків для нулів).


3
прагнуть просто спрямувати ОП на пошук джерела популярного компілятора; це визначення RFTM в даному випадку, тому на першому місці люди повинні виглядати.
підкреслюй_d

9

Бінарне представлення IEEE 754 до недавнього часу було рідкісним явищем у графічних процесорах, див . Параноя GPU з плаваючою точкою .

EDIT: у коментарях було поставлено питання, чи плаваюча точка GPU має відношення до звичайного комп'ютерного програмування, не пов'язаного з графікою. Так, чорт візьми! Найбільш високопродуктивна річ, що обчислюється сьогодні, робиться на графічних процесорах; до списку входять AI, обмін даними, нейронні мережі, фізичні симуляції, прогноз погоди та багато іншого. Одне з посилань у коментарях показує, чому: порядок переваги GPU.

Ще одне, що я хотів би додати, що більше стосується питання про ОП: що люди робили 10-15 років тому, коли плаваючою точкою GPU не був IEEE і коли для програмування графічних процесорів не було API, таких як сьогодні OpenCL або CUDA? Вірите чи ні, першим піонерам обчислювальних процесорів GPU вдалося запрограмувати GPU без API, щоб це зробити ! Я зустрів одного з них у своїй компанії. Ось що він зробив: він закодував дані, необхідні для обчислення у вигляді зображення з пікселями, що представляють значення, над якими він працював, а потім використовував OpenGL для виконання потрібних йому операцій (наприклад, "гауссова розмиття" для подання згортки з нормальним розподілом тощо) і декодував отримане зображення назад у масив результатів. І це все-таки було швидше, ніж використання процесора!

Такі речі спонукали NVidia нарешті зробити свої внутрішні бінарні дані сумісними з IEEE та запровадити API, орієнтований на обчислення, а не маніпулювання зображеннями.


Наскільки відповідні GPU? (а) Ця сторінка здається дуже застарілою. (b) До цього дня ви не можете програмувати графічні процесори на C: оскільки C підтримує такі речі, як рекурсивні функції, яких GPU, наскільки мені відомо, не робить. Тому ви навіть не можете написати компілятор, якщо цього хочете.
Яків Галка

1
@ybungalobill, вивантаження повторюваної роботи на GPU в даний час є кращим методом для широкомасштабних обчислень . Насправді я зараз розробляю його на C ++. На щастя, ми працюємо лише з графічними процесорами NVidia CUDA, які мають сумісне IEEE 754 бінарне представлення плавців.
Майкл

Я не кажу, що GPU не використовуються для обчислень GP. Я сказав, що ви насправді не програмуєте ядра на C, незважаючи на схожість синтаксису. Чи можете ви виконати int f(int n) { return n <= 1 ? 1 : n * f(n-1); }в CUDA? Якщо ні, то GPU не стосуються цього питання (яке запитує про комітети C та C ++).
Яків Галка

6
@ybungalobill: кілька відповідей на це. По-перше, CUDA підтримує C, C ++ та Fortran . Перегляньте те ж посилання, щоб отримати перевагу в грандіозній продуктивності графічних процесорів з 2048 потоками над типовим 8-поточним процесором. По-друге, правда, підтримуються лише підмножини (хоча і великі) з цих мов, включаючи відсутність підтримки відповідної для рекурсії моделі програмування CUDA (званої "динамічний паралелізм") до CUDA 5.0. По-третє, рекурсії зазвичай можуть бути замінені петлями, що так чи інакше необхідно для багатопотокового виконання.
Майкл
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.