sab123: (face)
[personal profile] sab123
Навеяло: как известно, плавающие числа нельзя сравнивать на точное равенство. Вместо того их надо сравнивать на различие в пределах погрешности. Спрашивается:

(1) Какого хрена в процессорах нет инструкции сравнения на равенство с погрешностью? которая брала бы три операнда - два числа и размер погрешности. Кстати, ту же фигню можно использовать и для сравнения на больше-меньше, чтобы разница в пределах погрешности считалась равенством.

(2) Какого хрена в языках высокого уровня нет операции сравнения на равенство с погрешностью? Погрешность можно было бы даже задавать один раз в начале блока, и потом обычно равенство делалось бы этой операцией.
Page 1 of 3 << [1] [2] [3] >>

Date: 2014-12-22 06:42 pm (UTC)
spamsink: (Default)
From: [personal profile] spamsink
(1) В процессорах нет инструкции сравнения на равенство с погрешностью ровно потому же, почему нет, скажем, инструкции сложения трех чисел: потому что и то, и другое легко реализуется программно, и экономия времени не будет оправдывать расходы на дополнительные транзисторы, тем более что городить дополнительный data path для третьего операнда гораздо дороже, чем реализовать какую-нибудь команду с двумя операндами.

(2) Это называется "подпрограмма", и существует во всех языках высокого уровня.

Date: 2014-12-22 07:01 pm (UTC)
From: [identity profile] orleanz.livejournal.com
Жестоко слово сие

Date: 2014-12-22 07:19 pm (UTC)
From: [identity profile] juan-gandhi.livejournal.com
Очень справедливо.

Date: 2014-12-22 07:45 pm (UTC)
spamsink: (Default)
From: [personal profile] spamsink
Но справедливо. Желание иметь инструкцию с тремя операндами свидетельствует о принципиальном непонимании процессорной архитектуры. Абсолютная погрешность реализуется вычитанием и взятием абсолютной величины - это две очень дешевые операции.

Операция сравнения на равенство с погрешностью на уровне языка - ненужный "синтаксический сахар", и в языках с мощностью, сравнимой с С++, реализуется самостоятельно с тем же успехом.

Date: 2014-12-22 07:46 pm (UTC)
spamsink: (Default)
From: [personal profile] spamsink
Ты серьезно, что ли?

Date: 2014-12-22 07:48 pm (UTC)
From: [identity profile] juan-gandhi.livejournal.com
Да. Если на самом деле равенство не определено, то зачем это расширение алгебры?

Date: 2014-12-22 07:50 pm (UTC)
From: [identity profile] sab123.livejournal.com
(1) Делать программно - сложно и медленно. Это как минимум 3 инструкции - вычесть, abs, сравнить. Ну, и если очень хотеть, то ничего не мешает установить третий операнд отдельной командой в регистр состояния, откуда его потом и брать (он скорее всего не будет меняться для многих сравнений). А что касается дополнительных транзисторов, то они нынче фигня, проблема не в том. чтобы наштамповать транзисторов, а в том, чтобы из них извлечь пользу.

(2) Подпрограммой - неудобно. Не говоря уже о том, как неудобно ее увязывать со значением, задаваемым в начале блока. Ну и вообще, в любом случае не подпрограмма, а хотя бы макро.

Date: 2014-12-22 07:56 pm (UTC)
spamsink: (Default)
From: [personal profile] spamsink
Вот и я говорю, что незачем. Ты на что хотел ответить "справедливо" - на пост или на мой комментарий?

Date: 2014-12-22 08:04 pm (UTC)
From: [identity profile] sab123.livejournal.com
Вот сравнение на точное равенство можно выбросить за бессмыссленностью.

Date: 2014-12-22 08:06 pm (UTC)
spamsink: (Default)
From: [personal profile] spamsink
1. Чем больше у процессора состояния, тем сложнее переключать контексты.

2. Польза из транзисторов извлекается путем их использования в как можно большем числе команд. Редко используемые команды с уникальной функциональностью - dead weight.

3. Делать программно ровно так же быстро, как и аппаратно. Если процессор в принципе умеет делать операцию, описываемую как "вычесть, abs, сравнить" быстрее, чем за 3 такта, то он это сможет сделать и путем instruction fusion. А если не умеет, то выгоды на копеечной экономии размера кода практически никакой.

Пишешь класс со статическим стеком значений точности и переопределенной операцией сравнения (== подпрограммой). Значение, задаваемое в начале блока, кладется на верхушку стека, в конце блока - убирается оттуда. И все дела.

Date: 2014-12-22 08:08 pm (UTC)
spamsink: (Default)
From: [personal profile] spamsink
Не собачье дело языка решать, как и для чего я использую числа с плавающей точкой.

Date: 2014-12-22 08:28 pm (UTC)
From: [identity profile] sab123.livejournal.com
При установке погрешности в 0, операции делаются эквивалентными. И это именно что дело языка - предоставить удобный набор операций, отражающих концепции предметной области.

Если каждый текст про программирование с плавающей точкой начинается с "их нельзя сравнивать", то почему оно не отражено в языках? А потом люди < a href="http://vit-r.livejournal.com/782219.html">предъявляют претензии. Кстати, в SQL и вовсе нет определяемых пользователем подпрограмм.

Date: 2014-12-22 08:35 pm (UTC)
spamsink: (Default)
From: [personal profile] spamsink
Эквивалентными, но более дорогими, чем сейчас. Зачем нам эта головная боль?

набор операций, отражающих концепции предметной области

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

Edited Date: 2014-12-22 08:37 pm (UTC)

Date: 2014-12-22 08:41 pm (UTC)
From: [identity profile] enternet.livejournal.com
Сергей, вы поразительный человек. Оптимист. Даже на вашем юзерпике изображен человек, который пытается задушиться биноклем, но улыбается при этом.

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

Извините )

Date: 2014-12-22 08:41 pm (UTC)
From: [identity profile] sab123.livejournal.com
1. А вот для этого у нас есть компилятор. Можно не сохранять контекст, а просто пусть следит за тем, чтобы заново загрузить контекст между вызовом функции и следующим использованием.

2. Ну так это не редко используемые, а часто используемые команды. Вот точное сравнение - это будут редко используемые, если писать правильно, а не срезать углы.

3. Процессору необязательно выполнять как "вычесть, abs, сравнить", а можно например параллельно выполнить два вычитания и два сравнения. Про instruction fusion - это совершенно та же фигня, по сути одна инструкция, записывающаяся магической последовательностью кодов. Кстати, наверное интересная и разновидность - это брать точность не как константу, а как зависящую от порядка участвующих значений.

4. Это коряво, медленно, и непонятно как реализовать если блоком является класс или файл. Кстати, обрати внимание на то, что генерить правильную магическую последовательность инструкций для instruction fusion без поддержки компилятора не получится. Ну ладно, положим, Си - это не язык, заточенный под плавающую математику, в нем можно обойтись ручными костылями и даже плюнуть на эффективность. Но в языках-то, заточенных под математику, типа Фортрана или SQL - почему нет?
Edited Date: 2014-12-22 08:42 pm (UTC)

Date: 2014-12-22 08:52 pm (UTC)
From: [identity profile] sab123.livejournal.com
> Эквивалентными, но более дорогими, чем сейчас. Зачем нам эта головная боль?

Ничего не мешает в компиляторе генерить разный код для случая погрешности, равной 0 и не равной 0.

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

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

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

Date: 2014-12-22 08:57 pm (UTC)
From: [identity profile] sab123.livejournal.com
Если я правильно помню (я не настоящий сварщик по преданию греху с плавающими числами, а только по верхушкам нахватался), в общем случае никакие нельзя. Но, конечно, от переводов из десятичных в двоичные и назад добавляется пикантности.

Date: 2014-12-22 09:03 pm (UTC)
spamsink: (Default)
From: [personal profile] spamsink
1. Речь о переключении контекстов между независимым процессами.

2. Как часто, вообще, используется в реальных алгоритмах сравнение плавающих чисел на (приближенное) равенство? Конкретные значения есть?
В итеративных алгоритмах epsilon - параметр для условия завершения итераций, поэтому записывать эту единственную проверку и удобнее, и математичнее как abs(x-y) < epsilon.

3. Instruction reordering разберется, точно так же, как разбирается со сложением четырех чисел. И операция должна быть коммутативной, иначе вообще бардак будет.

4. В фортране есть встроенные функции epsilon и tiny, позволяющие более гибко выразить, что хочется. За SQL я не отвечаю. :)

Date: 2014-12-22 09:08 pm (UTC)
spamsink: (Default)
From: [personal profile] spamsink
Ничего не мешает в компиляторе генерить разный код для случая погрешности, равной 0 и не равной 0.

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

вообще плавающая точка не нужна

Не "нужна", но "полезна на практике", поскольку дает выигрыш во времени выполнения программ на порядки по сравнению с soft-float. Много ли корысти будет от команды сравнения с погрешностью?

в языках с виртуальной машиной тоже не очень-то получится написать такое расширение, не вылезая за пределы виртуальной машины

На уровне виртуальной машины можно извращаться как угодно, это на хардвер не влияет.

Date: 2014-12-22 09:21 pm (UTC)
From: [identity profile] juan-gandhi.livejournal.com
На пост. Заявление правильное; правильного ответа как-то нету зато.

Date: 2014-12-22 09:24 pm (UTC)
From: [identity profile] sab123.livejournal.com
> Речь о переключении контекстов между независимым процессами.
Ну так использовать фиксированный регистр (какой-нибудь %f0 или в этом роде), он сохранится вместе с остальными регистрами плавающей точки. И так же полно инструкций, которые требуют, чтобы один из операндов был в фиксированном регистре.

> Как часто, вообще, используется в реальных алгоритмах сравнение плавающих чисел на (приближенное) равенство? Конкретные значения есть?

Мои лично использования сводятся к аналогу SQL, и там оно нужно просто постоянно. Если делать правильно.

> В итеративных алгоритмах epsilon - параметр для условия завершения итераций, поэтому записывать эту единственную проверку и удобнее, и математичнее как abs(x-y) < epsilon.

А в терминах равенства с погрешностью можно было бы записывать еще проще: x != y.

> В фортране есть встроенные функции epsilon и tiny, позволяющие более гибко выразить, что хочется.

Почитал. Это на самом деле не функции, а константы типа как в limits.h. С которыми надо все равно вручную сравнивать.

Date: 2014-12-22 09:30 pm (UTC)
spamsink: (Default)
From: [personal profile] spamsink
Ну так дай его. :)

Date: 2014-12-22 09:35 pm (UTC)
spamsink: (Default)
From: [personal profile] spamsink
Неортогональные ISAs ужасны.

Зачем в SQL плавающая точка? Значения каких типов предметной области нужно хранить в этом формате?

можно было бы записывать еще проще: x != y

Предварительно выполнив где-то далеко в коде setprecision(epsilon). Текстуальная локальность ухудшается, а с ней и читаемость-поддерживаемость кода.

С которыми надо все равно вручную сравнивать.

Так о том и речь, что иногда надо с epsilon, иногда - c tiny. Чем переключать режимы туда-сюда, проще написать сравнение явно.

Date: 2014-12-22 09:35 pm (UTC)
From: [identity profile] sab123.livejournal.com
> Не "нужна", но "полезна на практике", поскольку дает выигрыш во времени выполнения программ на порядки по сравнению с soft-float. Много ли корысти будет от команды сравнения с погрешностью?

Затрудняюсь сказать, оно будет определяться тем, насколько часто произодится сравнение, то есть насколько короткие тела циклов. А сколько корысти нужно для того, чтобы добавить команду? Чего-нибудь типа 1% хватит? 5%?

Ну хорошо, положим фиг с ней, с командой. Но вот заметим, что в языках-то плавающая точка все равно присутствовала в качестве родного типа, даже если реализовалась как soft-float. А ведь могли бы сказать, что ну нафиг, пусть она будет в библиотеке.

> На уровне виртуальной машины можно извращаться как угодно, это на хардвер не влияет.

Фиг с ним с хардвером (хотя надо сказать, что хардверщики обладают специальным талантом создавать кривизну, чтобы их хардвер было трудно использовать в софтвере). Я про то, что если делать библиотеку в терминах виртуальной машины, то на каждое использование наложится во-первых оверхед интерпретации отдельных команд над плавающими числами, во-вторых вызовов функций в виртуальной машине. А вот если добавить специальную инструкцию к системе команд виртуальной машины, то весь этот оверхед пропадет.

Date: 2014-12-22 09:36 pm (UTC)
From: [identity profile] juan-gandhi.livejournal.com
Его вообще нету. У меня тоже.
Все сложно. Тут есть хитрая комонада, и традиция такова, что мы не вполне понимаем, что вообще за зверь такой, вещественные числа.
Page 1 of 3 << [1] [2] [3] >>

January 2026

S M T W T F S
     12 3
45 6 7 8 9 10
11 12 13 14 151617
1819202122 23 24
25 26 2728293031

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 29th, 2026 08:16 pm
Powered by Dreamwidth Studios