LINUX.ORG.RU

быстрый логарифм

 ,


0

1

есть некоторая жирная (по времени вычислений) функция f(X), результат которой заранее рассчитан и занесён в таблицу. лучше всего эта функция интерполируется, если взять шаг X=1.1^N. Соответственно, для того что бы получать индексы таблицы нужно знать log(X)/log(1.1), но этот log() работает медленно и меня совсем не устраивает. посоветуйте какой ни будь быстрый алгоритм нахождения логарифма, а если такой реализован на fortran'е то вообще замечательно.

X и f — float одинарной точности

★★★★★

Последнее исправление: thunar (всего исправлений: 2)

Ответ на: комментарий от Xunnu

больше 1.05 и меньше или равном 1.5, лучше всего интерполяция ложится на основание 1.1.

thunar ★★★★★
() автор топика
Последнее исправление: thunar (всего исправлений: 1)

посоветуйте какой ни будь быстрый алгоритм нахождения логарифма

Запиши и логарифмы в таблицу. Функцию закешировал, а логарифмы чего стесняешься то?

Norgat ★★★★★
()

Замени LOG на LOG10.

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

vromanov ★★
()
Ответ на: комментарий от vromanov

Она и так и так большой получится..

так мне ~100 записей хватает.

по основанию 2 слишком точность падает, вот такое получается: http://postimg.org/image/q5unmszdj/

а по основанию 1.1 http://postimg.org/image/dn173se43/.

thunar ★★★★★
() автор топика
Ответ на: комментарий от Rakot

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

thunar ★★★★★
() автор топика
Ответ на: комментарий от Norgat

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

thunar ★★★★★
() автор топика
Ответ на: комментарий от thunar

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

Rakot ★★
()
Ответ на: комментарий от aiqu6Ait

что то не получается — не совпадают значения

real(4)::a

do i=0,200
a=i
print *, fastlog(a),log(a)/log(2.)
enddo

end

function fastlog(x) result(y)
real(4)::x,y
real(4)::r4Mant
integer(1)::i1Exp

r4Mant=SET_EXPONENT(x, 0)
i1Exp=EXPONENT(x)

y=r4Mant*1./log(2.) + i1Exp

endfunction

thunar ★★★★★
() автор топика
Последнее исправление: thunar (всего исправлений: 1)
Ответ на: комментарий от Rakot

Вероятность столновения?

сечения же.

И почему бы вместо таблиц не воспользоваться логарифмической интерполяцией?

потому что функция log() медленно считает.

real::t0,t1,R
integer::i

call cpu_time(t0)
do i=1,10000000
R=rand()
R=sqrt(R)
enddo
call cpu_time(t1)
print*,t1-t0

call cpu_time(t0)
do i=1,10000000
R=rand()
R=log(R)
enddo
call cpu_time(t1)
print*,t1-t0

end
  0.13000000    
  0.44999999
thunar ★★★★★
() автор топика
Последнее исправление: thunar (всего исправлений: 1)
Ответ на: комментарий от thunar

Мои резултаты:

Intel(R) Xeon(R) CPU E5-2690 0 @ 2.90GHz

gfortran -О2 и rand():

0.18697099
0.18797201

gfortran без О2 и rand():

0.21796601
0.66289997

gfortran -О2 и random_number(R):

0.18697099
0.18797201

gfortran без О2 и random_number(R):

0.21796601
0.66289997

ifort -O2 и random_number(R) (второе число меняется от запуска к запуску, но не сильно):

0.2949550
0.2619600
ifort без O2 и random_number(R) (второе число меняется от запуска к запуску, но не сильно):
0.2949550
0.2739580

Rakot ★★
()
Ответ на: комментарий от buddhist

ага, тут похоже, то что нужно.

thunar ★★★★★
() автор топика
Ответ на: комментарий от Rakot

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

thunar ★★★★★
() автор топика

А почему бы наоборот не сделать, построив таблицу N → X?

Ее, кстати, можно заранее с нормальной точностью в double'ах вычислить, округлить до float и сохранить.

Anon
()
Ответ на: комментарий от thunar

А почему не разложить 1.1^N в ряд Тейлора, и заранее не посчитать некоторое число членов ряда для 1.1. Потом только складывать?
Ну хоть проверить что получится.

vada ★★★★★
()
Ответ на: комментарий от thunar

А что код до этого без оптимизаций запускался? Я бы ещё посоветовал внимание обратить на ekopath.

Rakot ★★
()
19 декабря 2014 г.
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.