Re[20]: Откуда такая неизбывная приверженность к константам?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 26.10.24 10:23
Оценка:
Здравствуйте, netch80, Вы писали:

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


Я задал вопрос: "Зачем нужны непременно накопительные? Как часто в них возникает потребность?". Вы не ответили.

N>Авторы считают, что отсутствие зависимости по скрытому значению — да, помогает в реализации.


В каком смысле это значение более "скрыто", нежели значения регистров или ячеек памяти? По состояниям отдельных флагов можно выполнить переход, их можно использовать в операциях, можно прочитать явно.

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


Насколько часто при векторных операциях необходимы ветвления по промежуточным результатам? Там, как правило, безусловные, "пакетные" алгоритмы.

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


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


Во флагах состояния, вестимо. Пусть и не все, хотелось бы больше.

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


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


Если сейчас навскидку скачать любой бинарник и дизассемблировать его — уверены, что действий со знаковыми величинами, при которых штатно возникает переполнение, найдем примерно столько же, сколько и для беззнаковых?

N>где говорят про экономию ресурсов


Экономия на флагах состояния на фоне сложности любого процессора даже 30-40-летней давности — это фикция, тех ресурсов там совершенно ничтожное количество, исчисляемое единицами логических элементов.

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


Тоже непонятно, где здесь может быть "резкое облегчение". Параллельное выполнение даже простых арифметических операций требует наличия нескольких полноценных АЛУ, а флаги состояния из такого АЛУ выходят либо сами по себе, либо путем добавления единиц логических элементов. Некоторое упрощение получить можно, "резкое" — тупо неоткуда.

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


В последнее время явно видна тенденция сращивания функций процессора и компилятора. Если существующие архитектуры еще предполагали написание программы человеком на ассемблере, то новые уже предполагают только машинную генерацию кода. В таких условиях разумно целиком оптимизировать связку "компилятор+процессор" — возможно, в ней флаги состояния действительно получаются избыточными.

Но и x86, и ARM проектировались во времена, когда написание кода человеком на ассемблере использовалось достаточно широко.

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


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


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

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


N>Кажется, единственный вариант, при котором это возможно, это арифметика "по модулю". Назвать такое "очень часто" — это слишком сильная натяжка.


Например, там, где нуль/ненуль нужно преобразовать в 0/1 или 0/-1, компиляторы вовсю используют комбинации из neg, sbb, inc и and. А счетчики с переполнением часто используются для отслеживания небольших временнЫх интервалов в алгоритмах реального времени.

N>мы знаем, что "нормальных, запланированных" ситуаций с переполнениями почти нет


Хорошо Вам, что "вы знаете". Я вот их использую регулярно, и столь же регулярно вижу в коде, который делает компилятор (те же преобразования int в bool). А вот операций с заведомо знаковыми величинами, при которых знаковое же переполнение было бы штатной ситуацией, и не требовало специальных действий, я с ходу даже не припомню, как и в случае деления на нуль.

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


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


Где можно найти примеров, в которых это "наплевательство" требуется обставлять ловушками?

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


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


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

N>Ситуацию незамеченного деления на 0 за весь свой опыт я видел только одну


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

N>случаи проблем из-за непойманного переполнения при остальных трёх арифметических операциях — уже десятки.


Этих тоже хватало. Но, если б каждое такое переполнение порождало исключение, было бы еще хуже.

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


Это было бы полезно во всех без исключения языках, но не безусловно, а при возможности независимого управления каждым видом проверок.

N>Ну вот вы почему-то постановили, что константы разрядности в виде 32 и 64 они оправданны, а остальные — нет.


Это не "мы постановили", это непосредственно вытекает из физических, железных характеристик архитектуры. А числа вроде 2 Гб для границы АП, или 480 Мб для бессбойной загрузки Win95, ниоткуда не вытекают, а возникают произвольно.

N>жалобы при переходе на S/360, что 32-битный float был заметно хуже 36-битного по свойствам.


Вроде неудивительно. Чем не устраивал 64-битный?

N>Надо было таки оставить разрядности типа 36 и 72?


Они и так оставались доступными через 64- и 128-разрядные. Или Вы о хранении чисел в памяти?

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


Почему при границе в 2 Гб "сплошной перекачки" нет, а при смещении на те же 3 Гб вдруг потребовалась?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.