Dynamic Compilation
Functions used to compile on demand the Kokkos functions needed.
This mechanism allows to create new methods without degrading performance (after method invalidation).
Only functions operating on views are dynamically compiled, the rest are compiled with the wrapper library.
Compilation is not thread-safe and must be done by a single process (and single thread) at once. This is ensured by compilation_lock
.
Kokkos.DynamicCompilation.@compile_and_call
— Macro@compile_and_call(method, args, compile)
If has_specialization(method, args)
then invoke method
, otherwise compile
is executed. In both cases, method
is invoked through Base.invokelatest
.
This handles the following case:
function my_method(@nospecialize(x))
return @compile_and_call(my_method, x, begin #= ... =# end)
end
function my_program(x)
my_method(x) # Will compile
my_method(x)
end
Here the second invocation of my_method
is still done in the same world in which my_program
was invoked, even though the first invocation increased the global world counter. Therefore, we need to ensure method
has not been specialized in the latest world before trying to compile.
Kokkos.DynamicCompilation.compile_and_load
— Functioncompile_and_load(current_module, cmake_target; kwargs...)
Check if the library of cmake_target
compiled with kwargs
exists, if not compile it, then load it.
The library is a CxxWrap module, which is then loaded into current_module
in the sub-module Impl<number>
with '<number>' the total count of calls to compile_and_load
in this Julia session.
Kokkos.DynamicCompilation.has_specialization
— Functionhas_specialization(func, args_t::Tuple{Vararg{Type}})
True if the most specific method of func
applicable to args_t
has no @nospecialize
annotation on any argument.
Kokkos.DynamicCompilation.call_more_specific
— Functioncall_more_specific(func, args)
Call func
with args
with Base.invokelatest(func, args...)
, but only if there is a specialized method for the arguments (an error is raised otherwise).
After calling compile_and_load
from a @nospecialize
method meant to define a new method specialized for args
, this function will prevent infinite recursion if the new method is not applicable to args
.
Kokkos.DynamicCompilation.clean_libs
— Functionclean_libs()
Remove all shared libraries generated for compilation on demand of some methods or types.
Libraries are not unloaded, therefore subsequent calls to compile_and_load
might not trigger recompilation.
Kokkos.DynamicCompilation.compilation_lock
— Functioncompilation_lock(func)
Asserts that only a single process (and single thread) is compiling at once.
By default, there is only a lock on tasks of the current process.
If MPI.jl
is loaded, a PID lock file is also used (see FileWatching.Pidfile, or Pidfile.jl before 1.9). Lock files have the advantage that no collective MPI operations are needed, however they only work if all MPI ranks share the same filesystem, and if this is not the case then there is no need for lock files. This can be overloaded with the JULIA_KOKKOS_USE_COMPILATION_LOCK_FILE
environment variable.
Note that it is not the current process' ID that is used in the PID lock file, since PID are not guaranteed to be unique in a MPI application. Instead a random 32-bit number is used, constant for this process.