function accfun = dlaccelerate(fun)
%DLACCELERATE  Optimize deep learning function
%   ACCFUN = DLACCELERATE(FUN) creates an AcceleratedFunction object that
%   retains the underlying traces of the specified function handle FUN.
% 
%   Use DLACCELERATE to speed up deep learning gradient and model
%   computations. The returned AcceleratedFunction object stores the traces
%   of underlying function calls and reuses the cached result when the same
%   input pattern reoccurs.
%
%   Try using DLACCELERATE for function calls that:
%    - are long-running.
%    - have dlarray or dlnetwork inputs
%    - do not have side effects like writing to files or displaying output
%    - do not depend on external factors like global variables or
%      randomness (with the exception of using rand(sz, 'like', dlX) where 
%      dlX is a traced dlarray object).
%
%   A trace depends on the function inputs and outputs:
%     - For dlarray inputs, the trace depends on the size, format, and
%       underlying datatype of the dlarray.
%     - For dlnetwork inputs, the trace depends on the size, format, and
%       underlying datatype of the dlnetwork state and learnable parameters.
%     - For other inputs, the trace depends on the values of the input.
%     - The trace depends on the number of outputs.
%  
%   For more information refer to deep.AcceleratedFunction.
%
%   Example 1:
%     Create a function that defines the computation of interest and the
%     point at which to evaluate the function.
%       function [y,grad] = objectiveAndGradient(x)
%           y = x(1).^2 + x(2) - 2;
%           grad = dlgradient(y,x);
%       end
%       a = dlarray([0 0]);
%     Create an AcceleratedFunction object and use dlfeval with the
%     AcceleratedFunction object.
%       accfun = dlaccelerate(@objectiveAndGradient);
%       [val,grad] = dlfeval(accfun,a);
%
%   Example 2:
%     To cache traces of a function named modelGradients when using a
%     custom training loop, create an AcceleratedFunction object before
%     starting training.
%       accfun = dlaccelerate(@modelGradients);
%     To evaluate the model gradients function using trace caching, use
%     the dlfeval function with the AcceleratedFunction object.
%       gradients = dlfeval(accfun, dlnet, dlX, T);
%
%   See also: DLFEVAL, deep.AcceleratedFunction, MEMOIZE
 
% Copyright 2020-2022 The MathWorks, Inc.

arguments
    fun function_handle
end
narginchk(0,1)
nargoutchk(0,1);

% Using singleton class AcceleratedFunctionManager to track all handles created through this
% interface.
manager = deep.internal.AcceleratedFunctionManager.getInstance();

accfun  = manager.getAcceleratedFunction(fun);
end

