While the performance and energy benefits of heterogeneous computing
are now well established, the
adoption of heterogeneous computing has still been slow in many
domains that can benefit significantly from the use of accelerators.
The primary reason for this is the high complexity of developing and
maintaining software
for heterogeneous systems.

The two leading programming models for heterogeneous computing, OpenCL~\cite{OPENCL} and CUDA~\cite{cuda},
give software developers fine-grain control over
the hardware platform, transfer of data, and execution of kernels. The verbosity of the OpenCL and CUDA APIs
allows HPC specialists to use advanced, hardware-specific tuning techniques. However, this fine-grained 
control is a double-edged sword and adds a non-trivial amount of application code to write, maintain, and optimize across 
multiple architectures. While OpenCL offers functional portability, it
is often the case that different OpenCL variants of the same kernel
have to be written to obtain the best performance on different hardware devices.

% Max: Discussing OpenACC here is a little clumsy, since we never mention CUDA before. I may
% have been the one to originally write this paragraph but I'm suggesting we cut it.
As a result, much attention has been given to using OpenCL and CUDA 
as foundations for higher level programming models. For instance, consider OpenACC~\cite{OPENACC}.
OpenACC uses OpenMP-like
compiler directives to identify parallel regions of code that should be offloaded to an accelerator. It supports
a number of directives related to data motion and kernel execution, but is only accessible from C and Fortran, two
low-level languages. Additionally, while OpenACC minimizes the code changes required to add heterogeneity to a program,
it also reduces the control a programmer has in optimizing that heterogeneous execution, reduces the flexibility
of the system for arbitrary kernels, and hides a number of important features from the application developer which
often impact performance significantly.

On the other hand, using high-level managed languages, such as Java, often has 
many benefits. These benefits include a high-level syntax,
massive library support, and garbage collection. However, the performance of 
an application can often suffer when interpreted,
garbage-collected languages are used. Using heterogeneous systems to 
accelerate applications in these high-level languages
is also a difficult and error-prone task. Accessing OpenCL's C/C++ API from 
Java requires the use of the Java Native Interface (JNI)
API, immediately removing many of the programmability benefits of Java software development.

In this work, we use language features of the Habanero-Java (HJ)~\cite{hj-pppj11} parallel programming language to
support implicit heterogeneous execution from the JVM using OpenCL.
Habanero-Java with OpenCL generation (HJ-OpenCL) is an extension to the 
parallel Habanero Java programming language which enables execution of parallel
\hjforall{} loops on any heterogeneous processor in an OpenCL platform without any code change to the original HJ source. 
In addition, the programmer may use the \nextOp{} language construct for all-to-all barrier synchronization, and the
\safe{} language construct to preserve Java exception semantics.
These extensions do not interfere with existing HJ constructs for
other types of parallelism, such as asynchronous tasks, futures and
actors, but are
instead intended to complement them.
As a result, an application can be written entirely in the high-level HJ programming language and take advantage of existing Java libraries, 
frameworks, and tools while accelerating computationally-intensive parallel loops using the multi-threaded HJ runtime or many-threaded OpenCL kernels.
The main contributions of this work include:

\begin{enumerate}
\item
Auto-utilization of multi-core CPUs and many-core GPUs using OpenCL
from the Habanero-Java language, while maintaining Java exception
semantics with the  \safe{} construct introduced in this paper.

\item
Auto-generation of bridge code between the JVM and OpenCL. This includes OpenCL device discovery, OpenCL
platform initialization, data movement between the JVM and OpenCL devices, OpenCL kernel execution, and barrier synchronization within kernels.

\item
Auto-generation of OpenCL kernels from Java bytecode with extensions
to the APARAPI~\cite{APARAPI} open-source translation framework.

\item
Performance evaluation of HJ-OpenCL on multiple heterogeneous platforms with performance comparison between sequential Java,
sequential HJ, multi-threaded HJ, and HJ-OpenCL on multi-core CPUs and many-core GPUs.
\end{enumerate}
