Daniele Cono D'Elia edited case-study.tex  over 8 years ago

Commit id: fbc1f2da4d69f87fc23cdee1bf409bee39813614

deletions | additions      

       

A previous study by Lameed and Hendren~\cite{lameed2013feval} shows that the overhead of an \feval\ call is significantly high compared to a direct call, especially in JIT-based execution environments such as McVM and the proprietary MATLAB JIT accelerator by Mathworks. In fact, the presence of an \feval\ instruction can disrupt the results of intra- and inter-procedural level for type and array shape inference analyses, which are key factors for efficient code generation.  Lameed and Hendren thus propose and implement in McVM two dynamic techniques for optimizing \feval\ instructions. The first one is based on OSR: using the McOSR library~\cite{lameed2013modular}, \feval\ calls inside loops are instrumented with an OSR point and profiling code to cache the last-known types for the arguments of each \feval\ instruction. When an OSR is fired at run-time, a code generator modifies the original function by inserting a guard to choose between a fast path containing a direct call and a slow path with the original \feval\ call. The second technique is less general and uses value-based JIT compilation: when the first argument of an \feval\ call is an argument of the enclosing function, the compiler replaces each call to this function in all of its callers with a call to a special dispatcher. When the program is executed, At run-time,  the dispatcher will evaluate evaluates  the value of the parameter argument to use  for the \feval\ and execute executes  either a previously compiled cached code or generate generates  and JIT-compile JIT-compiles  a method version of the function  optimized for the current value of the argument. value.  Although the OSR-based approach is more general, it generates much less efficient code compared to the JIT-based version one  for three reasons: \begin{enumerate}  \item since the function called through \feval\ is unknown at compile time, the type inference engine is unable to infer types for the returned values, so the compiler has to generate generic instructions (suitable for handling different types) for the remainder of the code;  \item guard computation is expensive, because not only the value of the first argument, but also the types of the remaining arguments have to be checked to choose between the fast and the slow path;  \item since an \feval\ is executed through the interpreter,in the original functions  arguments are boxed to make them more generic before the call. \end{enumerate}  The first one in particular is a major source of inefficiency for the OSR-based approach, since the benefits from replacing the call to the interpreter's \feval\ dispatcher with a direct call are limited compared to the optimization opportunities deriving from a better type inference on the whole body of the function. In fact, as they operate on boxed values, instructions operating on for  generic-type variables are inherently much less efficient than their counterparts for [arrays of] primitive types. While the JIT-based approach is preferable as it generates much better code, on the other hand it cannot be applied to cases in which the first argument $f$ to \feval\ is not passed as argument to the enclosing function $g$. Some possible scenarios for MATLAB programs  are: \begin{itemize}  \item $f$ is an {\tt inline} or an anonymous function defined in $g$;  \item $f$ is the return value from a previous call in $g$ to another function;  %\item $f$ is retrieved from a data structure~\cite{lameed2013feval};  \item $f$ is a constant string containing the name of a user-defined function (a typical inappropriate use misuse  of \feval\ according to~\cite{radpour2013refactoring}). \feval ~\cite{radpour2013refactoring}).  \end{itemize}    Lameed and Hendren conclude their paper by stating, ``It would be interesting to look at future work that combine the