Если вы посмотрите на http://www.juliadiff.org/ForwardDiff.jl/latest/user/limitations.html, вы найдете:
Целевая функция должна быть написана достаточно обобщенно, чтобы принимать числа типа T <: Real в качестве входных данных (или массивы этих чисел) (...) Это также означает, что любое назначенное хранилище, используемое в функции, также должно быть универсальным . </p>
с примером здесь https://github.com/JuliaDiff/ForwardDiff.jl/issues/136#issuecomment-237941790.
Это означает, что вы можете сделать что-то вроде этого:
function test()
function objective(value)
for i=1:1_000_000
A[i] = value[1]
end
return sum(A)
end
A = zeros(ForwardDiff.Dual{ForwardDiff.Tag{typeof(objective), Float64},Float64,1}, 1_000_000)
ForwardDiff.gradient(objective, [1.0])
end
Но я бы не предположил, что это сэкономит вам много ресурсов, так как тип нестабилен.
Что вы можете сделать, это обернуть objective
и A
в модуль, подобный этому:
using ForwardDiff
module Obj
using ForwardDiff
function objective(value)
for i=1:1_000_000
A[i] = value[1]
end
return sum(A)
end
const A = zeros(ForwardDiff.Dual{ForwardDiff.Tag{typeof(objective), Float64},Float64,1}, 1_000_000)
end
А теперь вот это:
ForwardDiff.gradient(Obj.objective, [1.0])
должно быть быстро.
EDIT
Также это работает (хотя это нестабильный тип, но в менее проблемном месте):
function test()::Vector{Float64}
function objective(A, value)
for i=1:1_000_000
A[i] = value[1]
end
return sum(A)
end
helper_objective = v -> objective(A, v)
A = Vector{ForwardDiff.Dual{ForwardDiff.Tag{typeof(helper_objective), Float64},Float64,1}}(undef, 1_000_000)
ForwardDiff.gradient(helper_objective, [1.0])
end