Design: Нам нужен постоянный контроль режима округления с плавающей запятой

Созданный на 11 окт. 2020  ·  55Комментарии  ·  Источник: WebAssembly/design

У этого есть своя история. Потерпите меня.

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

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

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

Пожалуйста, позвольте нам префикс или иным образом изменить инструкции с плавающей запятой, чтобы указать режим округления. На Intel / AMD вы можете просто оптимизировать префикс, если он такой же, как и раньше (и нет промежуточных целей ветвления). Если префикс никогда не используется, тогда все обратно совместимо с округлением до ближайшего или четного, поэтому контрольное слово никогда не нужно писать; это легко проверить при проверке подлинности кода. Но на nVidia префикс втягивается в битовое поле в инструкции.

Пожалуйста, примените это. Это позволит использовать все больше и больше полезных приложений, чем вы можете себе представить.

Самый полезный комментарий

@penzn Если единственный способ продать это - иметь 4 вида каждой инструкции FP (по одной для каждого режима округления), то я бы согласился с этим.

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

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

Я лично считаю, что это можно превратить в предложение. Что думают все остальные?

Все 55 Комментарий

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

@tlively Достаточно

Чтобы было ясно, есть округление в смысле «округлить существующее число с плавающей запятой до целого числа», а затем округление в смысле «подтолкнуть единицы последнего места (ULP) в соответствии с бесконечно точным результатом».

В первом случае можно обойтись обычными подозреваемыми:

а. Круглый ближайший или четный.
б. Округлите в сторону отрицательной бесконечности.
c. Округлить в сторону положительной бесконечности.
d. Обрезать в сторону нуля (обрезать).

Во втором случае мы можем применить ту же политику округления, но к ULP вместо целой части. Неявно мы, прежде всего, должны знать максимальные границы ошибок для бесконечно правильного результата, потому что, если они слишком велики, ULP все еще не определен. Для арифметических операций это просто и уже сделано прямо на оборудовании. Для операций, которые могут давать иррациональные результаты, сначала необходимо знать границы ошибок на усеченной части (из-за усечения серии). Остается надеяться, что разработчики ЦП все сделали правильно. У меня есть серьезные сомнения по этому поводу, но это может быть правильным для fsqrt , который,

Очевидно, что первый случай может быть выполнен постфактум, потому что нам просто нужно избавиться от дробной части. Но во втором случае все должно происходить в одной инструкции, потому что после завершения инструкции любые лишние биты точности будут забыты. Поэтому, если вам нужны отдельные инструкции, вам понадобятся такие вещи, как «умножить и округлить ULP до отрицательной бесконечности» и «квадратный корень и усечь все после ULP». Хорошая новость заключается в том, что если вы сделаете это таким образом, то он подойдет как перчатка с nVidia, что, вероятно, более актуально в будущем, чем AMD64. Плохая новость заключается в том, что вам придется проявить определенную смекалку, чтобы не касаться контрольного слова слишком часто в последнем. И, кстати, все ваши существующие арифметические инструкции теперь должны быть дополнены суффиксом "округлять до ближайшего или даже".

Я остановлюсь здесь. Мы на одной странице?

Да, философия здесь звучит хорошо. У нас были аналогичные обсуждения в предложении SIMD. Следующая часть - убедиться, что предлагаемые инструкции имеют (разумно) эффективное снижение на соответствующих архитектурах (по крайней мере, x86 / x86-64 / ARM). Однако я не уверен, как nvidia вписывается в картину. WebAssembly обычно не работает на графических процессорах. Также было бы хорошо упомянуть, какие языки или приложения выиграют от наличия этих инструкций, чтобы мотивировать работать над ними.

«WebAssembly обычно не работает на графических процессорах». - Конечно, в 2029 году.

Но позвольте мне предложить потенциально лучшее решение для второго случая. Мне кажется, что единственное практическое применение для округления ULP - это интервальная математика, точка. Таким образом, вы можете сократить количество инструкций и повысить производительность, предоставив встроенную поддержку интервалов. Таким образом, «разделение 64-битных чисел с плавающей запятой» становится «делением 64-битных интервалов с плавающей запятой». Да, есть множество угловых случаев, но, сделав это таким образом, вы решите все эти проблемы раз и навсегда, позволяя языкам более высокого уровня переводить типы интервалов непосредственно в WASM. Я полностью поддерживаю необходимость избегать бессмыслицы с CISC, но интервалы настолько мощны и универсальны, что я думаю, что в этом случае стоит быть немного CISC.

Другая причина для реализации собственных интервалов заключается в том, что языки более высокого уровня, насколько мне известно, не имеют инструкций по манипулированию ULP. Во многих языках это даже ничего не значило, потому что числа с плавающей запятой в любом случае являются неопределенным мусором. Но легко представить себе добавление макросов для поддержки базовых интервальных функций в популярных языках, которые затем фильтруются прямо на уровень WASM. Нет шансов на создание сверхтонких ошибок из-за ошибочных манипуляций с ULP.

Если я помню, ракета Arianne 5 снова взорвалась из-за неточности вычислений с плавающей запятой, которую можно было бы предотвратить с определенными интервалами. И, если не ошибаюсь, безопасность Большого адронного коллайдера была доказана и интервальным анализом. Но дело не только в безопасности. Вычисления могут быть ускорены в геометрической прогрессии, в некоторых случаях с использованием интервалов, просто потому, что более низкая точность часто приемлема, а экономия времени распространяется на многие уровни дерева функций. Это, например, обеспечивает более быструю трассировку лучей. Гидродинамика тоже выиграет. (Все это абстрактно связано с алгоритмом Shrinking Bullseye.)

Меня заинтриговали ваши комментарии по поводу SIMD, но я оставлю это для другой темы.

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

Вот причины, по которым интервалы должны поддерживаться в WASM:

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

  2. WASM - это недостающее звено, которое нам нужно для поддержки широко распространенных вычислений по запросу именно потому, что оно четко определено вплоть до битового уровня, поэтому легко проверить, что выходные данные от ненадежных узлов идентичны и, следовательно, заслуживают доверия. Без четко определенного поведения мы получаем подходы, которые требуют от программиста ручного сравнения результатов в зависимости от кода. Это просто не масштабируется.

  3. Хорошая наука и инженерия нуждаются в интервальной математике, но ее мало используют, потому что она привязана к языкам более высокого уровня, а не встроена внизу. nVidia решила эту проблему, но для доступа к нему с языков более высокого уровня не хватает достойного ИК-кода. WASM может дать нам недостающий IR.

  4. Будущее распределенных вычислений - за WASM, но только если вы сможете сделать его масштабируемым. Я понимаю, что большинство людей думают об этом как о расширении браузера только для запуска более быстрых веб-страниц, но оно может управлять миром распределенных вычислений к 2030 году, если вы правильно разыграете свои карты. Я не могу этого достаточно подчеркнуть. Без интервалов мы получаем масштабируемую неоднозначность, а не масштабируемую четкость.

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

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

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

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

@brion Что ж, как я сказал выше, я вполне доволен идеей просто реализовать арифметические примитивы с учетом округления в WASM.

Общая проблема с манипуляциями с ULP, независимо от того, решаете ли вы ее с помощью таких примитивов или полной поддержки интервалов, заключается в том, что WASM, вероятно, станет методом, посредством которого распределенные вычисления упрощаются для HLL. По сути, это аппаратное обеспечение. Вы не можете напрямую перейти от HLL к машинному коду CPU / GPU и запустить его на анонимных целях по всему миру. (Представьте, что вы пытаетесь запустить распределенную вычислительную сеть, которая требует наличия графического процессора nVidia XYZ для того, чтобы даже участвовать.) Таким образом, вы должны сначала перейти к промежуточному программному обеспечению, из которого очевидным (и, возможно, единственным) выбором является WASM. Поэтому, если программисту HLL нужна функция, которая _из_ эффективно реализуема на оборудовании, но WASM ее не поддерживает, то ему приходится выполнять неэффективную эмуляцию.

@KloudKoder , может ли f64.fma помочь с производительностью библиотек интервальной арифметики хотя бы за f64 ?

@Yaffle Можете ли вы объяснить свои соображения относительно того, почему умножение-сложение может помочь? Например, как это ускорит процесс добавления двух интервалов, учитывая, что, по-видимому, он все еще будет делать близкие или четные?

помогает найти ошибку умножения двух чисел f64 или деления чисел f64:
сумма = а + б; ошибка = -sum + absmax (a, b) + absmin (a, b);
product = a * b; error = fma (a, b, - товар);
частное = a / b; ошибка = -fma (частное, b, -a);
если вы знаете ошибку, вы можете округлить значение, увеличивая (например, когда error> 0 и округляя до положительной бесконечности) или уменьшая (например, когда error <0 и округляя до отрицательной бесконечности) значение на наименьшую величину.
Таким образом, полученный интервал будет максимально узким.
Хотя, если вам не нужен самый узкий интервал, вы можете просто увеличивать / уменьшать оба конца ...
Кстати, есть веб-сайт с некоторым тестом - http://verifiedby.me/kv/rounding/index-e.html# : ~: text = Benchmark Хм ...

@Yaffle Подождите секунду, вы говорите о fma (который, как я понял, на самом деле нет в спецификации, если верить функции поиска) или fmax / fmin?

Начнем с добавления:

(a, b) + (c, d) = (RoundNegative (a + c), RoundPositive (b + d))

Как это повлечет за собой умножение, я в настоящее время не понимаю. А умножение-сложение принимает 3 параметра, а не 1. Ясно, что я неверно интерпретирую ваши обозначения.

@KloudKoder , fma, которая объединена-умножить сложить, я обновил свою нотацию

@Yaffle Думаю, я наконец понял вашу точку зрения. Вы имеете в виду, что различные инструкции Intel FMA вычисляют:

а * б + с

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

Это означает, во-первых, что:

product = FMUL (a, b)
error = FMA (a, b, -продукт)

эквивалентно:

error = NearestOrEven (ab - FMUL (a, b))

который по определению отключен не более чем на половину ULP, поэтому вам нужно только подтолкнуть результат на 1 ULP, чтобы получить верхнюю границу ошибки.

Это допустимый подход, но подталкивание ULP требует значительных накладных расходов: вам нужно сначала обработать результат как целое число, затем добавить свой ULP (как беззнаковый 1), затем посмотреть, заключили ли вы в поле экспоненты или, возможно, создали NaN и т. д., а затем потенциально выполнить откат и обновить результат до бесконечности или чего-то еще. Есть и другие способы сделать это, но AFAIK также сопряжен с болезненными накладными расходами. И обратите внимание, что я не требовал минимального интервала - просто «достаточно жесткого» для практических требований к точности. Так у вас есть быстрый способ подтолкнуть? Если нет, то, к сожалению, я вернулся к моей исходной точке, а именно, что интервалы не работают при текущем ABI по сравнению с тем, что реально возможно на реальном оборудовании.

Также обратите внимание, что выше я написал FMA, который ссылается на набор инструкций Intel. FMA Webassembly, напротив, не существует. У вас есть ссылка? Он не отображается в поиске документов на веб-сайте.

Наконец, по вашей ссылке:

"сложение / вычитание / умножение / деление / sqrt, включая спецификацию режима округления для самой команды"

Именно об этом и идет речь в этом предложении. Приятно иметь такую ​​возможность, но нам нужен прямой способ ее использовать.

Я счастлив, что мой пессимизм опровергнут ...

@KloudKoder ,
https://github.com/mskashi/kv/blob/2ec8bac6216d25b226c09e1740487837a4fc5fd5/kv/rdouble-nohwround.hpp#L97

  • это еще один вариант функции "подталкивания", кажется, она выполняет x + ABS(x) * (2**-53+2**-105) тогда, когда abs(x) > 2**-969 , что покрывает большинство значений f64 ...

f64.fma упоминается на https://github.com/WebAssembly/design/blob/master/FutureFeatures.md# : ~: text = fma
но если вам не нужен «самый большой интервал», вы можете просто подтолкнуть на 1 ulp оба конца ... хотя это может быть плохо (?).

в любом случае, вы правы, что накладные расходы могут быть большими

@Yaffle Теперь я вижу f64.fma в разделе «Дополнительные операторы с плавающей запятой». Я готов предположить, что это будет принято в качестве инструкции. И уж точно я бы не стал требовать минимального интервала, который вряд ли даст какие-то практические преимущества. Теперь посмотрим на ваш альтернативный толчок:

х + АБС (х) * ( 2-53 + 2-105)

ясно, что суть этого в том, чтобы добавить результат (x) к: самому смещенному вниз, так что его ведущая 1 появляется в ULP. Я не совсем уверен, зачем нам (2 ** (- 105)) - может быть, для того, чтобы разорвать связь между ближайшим или даже в пользу ненулевого подталкивания - но в любом случае вот что мы бы нужно сделать:

  1. Учитывая результат f64 x.

  2. Если x равен +/- 0,0, сдвиньте его вверх / вниз до наименьшего положительного / отрицательного числа и выйдите.

  3. Вычтите 53 из поля экспоненты. Назовите результат y. (В некоторых архитектурах для этого может потребоваться транспорт между регистрами с плавающей запятой и целочисленными регистрами. Давайте просто предположим, что это бесплатно.)

  4. Используйте команду условного набора (преобразование флага в целое число), чтобы запомнить, привел ли # 3 к переносу экспоненты (обычно нет). Это включает в себя несколько целочисленных инструкций, однако, насколько я понимаю, вы это делаете.

  5. ИЛИ результат # 4 к флагу «что-то не удалось», f, который с большой вероятностью будет равен 0.

  6. Пусть z, окончательный результат, будет суммой x и y. Простое округление до ближайшего или даже равного гарантирует, что z является допустимым сдвигом x.

  7. На какой-нибудь будущей контрольной точке перед фиксацией убедитесь, что f равно 0, и откажитесь, если нет.

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

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

Спасибо, что помогли так подробно продемонстрировать масштабы этой проблемы. Куда пойти отсюда?

Что, если я напишу вам поддержку Intel / AMD? Будет ли это достаточно мотивацией для вас, обслуживающего персонала, чтобы перенести его на другие платформы и сделать частью спецификации? Мы можем спорить о деталях и крайних случаях, но нет смысла даже обсуждать их, если мое предложение здесь недостаточно убедительно.

@KloudKoder благодарит за предложение помочь с реализацией :) К сожалению, стандартизация нового предложения предыдущих комментариев о том, почему полезные функции часто не подходят, даже если у них нет никаких технических недостатков.

@tlively Я прочитал ваш предыдущий комментарий и понимаю, почему новые коды операций трудно продать.

В данном случае это особенно неприятно, потому что интервалы пострадали от этой проблемы принятия курицы и яйца с того дня, как они были впервые предложены для использования с поплавками IEEE. По сути, есть большой соблазн избежать их использования на языках высокого уровня, потому что они такие медленные, но никто не хочет делать грязную работу по оптимизации их производительности, создавая внутреннюю поддержку, потому что (сюрприз!) Никто не находит их привлекательными для работы с (если они не отчаянно нуждаются в локализации ошибок). В конце концов, создание эффективных и тривиально доступных интервалов - это вопрос обеспечения безопасности данных - только в аналоговой, а не цифровой сфере. Мы зря тратим большой вклад nVidia (и, возможно, других) в виде инструкций с плавающей запятой, готовых к работе с интервалами.

Проблеск надежды состоит в том, что уже существуют общедоступные спецификации ожидаемого поведения, доступные как в виде исчерпывающего корпуса аксиом, так и в виде «диетической» версии для базовой арифметики. Так что по крайней мере некоторые аспекты их ожидаемого поведения уже определены для нас.

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

@tlively Я понимаю, но это не совсем так. nVidia имеет примитивы аппаратного интервала в смысле инструкций с плавающей запятой со встроенными режимами округления. Они недоступны через WebAssembly.

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

Вы можете рассматривать WebAssembly как способ ускорить работу веб-сайтов. Хотя я не возражаю, я также рассматриваю это как глобальную платформу распределенных вычислений, которая только и ждет, чтобы ее реализовали. Golem, например, уже включил этот хакерский способ, но он мог бы быть намного больше, если бы он обеспечивал аналоговую безопасность, включая этот тип поддержки. Это особенно важно при попытке обеспечить согласованность результатов, полученных на разных платформах (в том числе не использующих WebAssembly), поскольку результаты сложных вычислений с плавающей запятой редко бывают точно равными. Отсутствие интервалов означает, что этого фактически не может произойти, и WebAssembly никогда не реализует свой истинный потенциал. Так что это гораздо больше, чем просто «пожалуйста, сделай это быстро».

О, понятно, я не понимал, что это уже поддерживается оборудованием Intel. Насколько распространена поддержка?

Он довольно широко распространен на процессорах, не только на x86, это то, для чего нужны библиотечные функции fegetround и fesetround . Сложность заключается в том, что режим округления является «глобальным» (для каждого потока) состоянием, которое влияет на операции FP.

@tlively

О, понятно, я не понимал, что это уже поддерживается оборудованием Intel. Насколько распространена поддержка?

@penzn Верно . Этот тип округления присутствует в Intel уже несколько десятилетий. Как он указал, это ужасный дизайн, потому что изменение режима округления требует остановки конвейера с плавающей запятой. nVidia предусмотрительно интегрировала режим округления непосредственно в свои инструкции, поэтому, например, вы можете «складывать и округлять до положительной бесконечности» или «умножать и сокращать до нуля».

То, что я здесь пропагандирую, - если не исчерпывающие примитивы интервалов - это по крайней мере набор кодов операций и / или префиксов, которые обеспечат эффективный доступ к соответствующим инструкциям nVidia. Эти коды операций и / или префиксы затем могут быть, по крайней мере, в некоторой степени эффективно сопоставлены с Intel путем группирования инструкций с одинаковым типом округления в плотные последовательности, чтобы минимизировать манипуляции с режимом округления. Однако это могло быть сделано как повышение производительности; в первом выпуске можно было просто изменять режимы округления буквально, как указано в коде WASM.

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

Не думаю, что я указывал на это;) Это реальность среды CPU FP, хотя, возможно, ее можно было бы спроектировать лучше.

Этот тип округления присутствует в Intel уже несколько десятилетий.

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

В Future Features обсуждается улучшенная поддержка IEEE 754-2019 :

Для поддержки исключений и альтернативных режимов округления можно определить альтернативную форму для каждого из add , sub , mul , div , sqrt и fma . Эти альтернативные формы будут иметь дополнительные операнды для режима округления, маскированных ловушек и
старые флаги и дополнительный результат для нового значения флагов.

Это похоже на исходную идею для fpenv "освобожденного SIMD": https://github.com/WebAssembly/design/issues/1401#issuecomment -789073168.

Недостатком первоклассной поддержки интервалов является то, что для этого потребуется оптимизация времени выполнения на ЦП, в то время как у нас еще нет жизнеспособной реализации графического процессора, где она могла бы органически поддерживаться. Однако идея в «Future Features» страдает той же проблемой.

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

@penzn Да, моя формулировка была плохой. Я имел в виду, что вы упомянули архитектуру контрольного слова, которая, на мой взгляд, ужасна. Суть в том, что небольшое увеличение количества команд Intel в процентах из-за изменения режима округления приводит к многократному взрыву времени выполнения из-за остановок конвейера. Как вы ясно понимаете, единственное частичное смягчение этого - максимально возможное группирование инструкций по режиму округления.

Как бы я ни был рад увидеть полную поддержку интервалов в WASM, в этом нет необходимости. Строительных блоков nVidia было бы достаточно для практичности. (Интересно, как Apple M1 это делает, если на то пошло.) Я понимаю, что пока нет поддержки графических процессоров, но я ожидал бы, что это будет в будущем развитии WASM. Как вы думаете, почему интервальная поддержка должна быть на более высоком уровне? Даже трансцендентные функции (например, журнал) можно напрямую вычислить из базовой интервальной арифметики.

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

Как вы думаете, какой минимальный набор интервальных операций может быть реализован и полезен для ЦП?

@penzn Вряд ли я могу придумать более актуальный вопрос для этой ветки.

Прежде всего, есть два основных варианта архитектуры:

  1. Похоже на Intel. Другими словами, имейте инструкцию «установить режим округления». («Получить режим округления» не обязательно, потому что компетентное программное обеспечение должно знать, что оно уже установлено. Но не беда, если люди этого захотят.)

  2. Похоже на nVidia. Другими словами, имейте 4 формы каждой инструкции: (a) округление до ближайшего или четного (что уже есть в WASM), (b) chop (внутрь к нулю), (c) округление до отрицательной бесконечности и (d) округлить до положительной бесконечности.

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

Поэтому, предполагая, что мы выберем эту опцию, я бы настоятельно не рекомендовал использовать любую инструкцию «установить среду с плавающей запятой» (SFPE), которая одновременно влияет на маскирование исключений. Это приведет к обременению изменений режима округления множеством другой логики. Разделите эти функции по разным инструкциям. (Инструкции SFPE допустимы для совместимости, но они должны быть четко помечены как неработающие.) Важно отметить, что ни SFPE, ни режим set-rounding-mode не должны принимать переменные входные данные. (Представьте, что вам нужно спрашивать «Какой режим округления?» Перед каждой инструкцией, чтобы вы знали, что выполнять на nvidia!)

Тогда возникает вопрос: какой минимальный набор инструкций стоит здесь обсудить? Наверное:

  1. Установить круглые по ближайшему или четному.
  2. Установить отбивную (закруглить внутрь).
  3. Установите круглую отрицательную бесконечность.
  4. Установите круглую положительную бесконечность.
  5. Загрузите ULP.
  6. Толкнуть внутрь.
  7. Сдвинуть наружу.
  8. Получить знаковый бит (немного отличается от «получить знак»).
  9. Знаковые биты Xor, вывод в целое число или флаг (или, может быть, просто «переходить, если знаковые биты (не) различаются»).
  10. Скопируйте знаковый бит в другое значение с плавающей запятой.

Просто ради согласованности мы могли бы захотеть, чтобы первые 4 вышеуказанных кода операций были назначены в соответствии с битами RC Intel в управляющем слове FPU.

5 принимает значение с плавающей запятой (FP), а затем возвращает значение FP с наименьшей величиной, которое при добавлении ко входу с округлением chop изменило бы его значение. (Неявно ULP (X) имеет тот же знак, что и X.) Если вход был либо знаком с нулем, то выход должен быть FLOAT_MIN (наименьшее денормальное значение) того же знака. Если вход был либо знаком бесконечности, то выход не должен изменяться. ULP встречается повсеместно в интервальной арифметике, поэтому для этой инструкции есть фундаментальное оправдание. Например, было бы полезно в случае, если нужно умножить ULP на другое значение FP, чтобы вычислить составной член ошибки, как это произошло бы при эффективном вычислении (Y log X) через (усеченный) ряд Тейлора. Он также используется постоянно, чтобы знать, когда следует прекратить вычисление таких серий.

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

7 Увеличивает мантиссу (без изменения знака). Увеличивает также показатель степени, если мантисса оборачивается. Если вход был либо знаком нуля, то результатом будет FLOAT_MIN того же знака. Если на входе был знак бесконечности, результат должен быть таким же. Если вход был одним из знаков FLOAT_MAX, то результатом будет бесконечность того же знака.

8 Возвращает знаковый бит, что важно, если есть семантическая разница между отрицательным и положительным нулем, которая не может быть зафиксирована традиционной инструкцией «получить знак операнда FP». Обратите внимание, что это касается знакового бита, который в вышеупомянутом случае фактически отличается от (арифметического) знака.

9 важен для интервального деления. Например, обратное значение [2, 3] равно [(1/3), (1/2)] (минимум (1/3) и максимум (1/2)). Но обратное значение [-2, 3] равно [(1/3), (-1/2)], что означает не более (-1/2) ИЛИ не менее (1/3). (Инвертированные пределы подразумевают открытый интервал, в котором конечный сегмент отсутствует в реальной линии.) Причина в том, что [-2, 3] содержит ноль. Более того, он содержит точки как слева, так и справа от нуля, поэтому обратная величина приближается к бесконечности любого знака. Нам нужно знать, противоположны ли знаки, чтобы мы могли определить, менять ли ограничения или нет. Без этой инструкции будет много ветвлений с извлечением знаков только для основной арифметической функции деления.

10 Это всплывает все время, хотя хорошие примеры пока ускользают от меня. Без этой инструкции много срывов конвейера.

Я не возражаю, если приведенные выше инструкции не определены для операндов NaN, или если они ведут себя так, как будто NaN является нормальным значением FP. Нет смысла ускорять сломанную математику. Конечно, любая неопределенная операция потенциально приведет к утечке информации о базовом оборудовании и исключит возможность проверки результатов путем сравнения.

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

Я полностью за то, чтобы установить режим округления вместо первоклассной математики интервалов. Я также лично в порядке с постоянным режимом округления, хотя я думаю, что в Wasm мы пытались избежать глобального состояния, подобного этому - альтернативой было бы добавить варианты математических операций с флагом "режим округления" вместо инструкций 1-4 на вашем список.

Поэтому, предполагая, что мы выберем эту опцию, я бы настоятельно не рекомендовал использовать любую инструкцию «установить среду с плавающей запятой» (SFPE), которая одновременно влияет на маскирование исключений. Это приведет к обременению изменений режима округления множеством другой логики. Разделите эти функции по разным инструкциям. (Инструкции SFPE допустимы для совместимости, но они должны быть четко помечены как неработающие.) Важно отметить, что ни SFPE, ни режим set-rounding-mode не должны принимать переменные входные данные. (Представьте, что вам нужно спрашивать «Какой режим округления?» Перед каждой инструкцией, чтобы вы знали, что выполнять на nvidia!)

+1 и по этому поводу.

  1. Установить круглые по ближайшему или четному.
  2. Установить отбивную (закруглить внутрь).
  3. Установите круглую отрицательную бесконечность.
  4. Установите круглую положительную бесконечность.
  5. Загрузите ULP.
  6. Толкнуть внутрь.
  7. Сдвинуть наружу.
  8. Получить знаковый бит (немного отличается от «получить знак»).
  9. Знаковые биты Xor, вывод в целое число или флаг (или, может быть, просто «переходить, если знаковые биты (не) различаются»).
  10. Скопируйте знаковый бит в другое значение с плавающей запятой.

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

@penzn Если единственный способ продать это - иметь 4 вида каждой инструкции FP (по одной для каждого режима округления), то я бы согласился с этим. nVidia будет довольна (и, кто знает, может оказать некоторую финансовую поддержку).

Я готов забыть о денормальных значениях и просто заменить все приведенные выше ссылки на них «значениями FP с минимальным нормальным показателем» _ при условии_, что есть недорогой способ узнать, когда результаты не заслуживают доверия, потому что были сгенерированы потенциальные денормальные значения. Причина в том, что программное обеспечение более высокого уровня должно знать, что проверка результатов не выполняется между машиной X и машиной Y, потому что они по-разному обрабатывают денормальные значения, а не потому, что на одном из них произошла физическая ошибка. В противном случае мы либо попали бы в бесконечный цикл проверки, либо, что еще хуже, пришли к выводу, что консенсус был достигнут, хотя на самом деле многие машины одинаково получали неправильный ответ. Я предполагаю, что способ обнаружить разницу - либо разоблачить денормальное исключение, либо оставить его замаскированным, но проверить его (предположительно липкий) статус до выдачи окончательного результата. Однако, если это добавляет слишком много накладных расходов, нам, возможно, придется переосмыслить это. (Опять же, для меня «WASM» означает «байт-код промежуточного представления глобальных распределенных вычислений», поэтому в данном случае меня не беспокоят однопоточные операции браузера.)

@penzn Если единственный способ продать это - иметь 4 вида каждой инструкции FP (по одной для каждого режима округления), то я бы согласился с этим.

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

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

Я лично считаю, что это можно превратить в предложение. Что думают все остальные?

@penzn "только один вариант"? Под «вариантом» вы имеете в виду «альтернативные предлагаемые средства кодирования режима округления» или избыточные _поддерживаемые_ средства того же?

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

Что касается предложения, я, очевидно, поддерживаю. Я бы посоветовал, чтобы любое одобрение включало проверку по крайней мере одного эксперта, участвующего в IEEE1788 или IEEE1788.1, стандартах арифметики полного и частичного интервала, соответственно. В частности, мы должны следить за тем, чтобы IEEE1788 эффективно реализовывался с использованием предложенных примитивов. (Я считаю, что это так, но я не уверен.) Не то, чтобы мы предлагали реализовать здесь какой-либо стандарт, но это должно быть возможно сделать с довольно скромными накладными расходами.

Говоря об экспертах по интервальной арифметике, это видео, которое заставило меня задуматься о важности аналоговой безопасности еще в 2007 году. Проблемы, поднятые в видео, сегодня еще более актуальны, потому что, откровенно говоря, достигнут очень небольшой прогресс. Пора это изменить. Выступает Дж. Билл Уолстер. Я перейду к делу, но стоит посмотреть полное видео:

https://www.youtube.com/watch?v=U_Cq_h1vrD0&t=680s

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

https://www.researchgate.net/profile/G-Walster

Не обращайте внимания на мой предыдущий комментарий о денормалах, я думаю, мы можем полностью принять их здесь, поскольку это то, что Wasm делает в целом (также см. WebAssembly / simd # 2).

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

@penzn "только один вариант"? Под «вариантом» вы имеете в виду «альтернативные предлагаемые средства кодирования режима округления» или избыточные _поддерживаемые_ средства того же?

Я имею в виду новые инструкции в дополнение к существующим инструкциям в спецификации. Скажем, для умножения нам нужно будет добавить новую инструкцию (скажем) mul_round , взяв параметр режима округления; затем повторите это для остальных инструкций, зависящих от округления. Это был бы наиболее нейтральный к спецификациям способ сделать это, хотя он, очевидно, избыточен, поскольку новые инструкции будут включать поддержку существующего режима округления. Я лично вижу ценность в режиме липкого округления, поскольку это то, что происходит с родными целями, хотя это может быть трудно продать. Другой гипотетический вариант - это необязательный параметр округления кодирования в существующих инструкциях, но (1) неясно, как это сделать, и (2) я не думаю, что у нас есть прецедент этого.

Я думаю, что материала достаточно, по крайней мере, для обсуждения компьютерной графики, чтобы просмотреть операции в https://github.com/WebAssembly/design/issues/1384#issuecomment -810695841 и решить, какой способ кодирования режима округления предпочтительнее. @KloudKoder, можешь ли ты присутствовать на одном из собраний (см. здесь )? Для этого вам нужно будет создать учетную запись группы сообщества и набрать номер через Zoom - встречи открыты для людей, заинтересованных в участии.

Говоря об экспертах по интервальной арифметике, это видео, которое заставило меня задуматься о важности аналоговой безопасности еще в 2007 году. Проблемы, поднятые в видео, сегодня еще более актуальны, потому что, откровенно говоря, достигнут очень небольшой прогресс. Пора это изменить. Выступает Дж. Билл Уолстер. Я перейду к делу, но стоит посмотреть полное видео:

https://www.youtube.com/watch?v=U_Cq_h1vrD0&t=680s

Спасибо за ссылку - видео очень информативное! Я не уверен, что такое процесс W3C для запроса внешних обзоров, мы тоже можем поднять этот вопрос.

@penzn Хорошо на денормальных значениях. Ужасное наследие, но давайте продолжим, если оно уже работает в WASM.

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

Как насчет этого: вместо того, чтобы создавать 3 новые инструкции для каждой существующей округляемой инструкции, мы просто создаем 3 префикса инструкций (округление отрицательное, округленное положительное и отбрасывание). Никакой префикс не означает «ближайший или четный», поэтому он обратно совместим. Избыточные префиксы, префиксы перед необоснованными инструкциями, попытки определить цели возврата или перехода сразу после префикса или код, который заканчивается одиночным префиксом, будут заблокированы линтером во время компиляции. (Я просто опасаюсь нынешнего и ожидаемого роста определений инструкций, подразумеваемого 4 различными режимами округления, особенно если учесть непрерывный поток новых SIMD, который кажется надежной отраслевой динамикой.) Но это не красная линия для меня. Если команда хочет обрабатывать несколько разновидностей инструкций вместо реализации префиксов, пусть будет так.

Вам нужно будет создать учетную запись группы сообщества.

Ссылка, пожалуйста. Zoom - огромная дыра в безопасности, но я посмотрю, что я могу сделать. Однако я понимаю ценностное предложение.

Я только что понял, что нам еще нужны:

  1. Подтолкнуть к позитиву.
  2. Подтолкнуть отрицательно.

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

Тем, кто, как и я, ненавидит добавлять определения инструкций только ради эстетики, я заранее признаю, что все подталкивания _технически_ не нужны, потому что можно просто загрузить ULP (инструкция # 5), а затем добавить его или вычесть из некоторых другой поплавок. Но это требует явного использования драгоценного регистра и нескольких инструкций. Более того, подталкивания настолько важны, что я считаю, что они заслуживают собственных инструкций. Меня совсем не удивило бы, если бы я увидел их в оборудовании, поскольку полупроводниковая промышленность наконец осознала важность интервалов для обеспечения физической безопасности. Это ускорит процесс, а также избавит от необходимости тратить время и регистр, оценивающий ULP.

Также обратите внимание, что подталкивания обычно идут парами. Это означает, что под капотом снова и снова возникает неявный "Load ULP". Будь осторожен! Это не обязательно одно и то же ULP, поэтому, несмотря на внешний вид, их в общем случае нельзя игнорировать.

Ссылка для присоединения к CG: https://www.w3.org/community/webassembly/

Вам нужно добавить пункт повестки дня (открыть PR) на одну из встреч CG, 4/27 кажется довольно открытым, в файлах встречи также есть инструкции по получению приглашения на звонок: https: // github. ru / WebAssembly / встречи / tree / master / main / 2021

Дайте мне знать, если у вас возникнут вопросы, буду рад помочь.

Тем, кто, как и я, ненавидит добавлять определения инструкций только ради эстетики, я заранее признаю, что все подталкивания _технически_ не нужны, потому что можно просто загрузить ULP (инструкция # 5), а затем добавить его или вычесть из некоторых другой поплавок. Но это требует явного использования драгоценного регистра и нескольких инструкций. Более того, подталкивания настолько важны, что я считаю, что они заслуживают собственных инструкций.

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

@penzn Спасибо. Я жду ответа на свой запрос на регистрацию в CG. Я вернусь к этому вопросу, когда у меня будет дата встречи.

@penzn FYI до сих пор не ответил на мой запрос.

Возможно, нам придется спросить об этом @dschuff .

@penzn Спасибо, сейчас он в процессе, ожидая решения технической проблемы с регистрацией. Отчитаюсь.

@penzn Похоже, что человек, который мне помогал, исчез. На данный момент у меня наконец-то есть учетная запись W3C, но мне интересно, как запланировать встречу. Могу ли я отредактировать здесь один из MD-файлов или как?

https://github.com/WebAssembly/meetings/tree/master/main/2021

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

@KloudKoder да, это правильно - отредактируйте один из файлов и отправьте PR с изменениями. Вы присоединились к группе сообщества? Ссылка https://www.w3.org/community/webassembly/join (можно найти на странице CG . Я не помню, добавлялись ли вы к собраниям CG автоматически или вам все еще нужно отправить электронное письмо председателю.

@dtig , есть ли место для этого на встрече 27 апреля, или она будет полностью занята обсуждениями наслоения и связывания? Кроме того, если у вас есть доступ к приглашениям на собрания, не могли бы вы взглянуть на ситуацию с

@penzn Похоже, мы назначены на 11 мая 2021 года, если я правильно сделал этот пиар?

Я думаю, вам нужно обновить PR, указав, сколько времени вы планируете потратить на презентацию, или прокомментировать это, тогда это будет официально: https://github.com/WebAssembly/meetings/pull/756#issuecomment -822616912

Примечания к сегодняшнему заседанию CG (ничего не высечено на камне):

НАГРУЗКА ULP (LULP)

Загрузите единицы последнего места в f32 или f64. (Эта инструкция работает аналогично с f32 и f64.) Это важно для интервальных операций, границы ошибок которых являются функцией последнего члена, вычисленного в ряду Тейлора. Так, например, можно умножить этот последний член на ULP, а затем расширить интервал на эту величину с каждой стороны. Вычислять с помощью логических инструкций очень дорого, и он часто встречается в обычных интервальных вычислениях.

Есть несколько разных случаев:

  1. + -0.0 -> + -epsilon (ненулевое значение с плавающей точкой наименьшей величины).

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

  3. + -small -> + -epsilon, где small меньше 1.0x2 ^ (- 125) для f32 или 1.0x2 ^ (- 1021) для f64.

  4. + -other -> + -X, где X - наименьшее положительное число с плавающей запятой, которое при добавлении к другому при округлении чопов изменит свое значение.

НАГРУЗКА ПОЛОВИНЫ ULP (LHULP)

Роли LULP и LHULP совершенно разные. LULP используется для вычисления окончательных границ ошибки, но LHULP используется для проверки тривиальности текущего термина Тейлора. Когда текущий член становится меньше половины ULP, часто известно, что максимальная ошибка является либо полным ULP, либо произведением полного ULP и текущего члена. У него разные угловые случаи из-за прерывности экспоненциальных областей, поэтому очень дорого выполнять вычисления на уровне абстракции программиста.

  1. + -0,0 -> + -псилон.

  2. + -бесконечность -> + -бесконечность.

  3. + -small -> + -epsilon, где small меньше 1.0x2 ^ (- 124) для f32 или 1.0x2 ^ (- 1020) для f64.

  4. + -other -> + - (X / 2) где X - наименьшее положительное число с плавающей запятой, которое при добавлении к другому при округлении с чопом изменит свое значение.

Толчок внутрь (NIN)

Эта инструкция используется для расширения открытого интервала путем перемещения одной из его границ внутрь к нулю с помощью ULP. (Открытые интервалы подразумевают их границы, перечисленные в обратном порядке. Они означают «все на реальной линии, кроме этого интервала».) Обратите внимание, что [-0.0, -0.0], [+0.0, +0.0] и [-0.0 , +0.0] все означают «только ноль», а [+0.0, -0.0] означает «все, кроме нуля».

  1. + -бесконечность -> + -бесконечность.

  2. + other -> max (+0.0, + other -LULP (+ other)) где (-0.0) <(+ 0.0).

  3. -other -> min (-0.0, -other -LULP (-other)), где (-0.0) <(+ 0.0).

Как видите, это довольно дорого.

ТЯНУТЬ ВНУТРИ (НЕТ)

Этот метод используется для расширения (замкнутых) интервалов путем перемещения одной из его границ из нуля с помощью ULP.

  1. + -бесконечность -> + -бесконечность.

  2. + -другой -> + -другой + LULP (+ - другой).

ПОЗИТИВНЫЙ ПОДСКАЗКА (NPOS)

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

  1. + -бесконечность -> + -бесконечность.

  2. + другое -> + другое + LULP (+ другое).

  3. -другой -> -другой -LULP (-другой).

НАЖМИТЕ ОТРИЦАТЕЛЬНЫЙ (NNEG)

Эта инструкция действует противоположно NPOS.

  1. + -бесконечность -> + -бесконечность.

  2. + другое -> + другое -LULP (+ другое).

  3. -другой -> -другой + LULP (-другой).

ПОЛУЧИТЬ БИТ ДЛЯ ПОДПИСКИ (GSB)

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

УСТАНОВИТЬ ЗНАКОВЫЙ БИТ (SSB)

Копирует знаковый бит из нулевого бита целого числа или, возможно, флаг переноса.

БИТЫ ЗНАКА XOR (XSB)

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

БИТ ДЛЯ КОПИРОВАНИЯ (CSB)

Скопируйте знаковый бит одного числа с плавающей запятой в знаковый бит другого. (Это то же самое, что и CopySign? Я думаю, нам нужна инструкция для знакового бита и еще одна для арифметического знака.)

КРУГЛЫЙ БЛИЖАЙШИЙ-ИЛИ-ЧЕТНЫЙ, КРУГЛЫЙ, ОТРИЦАТЕЛЬНЫЙ, КРУГЛЫЙ ПОЛОЖИТЕЛЬНЫЙ

Эти префиксы, разновидности инструкций или часть глобальной переменной описывают политику округления? Префиксы обеспечивают максимальную обратную совместимость с минимальным расширением инструкций в будущем. Нужно обсудить.

Возможно, я не смогу прийти на встречу сегодня, поэтому просто выскажу свое мнение

  • коленный рефлекс +1 к опции "инструкция"

  • префиксы были бы хороши, но банку червей для других частей языка (в прошлом мы сопротивлялись их использованию в качестве решений)

  • наличие «политики округления» глобального состояния / переменной кажется, что это создаст ненужные вопросы / проблемы при проектировании по отношению к композиционности модуля, поэтому предпочел бы один из двух других подходов

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

@penzn @dschuff Все это обсуждалось на последней встрече WASM CG. Должен сказать, что я был очень впечатлен качеством отзывов и способностью каждого придерживаться темы.

Суть в том, что группа хочет увидеть какое-то сравнение производительности на практике. Мне было поручено создать сравнение яблок с яблоками на каком-то производительном языке (вероятно, C), не обязательно компилируя до WASM. В частности, предлагается включить в эксперимент 2 независимо оптимизированных режима работы: (1) реализация, включающая 4 режима округления, описанных выше (через макросы управления режимом округления), и (2) текущее состояние дел с округлением до ближайшего или четного, используя любые хаки, необходимые для получения бинарно идентичных результатов.

Есть три уровня сложности:

  1. Легко: оцените трансцендентные функции, в которых мы заранее знаем знак и вероятный диапазон выходных данных на основе быстрой проверки параметра. Таким образом, мы можем оптимизировать для минимального переключения между режимами округления. Это часто возникает в физическом моделировании.

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

  3. Жесткий: продукты той же матрицы, но со смещением, чтобы иметь нулевое среднее значение, поэтому знаки необходимо проверять в режиме реального времени. Это вызывает либо постоянное изменение режима округления, либо двухпроходный подход, при котором положительные промежуточные продукты обрабатываются отдельно от отрицательных, что усугубляет доступ к памяти. Это может появиться в ИИ, где есть как награды, так и наказания.

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

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

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

Мысли вслух: мне кажется, что мы могли бы забыть о ULP (и его манипуляции с int, что очень дорого), если бы следующие были более производительными:

При добавлении / вычитании интервалов просто умножьте верхний предел на (1 + дельта), а нижний предел на (1-дельта), где дельта - это верхний предел 1,0 и, следовательно, постоянный. Тогда сделайте наоборот. Отсортируйте результаты (что должно быть возможно в одной 4-сторонней инструкции SIMD). Возьмите самое отрицательное как новый нижний предел, а самое положительное как новый верхний предел. Или не сортируйте и просто берите min и max в последовательных инструкциях. (С другой стороны, нам может быть лучше использовать эту мощность SIMD для построения ULP сразу на 4 поплавках.)

Для умножения вычислите все 4 возможных произведения, а затем все 8 возможных значений дельта-масштабирования. Отсортируйте их и сделайте то же, что и выше.

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

@ conrad-watt @penzn @tlively

Извините, это заняло так много времени. Позвольте мне поделиться своими недавними мыслями. Позволять:

E = эпсилон (наименьший положительный результат)
S = маленький (ранее «дельта»: что-то вроде (2 ^ (- 20)) для f32 или (2 ^ (- 50)) для f64)

Теперь вам нужно умножить [A, B] на [C, D] (деление еще сложнее):

  1. Используйте SIMD для вычисления AC, AD, BC и BD.

  2. Используйте SIMD, чтобы найти минимальный X (самый отрицательный) и максимальный Y из этих 4 значений.

  3. Используйте SIMD для вычисления (X (1-S)), (X (1 + S)), (Y (1-S)) и (Y (1 + S)).

  4. Используйте SIMD, чтобы найти минимальное P и максимальное Q из этих 4 значений.

  5. Выпустить продукт [P, Q].

Как я предлагал ранее, идея состоит в том, что вы выбираете S достаточно большим, чтобы преодолеть неверное «перетаскивание», вызванное ближайшим или даже во всех случаях, поэтому вам вообще не нужны какие-либо настраиваемые режимы округления. Гений, правда?

К сожалению ... не работает! Рассмотрим случай, когда, скажем, точное значение AC немного меньше, чем E. Тогда функция "ближайший или даже" повысит его до точно E. Вы пытаетесь исправить это, умножая на (1-S), но ближайшее - или даже результат по-прежнему E из-за ошибки квантования. То же самое и для большинства денормальных чисел.

Таким образом, в дополнение к вышесказанному, можно иметь постоянный трекер, который запоминает наименьшее ненулевое абсолютное значение, когда-либо созданное. Если он упадет ниже некоторого порога, то вы знаете, что трюк (1-S) не сработал, поэтому вам нужно сделать откат и вычислить все заново, используя какой-то совершенно другой алгоритм. Нет. Веселье.

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

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

Мысли?

Забыл упомянуть: один из заманчивых выходов из проблемы (1-S) - просто добавить или вычесть несколько единиц E из минимума и максимума, а затем снова взять минимальное и максимальное значение, чтобы правильно разобраться со знаками. Если не ошибаюсь, это действительно работает. Однако затем мы попадаем в ситуацию, когда чисто положительные интервалы могут иметь продукты, которые вторгаются в отрицательные. Это открывает целую банку червей, потому что обычно такое поведение считается невозможным, независимо от точности. Он имеет реальные эффекты кодового пути, когда потенциально приводит к возникновению открытых интервалов из-за принятия обратных значений (закрытых интервалов, охватывающих ноль). Мы могли бы избежать этой проблемы, в свою очередь, проверяя пределы и вручную разбираясь с крайними случаями, но тогда я думаю, что мы снова вернулись к «гротеску».

Я хотел бы получить отзывы от заинтересованных сторон о том, где должен быть порог коэффициента производительности, чтобы оправдать включение этих предложенных инструкций в стандарт. Я спрашиваю, потому что прошли месяцы, а у нас до сих пор нет предложений от кого-либо, включая меня, даже если бы коэффициент производительности был меньше 2X. Основываясь на лучшем на данный момент дизайне, это также может показаться консервативной нижней границей. Реализация тестового примера кажется довольно сложной задачей, потому что, в зависимости от конкретной стратегии, он может включать в себя вызов встроенных функций SIMD, специфичных для конкретного компилятора, и, в любом случае, магии среды с плавающей запятой. Выполнение полной эмуляции с плавающей запятой не потребует всего этого, но (1) это будет огромный проект сам по себе и (2), вероятно, не приведет к реалистичному сравнению. На данный момент, пройдя через многочисленные кроличьи норы только для того, чтобы прийти к совершенно неэффективным альтернативным реализациям, я чувствую, что эти предложенные инструкции, и, прежде всего, варианты режима округления, предлагают преимущество в отношении производительности намного больше, чем было использовано для оправдания многих других инструкций. что WASM использует и имеет аппаратную основу. Другими словами, действительно ли нам нужно проделывать все этапы крупного демонстрационного проекта только для того, чтобы доказать то, что сейчас, на мой взгляд, очевидно? Конечно, вы можете возразить, что интервальная арифметика никому и никогда не понадобится, но я думаю, что мы прошли этот этап. Возникает вопрос: можно ли это сделать эффективно с помощью каких-либо творческих уловок с помощью WASM как есть? А если нет, то какое ускорение заставит сообщество стандартизировать рассматриваемые инструкции? И, наконец, в свете этого порога, очевидно ли уже в отсутствие явной демонстрации, что мы его превысим? Мы не на 20% земли и никогда не были.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

aaabbbcccddd00001111 picture aaabbbcccddd00001111  ·  3Комментарии

artem-v-shamsutdinov picture artem-v-shamsutdinov  ·  6Комментарии

jfbastien picture jfbastien  ·  6Комментарии

konsoletyper picture konsoletyper  ·  6Комментарии

spidoche picture spidoche  ·  4Комментарии