Skip to content

Thread Safety of ForwardDiff.GradientConfig #573

Closed
@gideonsimpson

Description

@gideonsimpson

So I'm not sure if it was intended to be, but I'm finding that if I generate a configuration as

cfg = ForwardDiff.GradientConfig(...)

and then use this in defining a gradient with ForwardDiff.gradient!, the resultant object is not thread safe. If I omit the cfg (and take an associated performance hit), everything works as expected.

EDIT: This shows the problem. On my laptop with 4 threads, I get a disagreement in the results:

using ForwardDiff
using Random
using Printf
using LinearAlgebra

n = 10^6;

function f(x)
    return x[1]^2
end

cfg = ForwardDiff.GradientConfig(f, zeros(Float64, 1));
∇f1 = x -> ForwardDiff.gradient(f, x, cfg);
∇f2 = x -> ForwardDiff.gradient(f, x);

Random.seed!(100);

x = randn(n);

results_single = zeros(n);
results_thread_v1 = zeros(n);
results_thread_v2 = zeros(n);

for j in 1:n
    results_single[j] = ∇f1([x[j]])[1]
end

Threads.@threads for j in 1:n
    results_thread_v1[j] = ∇f1([x[j]])[1]
end

Threads.@threads for j in 1:n
    results_thread_v2[j] = ∇f2([x[j]])[1]
end

@show norm(results_single .- results_thread_v1);
@show norm(results_single .- results_thread_v2);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions