CUDA, точность поплавка - PullRequest
       7

CUDA, точность поплавка

1 голос
/ 17 сентября 2011

Я использую CUDA 4.0 на Geforce GTX 580 (Fermi).У меня есть номера, такие как 7.721155e-43.Я хочу умножить их друг на друга только один раз или лучше сказать, что я хочу вычислить 7.721155e-43 * 7.721155e-43.

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

Ответы [ 2 ]

5 голосов
/ 17 сентября 2011

Величина наименьшего нормального числа IEEE с одинарной точностью составляет около 1,18e-38, а наименьшая денормализация сводит вас к 1,40e-45.Как следствие, операнд величиной 7,82e-43 будет содержать только около 9 ненулевых битов, что само по себе может быть проблемой, даже до того, как вы перейдете к умножению (результат которого опустится до нуля с одинарной точностью).Таким образом, вы можете также захотеть взглянуть на любые вычисления в восходящем направлении, которые производят эти крошечные числа.

Если эти небольшие числа являются промежуточными терминами в математическом выражении, переписайте это выражение в математически эквивалентное, которое не включает крошечныепромежуточные звенья будут одним из способов решения проблемы.Или вы можете масштабировать некоторые операнды с помощью коэффициентов, равных двум степеням (чтобы избежать дополнительного округления из-за масштабирования).Например, масштабировать до 2 ^ 24 = 16777216.

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

float r, f = 7.721155e-43f;
double d, t;

d = (double)f;   // explicit cast is not necessary, since converting to wider type
t = d * d;
[... more intermediate computation, leaving result in 't' ...]
r = (float)t;    // since conversion is to narrower type, cast will avoid warnings
0 голосов
/ 16 августа 2014

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

> 7.721155e-43 * 7.721155e-43
[1] 5.961623e-85
> exp(log(7.721155e-43) + log(7.721155e-43))
[1] 5.961623e-85
...