Re[19]: Откуда такая неизбывная приверженность к константам?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 26.10.24 05:46
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

N>>Что вы решили назвать тут флагом состояния?

ЕМ>Классический флаг состояния процессора, используемый с незапамятных времен.

Нет такого общего понятия. Есть много разных флагов, каждый со своим поведением.

N>>в знаковой интерпретации это нормально, а в беззнаковой это переполнение. Мы должны детектировать это переполнение?

ЕМ>Если у процессора в ходе выполнения программы возникает любая информация, которая с высокой вероятностью будет полезна этой программе, то да. Именно это и делает тот же x86 с флагами CF/OF, детектируя сразу обе ситуации.

Тему с накопительным поведением вы проигнорировали.

N>>Архитектура типа RISC-V намеренно лишена аналога Flags в x86.

ЕМ>И как, этим она существенно выигрывает у архитектур, где флаги есть?

Авторы считают, что отсутствие зависимости по скрытому значению — да, помогает в реализации. И она не одна такая. Вон MIPS ещё как минимум.

А теперь бинго — у x86 то же самое в векторных операциях... потому что не может быть одного флага результата на 4-8-16 разных операций впараллель

N>>Сложение, вычитание, умножение — они все требуют проверок

ЕМ>Именно так. Реализация этих проверок в топологии/микрокоде процессора всегда дешевле, чем в каждой из выполняемых на нем программ.

Ну и где они в x86?

N>>Мы можем добавлять JO или INTO после команды. Мы можем добавлять JC. Вопрос: почему нет парной к ней INTC?

ЕМ>Потому, что перенос очень часто является следствием нормального выполнения, и как-то специально его обрабатывать не требуется,

Нет здесь такой несимметричности.

N>>Есть один вариант решения: флагов нет, ставьте явные проверки по диапазонам и конкретным значениям, где нужно.

ЕМ>Это откровенно убогий вариант, как и возврат из функции единственного результата, некоторые значения которого резервируются под коды ошибок. Оправдывается только в случае крайней экономии ресурсов.

Ну где говорят про экономию ресурсов, а где про резкое облегчение дизайна за счёт отсутствия единого регистра флагов и за счёт этого лучшую параллельность.

Заметьте, Intel в своём проекте APX намеревается сделать то же самое.

N>>Я бы не против, если б SDIV ставила OF (как бы они ни звались) в случаях деления на 0 или MIN/-1.

ЕМ>Это было бы следуюшим по разумности вариантом при отказе от исключения.

Как раз более разумно, чем исключение

N>>вводить ещё и фолт для одного-единственного случая — точно явный и неуместный перекос.

ЕМ>Почему, если механизм исключений уже поддерживается аппаратурой?
EM> Порождать исключения для арифметических переполнений нет смысла, поскольку они очень часто возникают в совершенно нормальных, запланированных ситуациях.

Кажется, единственный вариант, при котором это возможно, это арифметика "по модулю". Назвать такое "очень часто" — это слишком сильная натяжка. От общего количества разных операций такого минимум и сконцентрированы они в некоторых совершенно конкретных областях: длинная арифметика, операции с кольцевыми счётчиками вроде seqnum в сетевых протоколах. А вот в, не побоюсь, 99% остальных если и кажется, что они есть, то это такие, в которых значение после переполнения проверяется на его выход за пределы ожидаемого множества. Например, в недавней дискуссии о роли беззнаковых — переход 0 -> ~0. А если не проверяется, а переполнение возможно, то код просто некорректен.
Уточню: я имею в виду вариант, когда тип значения обозначен. CF=1 при беззнаковом или OF=1 при знаковом.

EM> А вот в какой нормальной, запланированной ситуации могло бы возникнуть деление на нуль, результат которого можно было бы далее использовать без проверки?


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

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


Ну и почему на это плюют во всяких x86 для трёх операций из четырёх (это ещё и если не считать сдвиги за арифметику со степенью двойки, тогда окажется, что в 7 из 8)?

N>>Неужели не было уже понятно по опыту развития, что в этом нет смысла?

ЕМ>Тогда и в плюсовых исключениях тоже нет смысла. Не в их неправильном использовании, а в механизме, как твковом.

Передёргиваете. Я ясно сказал, что возможность проверки есть и там, где её применяют, проблема детектируется. Может, чуть заморочно.

ЕМ>>>Если же механизм исключений имеется, но решено отказаться от возбуждения исключения

N>>Механизм появляется вместе с более высокими уровнями реализации (в RISC-V). Но его принудительная ориентация на обработку в супервизоре избыточна.
ЕМ>Если команда деления может присутствовать в архитектуре, не поддерживающей обработку исключений, или возбуждение исключения может быть запрещено, то наиболее разумным решением будет использование флага состояния.

Да. Если он есть.

ЕМ>C — не язык "в себе". В C изначально закладывались на то, что исключения, если они есть в архитектуре, поддерживаются средой исполнения.


Ну предположим.

N>>Если где-то вы видите, например, обработчик SIGFPE (в который по POSIX мапится деление на 0, если трапается), то в нём всё равно нельзя без платформенно-специфичных средств вернуться на ту же команду.

ЕМ>Возможность вернуться и повторить — это уже определенная роскошь. Основной является возможность реагировать на нештатную ситуацию без явных проверок.

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

N>>В языках-то оно есть. Возьмите какую-нибудь Ada и там всё будет под полным контролем.

ЕМ>А какой ценой?

Проверка каждого результата при укладке в целевую переменную, на её границы, плюс операций с базовым размером значения (как int и long в C) на переполнения. Не сильно большая цена за реальную безопасность.

N>>Лучше бы вспомнили историю ATA геометрий — она красочнее.

ЕМ>Там были хоть какие-то объективные основания — разрядности шин, регистров, стоимость тогдашних микросхем и т.п.

Все эти "разрядности" и "стоимости" это фактор ровно того же плана: суммарная цена решения.

N>>В общем же случае я думаю, что каждое расширение какого-то реального параметра в 2-3 раза приводит к наступанию на очередной предел.

ЕМ>Это как раз понятно. Непонятно стремление вводить константы вместо переменных, хотя в основе математики лежала противоположная идея.

Ну вот вы почему-то постановили, что константы разрядности в виде 32 и 64 они оправданны, а остальные — нет. А я могу вспомнить жалобы при переходе на S/360, что 32-битный float был заметно хуже 36-битного по свойствам. Последствия этого убрали только в IEEE754, и то по мнению некоторых недостаточно качественно. Надо было таки оставить разрядности типа 36 и 72?

EM>>>выбор константы в 2 Гб тоже был неудачным

N>>Он был 99.99% удачен. Остальных давно ждал 64-битный режим
ЕМ>Тогда выбор одного гигабайта вместо двух был бы "удачным на 99.95%". А выбор 512 Мб — "на 99.9%". А фишка в том, что увеличение этой вероятности до максимальной не стоило бы практически ничего, но в итоге цена получилась вполне ощутимой.

В том и дело, что увеличение выше 2GB реально стоило — мороки программистам и производительности ядру. Сплошная перекачка данных между буферами.

N>>Тогда на всём экономили.

ЕМ>В загрузчиках MBR/VBR — да. В загрузчике Win95 не было ни малейших причин экономить байты и такты.

Я уже ответил, что считаю, что причина в несогласовании между сотрудниками (отделами), а не в намеренной чрезмерной экономии.
The God is real, unless declared integer.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.