% -*- latex -*-

\chapter{General Approach}
\label{chap:GeneralApproach}

\VTKm is designed to provide a \keyterm{pervasive parallelism}\index{pervasive parallelism} throughout all its visualization algorithms, meaning that the algorithm is designed to operate with independent concurrency at the finest possible level throughout.
\VTKm provides this pervasive parallelism by providing a programming construct called a \index{worklet}\keyterm{worklet}, which operates on a very fine granularity of data.
The worklets are designed as serial components, and \VTKm handles whatever layers of concurrency are necessary, thereby removing the onus from the visualization algorithm developer.
Worklet operation is then wrapped into \index{filter}\keyterm{filters}, which provide a simplified interface to end users.

A worklet is essentially a functor\index{functor} or kernel\index{kernel} designed to operate on a small element of data.
(The name ``worklet'' means a small amount of the work.
We mean small in this sense to be the amount of data, not necessarily the amount of instructions performed.)
The worklet is constrained to contain a serial and stateless function.
These constraints form three critical purposes.
First, the constraints on the worklets allow \VTKm to schedule worklet invocations on a great many independent concurrent threads and thereby making the algorithm pervasively parallel.
Second, the constraints allow \VTKm to provide thread safety.
By controlling the memory access the toolkit can insure that no worklet will have any memory collisions, false sharing, or other parallel programming pitfalls.
Third, the constraints encourage good programming practices.
The worklet model provides a natural approach to visualization algorithm design that also has good general performance characteristics.

\VTKm allows developers to design algorithms that are run on massive amounts of threads.
However, \VTKm also allows developers to interface to applications, define data, and invoke algorithms that they have written or are provided otherwise.
These two modes represent significantly different operations on the data.
The operating code of an algorithm in a worklet is constrained to access only a small portion of data that is provided by the framework.
Conversely, code that is building the data structures needs to manage the data in its entirety, but has little reason to perform computations on any particular element.

Consequently, \VTKm is divided into two \keyterm{environments}\index{environment} that handle each of these use cases.
Each environment has its own API, and direct interaction between the environments is disallowed.
The environments are as follows.

\begin{description}
\item[Execution Environment] \index{execution environment} \index{environment!execution}
  This is the environment in which the computational portion of algorithms are executed.
  The API for this environment provides work for one element with convenient access to information such as connectivity and neighborhood as needed by typical visualization algorithms.
  Code for the execution environment is designed to always execute on a very large number of threads.
\item[Control Environment] \index{control environment} \index{environment!control}
  This is the environment that is used to interface with applications, interface with I/O devices, and schedule parallel execution of the algorithms.
  The associated API is designed for users that want to use \VTKm to analyze their data using provided or supplied filters.
  Code for the control environment is designed to run on a single thread (or one single thread per process in an MPI job).
\end{description}

These dual programming environments are partially a convenience to isolate
the application from the execution of the worklets and are partially a
necessity to support GPU languages with host and device environments. The
control and execution environments are logically equivalent to the host and
device environments, respectively, in CUDA and other associated GPU
languages.

\begin{figure}[htb]
  \centering
  \includegraphics[width=4in]{images/VTKmEnvironments}
  \caption{Diagram of the \VTKm framework.}
  \label{fig:VTKmDiagram}
\end{figure}

Figure~\ref{fig:VTKmDiagram} displays the relationship between the control
and execution environment. The typical workflow when using \VTKm is that
first the control thread establishes a data set in the control environment
and then invokes a parallel operation on the data using a filter. From
there the data is logically divided into its constituent elements, which
are sent to independent invocations of a worklet. The worklet
invocations, being independent, are run on as many concurrent threads as
are supported by the device. On completion the results of the worklet
invocations are collected to a single data structure and a handle is
returned back to the control environment.

\begin{didyouknow}
  Are you only planning to use filters in \VTKm that already exist? If so,
  then everything you work with will be in the control environment. The
  execution environment is only used when implementing algorithms for
  filters.
\end{didyouknow}


\section{Package Structure}
\label{sec:PackageStructure}

\index{packages|(}

\VTKm is organized in a hierarchy of nested packages. \VTKm places
definitions in \keyterm{namespaces}\index{namespace} that correspond to
the package (with the exception that one package may specialize a template
defined in a different namespace).

The base package is named \vtkm{}. All classes within \VTKm are placed
either directly in the \vtkm{} package or in a package beneath it. This
helps prevent name collisions between \VTKm and any other library.

As described at the beginning of this chapter, the \VTKm API is divided into two distinct environments\index{environment}: the control environment\index{control environment}\index{environment!control} and the execution environment\index{execution environment}\index{environment!execution}.
The API for these two environments are located in the \vtkmcont{} and \vtkmexec{} packages, respectively.
Items located in the base \vtkm{} namespace are available in both environments.

Although it is conventional to spell out names in identifiers,\footnote{\index{coding conventions}\VTKm coding conventions are outlined in the \textfilename{doc/CodingConventions.md} file in the \VTKm source code and at \url{https://gitlab.kitware.com/vtk/vtk-m/blob/master/docs/CodingConventions.md}} there is an exception to abbreviate control and execution to \textnamespace{cont} and \textnamespace{exec}, respectively.
This is because it is also part of the coding convention to declare the entire namespace when using an identifier that is part of the corresponding package.
The shorter names make the identifiers easier to read, faster to type, and more feasible to pack lines in 80 column displays.
These abbreviations are also used instead of more common abbreviations (e.g.
ctrl for control) because, as part of actual English words, they are easier to type.

Further functionality in \VTKm is built on top of the base \vtkm{},
\vtkmcont{}, and \vtkmexec{} packages. Support classes for building
worklets, introduced in Chapter \ref{chap:SimpleWorklets}, are contained in the
\vtkmworklet{} package. Other facilities in \VTKm are provided in their own
packages such as \vtkmio{}, \vtkmfilter{}, and \vtkmrendering{}. These
packages are described in Part~\ref{part:Using}.

\VTKm contains code that uses specialized compiler features, such as those
with CUDA, or libraries, such as Intel Threading Building Blocks, that will
not be available on all machines. Code for these features are encapsulated
in their own packages under the \vtkmcont{} namespace: \vtkmcontcuda{} and
\vtkmconttbb{}.

\VTKm contains OpenGL interoperability \index{OpenGL}
\index{interoperability} that allows data generated with \VTKm to be
efficiently transferred to OpenGL objects. This feature is encapsulated in
the \vtkmopengl{} package.

Figure~\ref{fig:Packages} provides a diagram of the \VTKm package hierarchy.

\begin{figure}[htb]
  \centering
  %% \begin{itemize}
  %% \item \vtkm{}
  %% \item \vtkmexec{}
  %% \item \vtkmcont{}
  %% \item \vtkmcontcuda{}
  %% \item \vtkmcontopenmp{}
  %% \item \vtkmcontserial{}
  %% \item \vtkmconttbb{}
  %% \item \vtkmio{}
  %% \item \vtkmioreader{}
  %% \item \vtkmiowriter{}
  %% \item \vtkmfilter{}
  %% \item \vtkmrendering{}
  %% \item \vtkmworklet{}
  %% \end{itemize}
  \includegraphics{images/PackageHierarchy}
  \caption{\VTKm package hierarchy.}
  \label{fig:Packages}
\end{figure}

By convention all classes will be defined in a file with the same name as
the class name (with a \textfilename{.h} extension) located in a directory
corresponding to the package name. For example, the \vtkmcont{DataSet}
class is found in the \vtkmheader{vtkm/cont}{DataSet.h} header. There
are, however, exceptions to this rule. Some smaller classes and types are
grouped together for convenience. These exceptions will be noted as
necessary.

Within each namespace there may also
be \namespace{internal} and \namespace{detail}
sub-namespaces. The \namespace{internal} namespaces contain features
that are used internally and may change without
notice. The \namespace{detail} namespaces contain features that are
used by a particular class but must be declared outside of that
class. Users should generally ignore classes in these namespaces.

\index{packages|)}


\section{Function and Method Environment Modifiers}
\label{sec:FunctionAndMethodEnvironmentModifiers}

Any function or method defined by \VTKm must come with a modifier that determines in which environments the function may be run.
These modifiers are C macros that \VTKm uses to instruct the compiler for which architectures to compile each method.
Most user code outside of \VTKm need not use these macros with the important exception of any classes passed to \VTKm.
This occurs when defining new worklets, array storage, and device adapters.

\VTKm provides three modifier macros, \vtkmcontmodifier, \vtkmexecmodifier, and
\vtkmexeccontmodifier, which are used to declare functions and methods that
can run in the control environment, execution environment, and both
environments, respectively. These macros get defined by including just
about any \VTKm header file, but including \vtkmheader{vtkm}{Types.h} will
ensure they are defined. 

The modifier macro is placed after the template declaration, if there is one,
and before the return type for the function. Here is a simple example of a
function that will square a value. Since most types you would use this
function on have operators in both the control and execution environments,
the function is declared for both places.

\vtkmlisting{Usage of an environment modifier macro on a function.}{EnvironmentModifierMacro.cxx}

The primary function of the modifier macros is to inject compiler-specific
keywords that specify what architecture to compile code for. For example,
when compiling with CUDA\index{CUDA}, the control modifiers have
\textcode{\_\_host\_\_}\index{\_\_host\_\_} in them and execution modifiers
have \textcode{\_\_device\_\_}\index{\_\_device\_\_} in them.

It is sometimes the case that a function declared as
\vtkmexeccontmodifier has to call a method declared as \vtkmexecmodifier or
\vtkmcontmodifier. Generally functions should not call other functions with
incompatible control/execution modifiers, but sometimes a generic
\vtkmexeccontmodifier function calls another function determined by the
template parameters, and the valid environments of this subfunction may be
inconsistent. For cases like this, you can use the
\vtkmmacro{VTKM\_SUPPRESS\_EXEC\_WARNINGS} to tell the compiler to ignore the
inconsistency when resolving the template. When applied to a templated
function or method, \vtkmmacro{VTKM\_SUPPRESS\_EXEC\_WARNINGS} is placed
before the \textcode{template} keyword. When applied to a non-templated
method in a templated class, \vtkmmacro{VTKM\_SUPPRESS\_EXEC\_WARNINGS} is
placed before the environment modifier macro.

\vtkmlisting{Suppressing warnings about functions from mixed environments.}{SuppressExecWarnings.cxx}
