Джулия, абсолютно новичок здесь с вопросом для вас.
Я учу себя немного Джулии, портируя некоторые из моих кодов Mathematica и Python (в основном научные c вычисления в физике и c и посмотреть что к чему. До сих пор все было довольно гладко. И быстро. До сих пор.
Теперь я моделирую элементарный блокировочный усилитель, который, по сути, принимает - возможно, очень сложный - зависящий от времени сигнал Uin(t)
и выдает выходной сигнал * 1006. *, фазовая автоподстройка в некоторой опорной частоте fref
(то есть, она подчеркивает компонент Uin(t)
, который имеет определенное фазовое соотношение с синусоидальной волной эталонной). Мало что имеет значение в описании, имеет значение , что это в основном делает это путем вычисления интеграла (я на самом деле опускаю фазу здесь для ясности):
Итак, я изложил и протестировал это в Mathematica и Julia: я определяю макет Uin(t)
, передаю некоторые значения параметров, а затем создаю массив Uout(t)
в момент t = 0
, для диапазона fref
.
Юлия: Я использовал пакет QuadGK для числовой интеграции.
T = 0.1
f = 100.
Uin(t) = sin(2pi * f * t) + sin(2pi * 2f *t)
Uout(t, fref)::Float64 = quadgk(s -> Uin(s) * sin(2pi * fref * s), t-T, t, rtol=1E-3)[1]/T
frng = 80.:1.:120.
print(@time broadcast(Uout, 0., frng))
Mathematica
T = 0.1;
f = 100.;
Uin[t_] := Sin[2 π f t] + Sin[2 π 2 f t]
Uout[t_, fref_] := NIntegrate[Sin[2 π fref s] Uin[s], {s, t - T, t}]/T
frng = Table[i, {i, 80, 120, 1}];
Timing[Table[Uout[0, fr], {fr, frng}]]
Результаты:
Джулия рассчитывала эту операцию где-то между 45 и 55 секундами на ноутбуке i7-5xxx от батареи, что составляет много , тогда как Mathematica делала это за ~ 2 секунды. Разница ужасна и, честно говоря, в это трудно поверить. Я знаю, что Mathematica имеет несколько довольно приятных и изящных алгоритмов в своем ядре, но Джулия - это Джулия. Итак, вопрос: что дает?
PS: установка f
и T
как const
уменьшает время Джулии до ~ 8-10 секунд, но f
и T
не может быть const
с в реальной программе. Кроме этого, есть ли что-то очевидное, что я упускаю?
РЕДАКТИРОВАТЬ 2 февраля 2020:
Замедление, по-видимому, связано с алгоритму, пытающемуся выследить точность, когда значение близко к нулю, например, см. ниже: для fref = 95 вычисление занимает 1 целую секунду (!), в то время как для смежных значений частоты оно вычисляется мгновенно (возвращаемый результат является кортежем ( res, ошибка)). Кажется, что функция quadgk останавливается при очень малых значениях):
0.000124 seconds (320 allocations: 7.047 KiB)
fref = 94.0 (-0.08637214864144352, 9.21712218998258e-6)
1.016830 seconds (6.67 M allocations: 139.071 MiB, 14.35% gc time)
fref = 95.0 (-6.088184966010742e-16, 1.046186419361636e-16)
0.000124 seconds (280 allocations: 6.297 KiB)
fref = 96.0 (0.1254003757465191, 0.00010132083518769636)
Примечания: это независимо от того, какой допуск я хочу получить. Кроме того, Mathematica, как правило, задает допуски точности станка по умолчанию, в то же время несколько замедляя работу при приближении к нулям, и numpy / scipy просто пролетают через все это, но дают менее точные результаты, чем Mathematica (при настройках по умолчанию; в этом не особо разбирались ).