774 Тем для обсуждения
6,825 Открытых обсуждений
- Association for Computing Machinery TechNews (ACM)
- Go Parallel! (Dr. Dobbs)
- HPCwire (Tabor Communications, Inc.)
- insideHPC (John West)
- Joe Duffy's Weblog (Microsoft)
- Microsoft Parallel Programming Development Center (Microsoft Germany)
- MultiCoreInfo.com
- scalability.org (Scalable Informatics)
- Software Dev Blog (Intel Germany)
- Soft Talk Blog (Intel United Kingdom)
- The Moth (Microsoft)
Достоверны ли вычисления?
Igor Vorobtsov (Intel) (3 пост(а)) 07.12.2011 17:28
В последнее время я достаточно много занимаюсь вопросами, связанными с точностью результатов, полученных при вычислениях, и пытаюсь найти ответ на вопрос - можно ли вообще получить точные результаты и как это сделать? Если отвечать на данный вопрос коротко и ясно – НЕТ, точный результат «в лоб» на машине получить практически невозможно при наличии сколь-нибудь сложной математической задачи, которую мы пытаемся решить.
Речь идёт не о погрешностях, которые возникают при использовании того или иного численного алгоритма и метода – речь о модели представления действительных чисел. Ввиду «ограниченности» машин, мы не можем точно представить все действительные числа – только лишь аппроксимировать их. В математическом анализе, для любого вещественного числа имеется бесконечно много чисел, которые больше или меньше его, а между любыми двумя вещественными числами также находится бесконечно много вещественных чисел. Система же машинных чисел конечна и дискретна, и образует подмножество системы вещественных чисел. Отсюда и возникает погрешность, которая будет накапливаться с количеством математических операций.
Многие скажут, что подобная точность и не нужна – ну подумаешь, в десятом знаке после запятой будет не тройка, а семёрка… а вот если нужна? Если мы решаем задачи, в которых эти значения могут быть весьма критичными (скажем, проблемы устойчивости атомных реакторов и подобные инженерные задачи), и мы должны точно знать, верно ли оно или нет? Кроме того, мы не гарантируем корректность проверки числовых соотношений. Например, если имеется код
if x < 0 then A else B
и значение х вычисляется приближенно, то и правильность ветвления может оказаться под угрозой.
А может быть, всё-таки, есть способ вычислять точно? Да, такие способы есть, и их, на сегодня, целых 2 – но с понятием «точно» в данных случаях нужно быть очень аккуратным.
Первый подход – давайте заменять точное значение приближенным (что ещё нам остаётся делать), и производить оценку погрешности исходных данных и округлений. У данного подхода есть целый ряд серьёзных минусов, в частности, для нетривиальных алгоритмов получить оценку оказывается чрезвычайно сложной задачей. Кроме того, вычисления по формулам, связывающим погрешность исходных данных и погрешность результатов, сами неизбежно производятся с погрешностью.
А вот второй поход, мне показался наиболее интересным – так называемый интервальный подход. Неизвестное точное значение заменяется не единственным приближенным, а множеством элементов. Всё просто – на уровне программиста, можно сказать, мы вводим новый тип данных – interval, у которого есть нижняя и верхняя границы. Производя какие-бы то ни было вычисления, мы оперируем с границами интервалов, округляя нижнюю границу с недостатком, а верхнюю – с избытком. При этом для использования данного подхода, очевидно, необходимо реализовать интервальную арифметику, определив операции сложения, умножения, и т.д.
Использование подобной арифметики приведёт к получению интервала, как результата вычислений, и в этом случае мы сможем гарантировать, что точное значение лежит в данном интервале. Кроме того, сравнивая нижнюю и верхнюю границы, мы сможем точно сказать, какое количество верных значащих цифр у нас есть. Например, при получение результата в виде [0.092312986, 0.092313129], мы можем точно сказать, что 0.09231 – значение, которое не зависит от машинных округлений.
Ввиду математической направленности и ряда других причин, в своей работе я использую Fortran. К большому сожалению, в Интеловской реализации Фортрана интервальной арифметики нет, хотя подобная реализация есть в ряде расширений для языков, например, XSC языков (Pascal-XSC), а так же в реализации Sun. Так что интервальную арифметику я реализовывал сам в виде модуля на языке Фортран.
На сегодня, пожалуй, и всё. Это вводная статья, написанная с целью определения интереса к данному вопросу.
Если тема найдёт отклик в ваших сердцах и головах
, я с удовольствием поделюсь своим опытом в вопросе достоверных вычислений и расскажу о реализацию арифметики более подробно.
И напоследок… для тех, кому данная тема показалась интересной, есть простая задачка, наводящая на мысли о правильности ветвления и сравнения действительных чисел (ну и о смысле «бытия»
).
Итак, пусть у нас есть два вещественных числа a и b (на Фортране – real, на С – float). Так вот, равны ли значения a = 1.1 – 1 и b = 0.1? И что меняется, если a=1.5-1, а b=0.5?
Категории: Intel Software Network, Разработка софта
Метки: точность вычислений
Пожалуйста, обратитесь к странице Уведомление об оптимизации для более подробной информации относительно производительности и оптимизации в программных продуктах компании Intel.
Комментарии (23)
| 07.12.2011 05:35
Igor Vorobtsov (Intel)
| а можно прям простенькую програмку написать и посмотреть на чудеса арифметики с плавающей точкой )) |
| 07.12.2011 05:41
Dmitry Oganezov (Intel)
| Это мне нужно до офиса добраться а то фортрана нет ;) Да и вряд ли у кого-то из читателей фортран установлен. |
| 07.12.2011 10:49
Igor Vorobtsov (Intel)
| А Фортран и не нужен... все парвила работают с любым языком... скажем, на С результат будет тоже весьма интересным. |
| 07.12.2011 11:08
ilnarb
|
ответ на вопрос: первое не равно, второе равно. на С++ легко реализовать интервальную арифметику, определив все операторы для пользовательского типа. |
| 07.12.2011 11:11
ilnarb
| мой ответ для С float, с фортраном никогда не связывался, и надеюсь, не придется |
| 07.12.2011 11:11
Igor Vorobtsov (Intel)
|
а почему? ))) собственно, именно так я и сделал на Фортране - определил и перегрузил все операторы для своего типа interval... но тут есть нюансы. Кстати, на Фортране это сделать нисколько не сложнее - Fortran 95 позволяет и опреаторы определять, и перегружать функции, и память динамически выделять. |
| 07.12.2011 11:14
Igor Vorobtsov (Intel)
| а разницы никакой нет.. Фортран, С... везде поддерживается стандарт IEEE 754 для работы с "плавающими" числами |
| 07.12.2011 16:07
ksili
|
> можно ли вообще получить точные результаты и как это сделать? Использовать только целые числа! :)) > Неизвестное точное значение заменяется не единственным приближенным, а множеством элементов. Всё просто – на уровне программиста, можно сказать, мы вводим новый тип данных – interval, у которого есть нижняя и верхняя границы. Производя какие-бы то ни было вычисления, мы оперируем с границами интервалов, округляя нижнюю границу с недостатком, а верхнюю – с избытком. Ну так интервал же будет увеличиваться? Или нет? Чем это отличается от накапливаемой погрешности при обычных вычислениях? По-моему ничем. Точнее отличается - вычислений теперь в два раза больше. Мне кажется, работу с интервалами следует использовать только при проверке близости результата к нужному значению (типа проверка на "равенство"). Ибо так вычислений становится в 2 раза больше только при проверке, а не на каждом шаге. А вообще , мне кажется выход в том, чтобы использовать алгоритмы, которые либо лишены накапливания погрешности, либо такие, которые позволяют делать что-то вроде синхронизации в системах связи (погрешность помаленьку накапливается, но на каком-то шаге - периодически - происходит корректировка до нулевой погрешности). |
| 08.12.2011 01:47
Igor Vorobtsov (Intel)
|
Всё правильно, интервал будет увеличиваться/расширяться, но тем самым мы гарантируем наличие точного значения внутри данного интервала.А как оценить накапливаемую погрешность при обычных вычислениях? В этом и основаня проблема. Важно понимать, что даже если мы будем её постоянно вычислять, то сами эти вычисления идут с погрешностью - ведь мы не можем представить любое число с плавающей точкой точно на машине. А вот интервальная арифметика решает эту проблему. Использовать алгоритмы, которые лишены накапливания погрешности, к сожалению, невозможно, потому что это закладывается в основах машинной арифметики, а не самого алгоритма, и мой пример легко показывает, какие проблемы из-за этого возникают. |
| 09.12.2011 00:34
ilnarb
|
>> а почему? ))) число представляется как сумма степеней двойки, во втором случае 2^0+2^(1/2), в первом случае нельзя получить точно 1.2 за конечное число элементов ряда, ограниченной размерностью переменной |
| 12.12.2011 06:37
Igor Vorobtsov (Intel)
| Вот, всё дело как всегда в ограниченности размера... интервальная арифметика - своеобразный выход из ситуации. |
| 10.01.2012 22:13
С.П. Шарый |
Используемый Вами термин "достоверные вычисления" плох, так как на русском языке ещё с 70-х годов существует устоявшийся термин "доказательные вычисления", введённый К.И.Бабенко. Можете "погуглить" и лично убедиться. Специально для Вас выложил на http://www.nsc.ru/interval/SharyCMO11.pdf свою презентацию на конференциях прошлого года в Челябинске и на Байкале, где этот момент разъясняется. Неологизм "достоверные вычисления" попытались (на мой взгляд, очень неумно) ввести в оборот группа переводчиков книги Кулиша и др. на русский язык в 2005 году. А Вам не нужно усиливать терминологическую путаницу. Кстати, где Вы конкретно работаете в Интеле? Мне Ваши популярные лекции читать дюже умилительно, так как интервальная арифметика (и не только) присутствовала в Intel MKL начиная с версии 8.0 (сентябрь 2005 года). Реализовывал её я лично сам (работая в Новосибирском отделении Интела с августа 2004-го по март 2007-го), вместе с различными решателями. И даже храню латунный диск с гравировкой сего события (который даётся всем разработчикам, которые внесли вклад в продукт). Потом через несколько лет эту интервальную арифметику выкинули из MKL, но это уже отдельная история, которая происходила без меня. Теперь вот интересно наблюдать, как "жизнь берёт своё", и интерес к моей науке и к тому, чем когда-то занимался я, снова пробивает себе дорогу в полувоенном Интеле, где когда-то "зарезали" (в конце августа 2006 года) эту самую интервальную арифметику как бесперспективную. Для информации. Мы тут в Новосибирске организуем очередной всегалактический симпозиум SCAN'2012 по компьютерным арифметикам, доказательным численным методам и интервальному анализу, смотрите на http://conf.nsc.ru/scan2012 Приглашаем Вас и всех заинтересованных людей принять участие в нём. Конференция такого уровня проводится в России впервые. Между прочим, Sun'овский интервальный Фортран, о котором Вы пишете, реализовывался в Новосибирске компанией "УниПро" (в 1997-2002 годах, а я был членом этой команды). Хотя наш руководитель А.В.Кулибаба, к сожалению, ушёл из жизни, здесь ещё сохранились люди, которые писали коды и принимали те или иные конкретные проектные решения, и они многое могут рассказать ... |
| 10.01.2012 22:26
С.П. Шарый |
Побеспокою Вас ещё вот по какому поводу. В выложенной для Вас презентации на http://www.nsc.ru/interval/SharyCMO11.pdf есть ответ на вопрос участника ksili о том, каким же образом можно организовать алгоритм для того, чтобы интервальные границы погрешностей не были слишком велики. Один из перспективных способов - апостериорное оценивание погрешностей результата (интервальными методами, естественно). Тут ошибка не будет накручиваться, как снежный ком. |
| 11.01.2012 00:11
Tamara Kashevarova (Intel)
|
Господа, методы интервальной математики успешно развиваются столь давно, что достаточно набрать в http://www.google.com " методы интервальной математики" и вы сможете найти полезные ответы. можно набрать "интервальный анализ" или "методы расространения ограничений и интервальный анализ". Кстати, в MKL (Intel) были реализованы некоторые методы интервальной математики для решения линейных систем уравнений и операции интервальной арифметики. По методам интервального анализа уже более 20 лет проводятся регулярные научные как международные, так и Российские конференции. Успехов! |
| 11.01.2012 07:27
Dmitry Petunin (Intel)
|
Конечно же, интервал, по мере вычислений, будет увеличиваться. Более того, при вычислении значений немонотонных функций он будет увеличиваться очень быстро. Поэтому, например, для решения уравнений существуют специальные интервальные методы вычислений и интервальные аналоги иттерационных методов, для которых важныой частью итерации явлется пересечение с интервалом полученным на предыдущем шаге. Таким образом эти алгоритмы монотонно сужают интервал и критерием остановки служит, достаточное сужение интервала либо малая скорость его сужения. |
| 11.01.2012 17:15
ksili
|
У вас в презентации есть фраза > Ввод данных вЭВМ и арифметические операции с ними неизбежно сопровождаются ошибками Хочу повториться: с целочисленными данными ошибок нет. |
| 11.01.2012 17:22
ksili
|
Ещё хотел спросить, есть ли какой-то способ быстро получать интервальное представление одного числа? Т.е. есть вещественное число. Оно не имеет точного представления в ЭВМ. Соответственно FPU будет округлять его в соответствии с режимом округления. При этом округлении получаем одну границу интервала для данного числа. Получается, чтобы получить вторую границу, надо изменить режим округления (например, сначала был - к плюс бесконечности, а потом - к минус бесконечности), и опять загрузить это же число в FPU. Не слишком ли долгая это операция (если таких интервалов надо получить много)? Какие могут использоваться приёмы для ускорения получения интервала? И может я не так всё понимаю и проблемы нет? |
| 11.01.2012 20:24
С.П. Шарый |
Ответ на первый пост от ksili. > У вас в презентации есть фраза > > Ввод данных вЭВМ и арифметические операции с ними неизбежно сопровождаются ошибками > Хочу повториться: с целочисленными данными ошибок нет. Правильно. Но насколько ценны ввод-вывод и вычисления только с целочисленными данными? Математическое моделирование требует в огромном количестве задач вычислений с непрерывными числовыми полями типа вещественной оси. Тут даже вычисления с рациональными дробями (аналог упомянутых Вами целочисленных вычислений) не помогут сильно. Всё равно, при сколько-нибудь длинной цепочке вычислений, Вам придётся "сбрасывать" сложность представления этих рациональных дробей - путём аналога округления. Или же, если Вы захотите тащить всё усложняющиеся дробные представления всё дальше и дальше, придётся смириться с тем, что вычисления Ваши замедлятся до безобразия. И, возможно, Вы ничего путного так и не сможете вычислить за отведённое Вам время! |
| 11.01.2012 20:36
С.П. Шарый |
Ответ Дмитрию Владимировичу Петунину из Интела. -))) Вы правильно обрисовали один из возможных способов уменьшения ширины интервалов в вычислениях - пересечение с другими известными оценками (с уже полученными ранее, к примеру). Но я имел в виду принципиально другой способ (это и представлено в моей перезентации) - апостериорное оценивание погрешностей. Суть его в том, что вначале мы обычным и привычиным нам образом получаем точечный результат. Недоказательный, естественно, без всяких там интервальных границ и т.п. А потом уже на его основе строится маленький брусик (интервальчик), например, чуть-чуть раздувая полученное приближённое решение, и уже относительно него - нового брусика - доказываем, что он содержит что надо. Для решений "обратных задач" (к которым относятся все уравнения) этот способ даёт гораздо более узкие интервалы оценок, чем "традиционные" интервальные вычисления, так как просто процедуры верификации, о которой я упомянул, гораздо меньше весит. Я в своё время реализовывал один из этих методов (метод Румпа) в качестве семантического теста для компилятора. Помните, ещё некая Озолс критиковала меня за то, что в этой программе у меня большую часть вычислений составляли неинтервальные. Ну так там и нужно было, поскольку верификация в обратных линейных задачах (типа решений СЛАУ) обычно очень проста. |
| 11.01.2012 21:13
С.П. Шарый |
Отвечаю на последний вопрос ksili. В самом деле, переключение режима округления - операция дорогостоящая, и потому её всячески обходят при реализациях. Например, с помощью такого трюка. Выставляем режим округления к +infty, вводим правый конец интервала, локализющего данное вещественное число x. Потом берём (-x) - а это не стоит почти ничего, и с ним проделываем то же самое, формируя правый конец интервала, локализующего (-x). Второй раз меняем знак - теперь уже для этого правого конца от (-x). Это и будет левый конец интервала, локализующего исходный x. Можете посмотреть Appendix B спецификации на интервальный Фортран-95 от Sun Microsystems, который я выложил на наш сайт http://www.nsc.ru/interval в раздел программирование. Там подробно расписаны алгоритмы реализации интервальных арифметических операций с помощью такого трюка. Что же касается необходимости проделывать отдельные операици ввода для ДВУХ концов интервала, локализующего число, то это уже никак нельзя обойти. |
| 12.01.2012 01:27
Igor Vorobtsov (Intel)
|
Спасибо за комментарии!!! Очень правильные и по делу! Да, с целыми числами проблемы нет - но и в серьёзных прикладных задачах работать с целыми числами не получится. По второму вопросу - способ есть, я написал простенькую функцию, которая производит вычисление нижней и верхней границы (округление вних и вверх). Делал всё численно. Использовал встроенные функции (в Фортран) epsilon и tiny для определения машинного эпсилона и наименьшего числа. Проверял, какое у нас значение (в сравнении в tiny) и либо умножал его либо на (1.d0 - epsilon) или на (1.d0 + epsilon), либо занулял или присваивал значение -tiny (для округления вниз, ввер= - просто tiny). Менять режим округления слишком затратно - это точно! |
| 24.02.2012 04:11
Igor Vorobtsov (Intel)
| Огромное спасибо, уважаемый С.П. Шарый, за такие подробные комменты и презентацию. Видимо, именно про вас говорил Гена Фёдоров, когда рассказывал мне, что над подобными задачами в Интеле уже работали :) Но, данную работу я провожу в рамках университета (ННГУ), никаких планов по включения в MKL нет - хотя я был бы очень рад, если бы ваши наработки остались и до сих пор. |




Dmitry Oganezov (Intel)
25,608
Добро пожаловать в ISN блог, Игорь!
Над вопросом подумаю, повспоминаю...