diff --git a/DifferentiationInterface/docs/src/explanation/operators.md b/DifferentiationInterface/docs/src/explanation/operators.md index 2629df5d2..6ca844ae5 100644 --- a/DifferentiationInterface/docs/src/explanation/operators.md +++ b/DifferentiationInterface/docs/src/explanation/operators.md @@ -117,6 +117,7 @@ op(f, prep, backend, x, [t]) # fast because it skips preparation !!! warning The `prep` object is the last argument before `backend` and it is always mutated, regardless of the bang `!` in the operator name. + As a consequence, preparation is **not thread-safe** and sharing `prep` objects between threads may lead to unexpected behavior. If you need to run differentiation concurrently, prepare separate `prep` objects for each thread. ### Reusing preparation diff --git a/DifferentiationInterface/src/docstrings.jl b/DifferentiationInterface/src/docstrings.jl index 6e22c2f1c..ff3359884 100644 --- a/DifferentiationInterface/src/docstrings.jl +++ b/DifferentiationInterface/src/docstrings.jl @@ -26,6 +26,9 @@ function docstring_prepare(operator; samepoint=false, inplace=false) Otherwise, preparation becomes invalid and you need to run it again. In some settings, invalid preparations may still give correct results (e.g. for backends that require no preparation), but this is not a semantic guarantee and should not be relied upon. + !!! danger + The preparation result `prep` is **not thread-safe**. Sharing it between threads may lead to unexpected behavior. If you need to run differentiation concurrently, prepare separate `prep` objects for each thread. + When `strict=Val(true)` (the default), type checking is enforced between preparation and execution (but size checking is left to the user). While your code may work for different types by setting `strict=Val(false)`, this is not guaranteed by the API and can break without warning. """