<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//NLM//DTD Journal Publishing with OASIS Tables v3.0 20080202//EN" "journalpub-oasis3.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:oasis="http://docs.oasis-open.org/ns/oasis-exchange/table" dtd-version="3.0">
  <front>
    <journal-meta>
<journal-id journal-id-type="publisher">GMD</journal-id>
<journal-title-group>
<journal-title>Geoscientific Model Development</journal-title>
<abbrev-journal-title abbrev-type="publisher">GMD</abbrev-journal-title>
<abbrev-journal-title abbrev-type="nlm-ta">Geosci. Model Dev.</abbrev-journal-title>
</journal-title-group>
<issn pub-type="epub">1991-9603</issn>
<publisher><publisher-name>Copernicus GmbH</publisher-name>
<publisher-loc>Göttingen, Germany</publisher-loc>
</publisher>
</journal-meta>

    <article-meta>
      <article-id pub-id-type="doi">10.5194/gmd-8-2815-2015</article-id><title-group><article-title>POM.gpu-v1.0: a GPU-based Princeton Ocean Model</article-title>
      </title-group><?xmltex \runningtitle{POM.gpu-v1.0}?><?xmltex \runningauthor{X.~Huang~et~al.}?>
      <contrib-group>
        <contrib contrib-type="author" corresp="no" rid="aff1">
          <name><surname>Xu</surname><given-names>S.</given-names></name>
          
        </contrib>
        <contrib contrib-type="author" corresp="yes" rid="aff1">
          <name><surname>Huang</surname><given-names>X.</given-names></name>
          <email>hxm@tsinghua.edu.cn</email>
        </contrib>
        <contrib contrib-type="author" corresp="no" rid="aff2 aff3">
          <name><surname>Oey</surname><given-names>L.-Y.</given-names></name>
          
        </contrib>
        <contrib contrib-type="author" corresp="no" rid="aff1">
          <name><surname>Xu</surname><given-names>F.</given-names></name>
          
        </contrib>
        <contrib contrib-type="author" corresp="no" rid="aff1">
          <name><surname>Fu</surname><given-names>H.</given-names></name>
          
        </contrib>
        <contrib contrib-type="author" corresp="no" rid="aff1">
          <name><surname>Zhang</surname><given-names>Y.</given-names></name>
          
        </contrib>
        <contrib contrib-type="author" corresp="no" rid="aff1">
          <name><surname>Yang</surname><given-names>G.</given-names></name>
          
        </contrib>
        <aff id="aff1"><label>1</label><institution>Ministry of Education Key Laboratory for Earth System Modeling, Center
for Earth System Science, Tsinghua University, 100084, and Joint Center for Global Change Studies, Beijing, 100875, China</institution>
        </aff>
        <aff id="aff2"><label>2</label><institution>Institute of Hydrological &amp; Oceanic Sciences, National Central University, Jhongli, Taiwan</institution>
        </aff>
        <aff id="aff3"><label>3</label><institution>Program in Atmospheric &amp; Oceanic Sciences, Princeton University, Princeton, New Jersey, USA</institution>
        </aff>
      </contrib-group>
      <author-notes><corresp id="corr1">X. Huang (hxm@tsinghua.edu.cn)</corresp></author-notes><pub-date><day>9</day><month>September</month><year>2015</year></pub-date>
      
      <volume>8</volume>
      <issue>9</issue>
      <fpage>2815</fpage><lpage>2827</lpage>
      <history>
        <date date-type="received"><day>13</day><month>October</month><year>2014</year></date>
           <date date-type="rev-request"><day>17</day><month>November</month><year>2014</year></date>
           <date date-type="rev-recd"><day>10</day><month>August</month><year>2015</year></date>
           <date date-type="accepted"><day>19</day><month>August</month><year>2015</year></date>
      </history>
      <permissions>
<license license-type="open-access">
<license-p>This work is licensed under a Creative Commons Attribution 3.0 Unported License. To view a copy of this license, visit <ext-link ext-link-type="uri" xlink:href="http://creativecommons.org/licenses/by/3.0/">http://creativecommons.org/licenses/by/3.0/</ext-link></license-p>
</license>
</permissions><self-uri xlink:href="https://gmd.copernicus.org/articles/8/2815/2015/gmd-8-2815-2015.html">This article is available from https://gmd.copernicus.org/articles/8/2815/2015/gmd-8-2815-2015.html</self-uri>
<self-uri xlink:href="https://gmd.copernicus.org/articles/8/2815/2015/gmd-8-2815-2015.pdf">The full text article is available as a PDF file from https://gmd.copernicus.org/articles/8/2815/2015/gmd-8-2815-2015.pdf</self-uri>


      <abstract>
    <p>Graphics processing units (GPUs) are an attractive solution in many
scientific applications due to their high performance. However, most existing
GPU conversions of climate models use GPUs for only a few computationally
intensive regions. In the present study, we redesign the mpiPOM (a parallel
version of the Princeton Ocean Model) with GPUs. Specifically, we first
convert the model from its original Fortran form to a new Compute Unified
Device Architecture C (CUDA-C) code, then we optimize the code on each of the
GPUs, the communications between the GPUs, and the I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O between the GPUs
and the central processing units (CPUs). We show that the performance of the
new model on a workstation containing four GPUs is comparable to that on a
powerful cluster with 408 standard CPU cores, and it reduces the energy
consumption by a factor of 6.8.</p>
  </abstract>
    </article-meta>
  </front>
<body>
      

<sec id="Ch1.S1" sec-type="intro">
  <title>Introduction</title>
      <p>High-resolution atmospheric, oceanic and climate modellings remain
significant scientific and engineering challenges because of the enormous
computing, communication, and storage requirements involved. Due to the rapid
development of computer architecture, in particular the development of
multi-core and many-core hardware, the computing power that can be applied to
scientific problems has increased exponentially in recent decades. Parallel
computing methods, such as the Message Passing Interface (MPI,
<xref ref-type="bibr" rid="bib1.bibx12" id="altparen.1"/>) and Open Multi-Processing (OpenMP,
<xref ref-type="bibr" rid="bib1.bibx7" id="altparen.2"/>), have been widely used to support the
parallelization of climate models. However, supercomputers are becoming
increasingly heterogeneous, involving devices such as the GPU and the Intel
Many Integrated Core (Intel MIC), and new approaches are required to
effectively utilize the new hardware.</p>

<?xmltex \floatpos{t}?><table-wrap id="Ch1.T1" specific-use="star"><caption><p>Existing GPU porting work in climate fields. The
speedups are normalized to one CPU core.</p></caption><oasis:table frame="topbot"><oasis:tgroup cols="4">
     <oasis:colspec colnum="1" colname="col1" align="left"/>
     <oasis:colspec colnum="2" colname="col2" align="left"/>
     <oasis:colspec colnum="3" colname="col3" align="left"/>
     <oasis:colspec colnum="4" colname="col4" align="center"/>
     <oasis:thead>
       <oasis:row rowsep="1">  
         <oasis:entry colname="col1">Model name</oasis:entry>  
         <oasis:entry colname="col2">Model description</oasis:entry>  
         <oasis:entry colname="col3">Porting modules to GPU</oasis:entry>  
         <oasis:entry colname="col4">Speedup</oasis:entry>
       </oasis:row>
     </oasis:thead>
     <oasis:tbody>
       <oasis:row>  
         <oasis:entry colname="col1">WRF</oasis:entry>  
         <oasis:entry colname="col2">Weather Research and Forecasting</oasis:entry>  
         <oasis:entry colname="col3">WSM5 microphysics</oasis:entry>  
         <oasis:entry colname="col4">8</oasis:entry>
       </oasis:row>
       <oasis:row>  
         <oasis:entry colname="col1">WRF-Chem</oasis:entry>  
         <oasis:entry colname="col2">WRF chemical</oasis:entry>  
         <oasis:entry colname="col3">Chemical kinetics kernel</oasis:entry>  
         <oasis:entry colname="col4">8.5</oasis:entry>
       </oasis:row>
       <oasis:row>  
         <oasis:entry colname="col1">POP</oasis:entry>  
         <oasis:entry colname="col2">Parallel Ocean Program</oasis:entry>  
         <oasis:entry colname="col3">Loop structures</oasis:entry>  
         <oasis:entry colname="col4">2.2</oasis:entry>
       </oasis:row>
       <oasis:row>  
         <oasis:entry colname="col1">COSMO</oasis:entry>  
         <oasis:entry colname="col2">Consortium for Small-scale Modeling</oasis:entry>  
         <oasis:entry colname="col3">Dynamical core</oasis:entry>  
         <oasis:entry colname="col4">22.7</oasis:entry>
       </oasis:row>
       <oasis:row>  
         <oasis:entry colname="col1">NIM</oasis:entry>  
         <oasis:entry colname="col2">Nonhydrostatic Icosahedral Model</oasis:entry>  
         <oasis:entry colname="col3">Dynamical core</oasis:entry>  
         <oasis:entry colname="col4">34</oasis:entry>
       </oasis:row>
       <oasis:row>  
         <oasis:entry colname="col1">ASUCA</oasis:entry>  
         <oasis:entry colname="col2">Nonhydrostatic weather model</oasis:entry>  
         <oasis:entry colname="col3">Dynamical core and physical</oasis:entry>  
         <oasis:entry colname="col4">80</oasis:entry>
       </oasis:row>
     </oasis:tbody>
   </oasis:tgroup></oasis:table></table-wrap>

      <p>In recent years, a number of scientific codes have been ported to the GPU as
shown in Table <xref ref-type="table" rid="Ch1.T1"/>. Most existing GPU acceleration codes for
climate models are only operating on certain hot spots of the program,
leaving a significant portion of the program still running on CPUs. The speed
of some subroutines reported in the Weather Research and Forecast (WRF)
<xref ref-type="bibr" rid="bib1.bibx28" id="paren.3"/> and WRF-Chem <xref ref-type="bibr" rid="bib1.bibx25" id="paren.4"/> is improved
by a factor of approximately 8, whereas the whole model achieves limited
speedup because of partial porting. The speed of POP
<xref ref-type="bibr" rid="bib1.bibx57" id="paren.5"/> is improved by a factor of only 2.2 because the
model only accelerated a number of loop structures using the OpenACC
Application Programming Interface (OpenACC API). The speed of COSMO
<xref ref-type="bibr" rid="bib1.bibx23" id="paren.6"/>, NIM <xref ref-type="bibr" rid="bib1.bibx11" id="paren.7"/> and ASUCA
<xref ref-type="bibr" rid="bib1.bibx42" id="paren.8"/> are greatly improved by multiple GPUs. We believe
that the elaborate optimization of the memory access of each GPU and the
communication between GPUs can further accelerate these models.</p>
      <p>The objective of our study was to shorten the computation time of the
Princeton Ocean Model (POM) by parallelizing its existing model structures
using the GPU. Taking the parallel version of the Princeton Ocean Model
(mpiPOM), we demonstrate how to code an ocean model so that it runs
efficiently on GPU architecture. We first convert the mpiPOM from its
original Fortran version into a new Compute Unified Device Architecture C
(CUDA-C) version, POM.gpu-v1.0. CUDA-C is the dominant programming language
for GPUs. We then optimize the code on each of the GPUs, the communications
between the GPUs, and the I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O between GPUs and the CPUs to further
improve the performance of POM.gpu.</p>
      <p>To understand the accuracy, performance and scalability of the POM.gpu code,
we customized a workstation with four Nvidia K20X GPUs. The results show that
the performance of POM.gpu running on this workstation is comparable to that
on a powerful cluster with 408 standard CPU cores.</p>
      <p>This paper is organized as follows. In Sect. <xref ref-type="sec" rid="Ch1.S2"/>, we review
the mpiPOM model. In Sect. <xref ref-type="sec" rid="Ch1.S3"/>, we briefly introduce the GPU
computing model. In Sect. <xref ref-type="sec" rid="Ch1.S4"/>, we present the detailed
optimization techniques. In Sect. <xref ref-type="sec" rid="Ch1.S5"/>, we report on the
correctness, performance and scalability of the model. We present the code
availability in Sect. <xref ref-type="sec" rid="Ch1.S6"/> and conclude our work in Sect. <xref ref-type="sec" rid="Ch1.S7"/>.</p>
</sec>
<sec id="Ch1.S2">
  <title>The mpiPOM</title>
      <p>The mpiPOM is a parallel version of the POM. It retains most of the physics
of the original POM <xref ref-type="bibr" rid="bib1.bibx3 bib1.bibx4 bib1.bibx38 bib1.bibx39 bib1.bibx40 bib1.bibx36 bib1.bibx37" id="paren.9"/> and
includes satellite and drifter assimilation schemes from the Princeton
Regional Ocean Forecast System <xref ref-type="bibr" rid="bib1.bibx34 bib1.bibx24 bib1.bibx54" id="paren.10"/>, stokes drift and wave-enhanced mixing <xref ref-type="bibr" rid="bib1.bibx33 bib1.bibx52 bib1.bibx50" id="paren.11"/>. The POM code was reorganized and the parallel
MPI version was implemented by <xref ref-type="bibr" rid="bib1.bibx18" id="text.12"/> using a two-dimensional
data decomposition of the horizontal domain. The MPI is a standard library
for message passing and is widely used to develop parallel programs. The POM
is a powerful ocean model that has been used in a wide range of applications:
circulation and mixing processes in rivers, estuaries, shelves, slopes,
lakes, semi-enclosed seas and open and global oceans. It is also at the core
of various real-time ocean and hurricane forecasting systems, e.g. the
Japanese coastal ocean and Kuroshio current <xref ref-type="bibr" rid="bib1.bibx29 bib1.bibx17 bib1.bibx47" id="paren.13"/>, the Adriatic Sea Forecasting
System <xref ref-type="bibr" rid="bib1.bibx56" id="paren.14"/>, the
Mediterranean Sea forecasting system <xref ref-type="bibr" rid="bib1.bibx20" id="paren.15"/>, the GFDL
Hurricane Prediction System
<xref ref-type="bibr" rid="bib1.bibx21 bib1.bibx22" id="paren.16"/>, the US Hurricane
Forecasting System <xref ref-type="bibr" rid="bib1.bibx9 bib1.bibx10" id="paren.17"/>, and the Advanced Taiwan Ocean Prediction (ATOP)
system <xref ref-type="bibr" rid="bib1.bibx33" id="paren.18"/>. Additionally, the model has been used to study
various geophysical fluid dynamical processes (e.g.
<xref ref-type="bibr" rid="bib1.bibx1 bib1.bibx30 bib1.bibx31 bib1.bibx19 bib1.bibx13 bib1.bibx41 bib1.bibx55 bib1.bibx8 bib1.bibx34 bib1.bibx49 bib1.bibx50 bib1.bibx51 bib1.bibx6 bib1.bibx15 bib1.bibx45 bib1.bibx46" id="altparen.19"/>). For a more complete list, please visit the
POM website (<uri>http://www.ccpo.odu.edu/POMWEB</uri>).</p>
      <p>The mpiPOM experiment used in this paper is one of two that were designed and
tested by Professor Oey and students; the codes and results are freely
available at the FTP site
(<uri>ftp://profs.princeton.edu/leo/mpipom/atop/tests/</uri>). The reader can
refer to Chapter 3 of the lecture notes <xref ref-type="bibr" rid="bib1.bibx35" id="paren.20"/> for more detail.
The test case is a dam-break problem in which warm and cold waters are
initially separated in the middle of a zonally periodic channel
(200 km <inline-formula><mml:math display="inline"><mml:mo>×</mml:mo></mml:math></inline-formula> 50 km <inline-formula><mml:math display="inline"><mml:mo>×</mml:mo></mml:math></inline-formula> 50 m) on an f-plane, with walls at the
northern and southern boundaries. Geostrophic adjustment then ensues and
baroclinic instability waves amplify and develop into finite-amplitude eddies
in 10<inline-formula><mml:math display="inline"><mml:mo>∼</mml:mo></mml:math></inline-formula>20 days. The horizontal grid sizes are 1 km and there are 50
vertical sigma levels. Although the problem is a test case, the code is the
full mpiPOM version used in the ATOP forecasting system.</p>
      <p>The model solves the primitive equation under hydrostatic and Boussinesq
approximations. In the horizontal, spatial derivatives are computed either
using centered-space differencing or Smolarkiewicz's positive definite
advection transport algorithm <xref ref-type="bibr" rid="bib1.bibx44" id="paren.21"/> on a staggered
Arakawa C-grid; both schemes have been tested, but the latter is reported
here. In the vertical, the mpiPOM supports terrain-following sigma
coordinates and a fourth-order scheme option to reduce the internal
pressure-gradient errors <xref ref-type="bibr" rid="bib1.bibx2" id="paren.22"/>. The mpiPOM uses the
time-splitting technique to separate the vertically integrated equations
(external mode) from the vertical structure equations (internal mode). The
external mode calculation is responsible for updating the surface elevation
and vertically averaged velocities. The internal mode calculation updates the
velocity, temperature and salinity, as well as the turbulence quantities. The
three-dimensional internal mode and the two-dimensional external mode are
both integrated explicitly using a second-order leapfrog scheme. These two
modules are the most computationally intensive kernels of the mpiPOM model.</p>
      <p><?xmltex \hack{\newpage}?>The main computational problem of the mpiPOM is memory bandwidth limited. To
confirm this issue, we use the runtime performance API tool to estimate the
floating point operation count and the memory access instruction count, as in
<xref ref-type="bibr" rid="bib1.bibx5" id="normal.23"/>. The results reveal that the computational
intensity, defined as floating point operations per byte transferred to or
from memory, of the mpiPOM is approximately <inline-formula><mml:math display="inline"><mml:mrow><mml:mn mathvariant="normal">1</mml:mn><mml:mo>:</mml:mo><mml:mn>3.3</mml:mn></mml:mrow></mml:math></inline-formula>, whereas the
computational intensity provided by a modern high-performance CPU (an Intel
SandyBridge E5-2670) is <inline-formula><mml:math display="inline"><mml:mrow><mml:mn>7.5</mml:mn><mml:mo>:</mml:mo><mml:mn mathvariant="normal">1</mml:mn></mml:mrow></mml:math></inline-formula>. Many large arrays are mostly pulled from the
main memory and there is poor data reuse in the mpiPOM. In addition, there
are no obvious hot spot functions in the mpiPOM, and even the most
time-consuming subroutine occupies only 20 % of the total execution time.
Therefore, porting a handful of subroutines to the GPU is not helpful in
improving the model efficiency. This explains why we must port the entire
program from the CPU to the GPU.</p>
</sec>
<sec id="Ch1.S3">
  <title>GPU computing model overview</title>
      <p>Modern GPUs employ a stream-processing model with parallelism. Each GPU
contains a number of stream multiprocessors (SMs). In this work, we carried
out the conversion using four Nvidia K20X GPUs. Each K20X GPU contains
14 SMs and each SM has 192 single-precision processors and 64 additional
processors for double precision. Although the computational capability of
each processor is low, one GPU with thousands of processors can greatly boost
the performance compared to the CPU. In computing, FLOPS (FLoating-point
Operations Per Second) is a measure of computer performance. The theoretical
peak performance of each K20X GPU is 3.93 teraFLOPS (TFLOPS, one trillion
floating-point operations per second) for the single-precision floating-point
calculations. In contrast, a single Intel SandyBridge E5-2670 CPU is only
capable of 0.384 TFLOPS.</p>
      <p>Each pair of GPUs shares 6 Gigabytes (GB) of memory, with the interface
having a potential bandwidth of 250 GB s<inline-formula><mml:math display="inline"><mml:msup><mml:mi/><mml:mrow><mml:mo>-</mml:mo><mml:mn mathvariant="normal">1</mml:mn></mml:mrow></mml:msup></mml:math></inline-formula>.
Figure <xref ref-type="fig" rid="Ch1.F3"/> illustrates the memory hierarchy of
the K20X GPU. Each SM possesses some types of fast on-chip memory such as
register, L1 cache, shared memory and read-only data cache. In GPUs, the
register is the fastest memory, of which the size is 256 Kilobytes (KB) for
each SM. The shared memory and the L1 cache use the common 64 KB space,
which can be partitioned as 16/48 KB, 32/32 KB or 48/16 KB. The 48 KB
read-only data cache is useful for holding frequently used values that remain
unchanged during each stage of the processing.</p>
      <p>There are three widely used methods for porting a program to GPUs. The first
method uses drop-in libraries provided by CUDA to replace the existing code,
as in <xref ref-type="bibr" rid="bib1.bibx43" id="normal.24"/>. The second method uses the OpenACC
directive as hints in the original CPU code as in <xref ref-type="bibr" rid="bib1.bibx57" id="normal.25"/>.
The last method is the most complex but also the most effective; it involves
rewriting the entire program using low-level CUDA subroutines.</p>

      <?xmltex \floatpos{t}?><fig id="Ch1.F1"><caption><p>The hierarchy of stream, kernel,
block, warp and thread.</p></caption>
        <?xmltex \igopts{width=227.622047pt}?><graphic xlink:href="https://gmd.copernicus.org/articles/8/2815/2015/gmd-8-2815-2015-f01.pdf"/>

      </fig>

      <p>In CUDA terminology, a kernel is a single section of code or subroutine
running on the GPU. The underlying code in a kernel is split into a series of
threads, each of which deals with different data. These threads are grouped
into equal-size thread blocks that can be executed independently. A thread
block is further divided into warps as basic scheduled units. A warp consists
of 32 consecutive threads that execute the same instruction simultaneously.
Each kernel and data transfer command in CUDA has an optional parameter,
“stream ID”. If the stream ID is set in code, commands belonging to
different streams can be executed concurrently. A stream in CUDA is a
sequence of commands executed in order. Different streams can execute
concurrently with different priorities.
Figure <xref ref-type="fig" rid="Ch1.F1"/> illustrates the hierarchy of these
terms.</p>
      <p>At present, CUDA compilers are available for C and Fortran. Although
CUDA-Fortran has been available since 2009 and would involve less
modification of the mpiPOM code, we chose CUDA-C to convert the POM.gpu-v1.0
because of the following reasons: (1) CUDA-C is free of charge; (2) previous
work <xref ref-type="bibr" rid="bib1.bibx14" id="paren.26"/> has shown that the CUDA-Fortran compiler
did not perform as well as the CUDA-C version for some of the kernels during
the porting of NIM; (3) the read-only data cache is not supported by
CUDA-Fortran, which is the key optimization of Sect. <xref ref-type="sec" rid="Ch1.S4.SS1.SSS2"/>;
and (4) we have many previous optimization experiences with CUDA-C.</p><?xmltex \hack{\newpage}?>
</sec>
<sec id="Ch1.S4">
  <title>Full GPU acceleration of the mpiPOM</title>
      <p>Figure <xref ref-type="fig" rid="Ch1.F2"/> is a flowchart illustrating the structure of
the POM.gpu. The main difference between the mpiPOM and the POM.gpu is that
the CPU in the POM.gpu is only responsible for the initializing and the
output work. The POM.gpu begins by initializing the relevant arrays on the
CPU and then copies data from the CPU to the GPU. The GPU then performs all
of the model computations. Outputs such as velocity and sea-surface height
(SSH) are copied back to the CPU and are then written to the disk at a
user-specified time interval.</p>
      <p>In the following sections, we introduce the optimizations of the POM.gpu by
computation, communication and I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O aspects individually.</p>
      <p>For the individual GPUs, we concentrate on memory access optimization by
making better use of caches in the GPU memory hierarchy. This involves using
read-only data cache, local memory blocking, loop fusion and function fusion,
and disabling error-correcting code memory. The test results demonstrate that
a single GPU can run the model almost 100 times faster than a single CPU
core.</p>
      <p>In terms of communication, we overlapped the sending of boundary data between
the GPUs with the main computation. Data are also sent directly between the
GPUs, bypassing the CPU.</p>
      <p>In terms of I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O, we launched extra MPI processes on the main CPU to
output the data. These MPI processes are divided into two categories, the
computation processes and the I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O processes. The computation processes
are responsible for launching kernels into GPUs and the I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O processes
are responsible for copying data back from the GPUs and for writing to disks.
The computation processes and the I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O processes can execute
simultaneously to save output time.</p>

      <?xmltex \floatpos{t}?><fig id="Ch1.F2"><caption><p>POM.gpu flowchart.</p></caption>
        <?xmltex \igopts{width=227.622047pt}?><graphic xlink:href="https://gmd.copernicus.org/articles/8/2815/2015/gmd-8-2815-2015-f02.pdf"/>

      </fig>

<sec id="Ch1.S4.SS1">
  <title>Computational optimizations in a single GPU</title>

      <?xmltex \floatpos{t}?><fig id="Ch1.F3"><caption><p>The memory hierarchy of the K20X
GPU and the relationships with each optimization.</p></caption>
          <?xmltex \igopts{width=227.622047pt}?><graphic xlink:href="https://gmd.copernicus.org/articles/8/2815/2015/gmd-8-2815-2015-f03.pdf"/>

        </fig>

      <p>Managing the significant performance difference between global memory and
on-chip fast memory is the primary concern for GPU computing. The ratio of
bandwidth between global memory and shared memory is approximately <inline-formula><mml:math display="inline"><mml:mrow><mml:mn mathvariant="normal">1</mml:mn><mml:mo>:</mml:mo><mml:mn>10</mml:mn></mml:mrow></mml:math></inline-formula>.
Therefore, data reuse in an on-chip cache always needs to be seriously
considered. As shown on the right side of
Fig. <xref ref-type="fig" rid="Ch1.F3"/>, we propose two classes of
optimization, including the standard optimization of fusion and the special
optimization of the GPU, to better utilize the fast registers and caches.</p>
<sec id="Ch1.S4.SS1.SSS1">
  <title>Standard optimizations of fusion</title>
      <p>Fusion optimization in the POM.gpu code includes loop fusion and function
fusion. The loop fusion merges several loops into one loop and the function
fusion merges several subroutines into one subroutine.</p>
      <p>Loop fusion is an effective method to store scalar variables in registers for
data reuse. As shown in Fig. <xref ref-type="fig" rid="Ch1.F4"/>, if the variable
<italic>drhox(k, j, i)</italic> is read several times in multiple loops, we can fuse
these loops into one. Therefore, <italic>drhox(k, j, i)</italic> will first be read
from the global memory and then repeatedly read from a register. For
instance, for the <italic>profq</italic> kernel optimized with loop fusion, the
device memory transactions decrease by 57 %, and the running speed of this
kernel is improved by 28.6 %. The loop fusion optimization can also be
applied in a number of mpiPOM subroutines.</p>

      <?xmltex \floatpos{t}?><fig id="Ch1.F4" specific-use="star"><caption><p>A simple example of loop fusion.</p></caption>
            <?xmltex \igopts{width=384.112205pt}?><graphic xlink:href="https://gmd.copernicus.org/articles/8/2815/2015/gmd-8-2815-2015-f04.pdf"/>

          </fig>

      <p>Similar to loop fusion, we can also merge functions in which the same arrays
are accessed. For example, the <italic>advv</italic> and <italic>advu</italic> functions in
the mpiPOM code are used to calculate the advection terms in horizontal
directions, respectively. After merging them into one subroutine, the
redundant memory access is avoided. The function fusion can also be applied
in which one function is called several times to calculate different tracers.
The <italic>proft</italic> function in the mpiPOM code is called twice – one for
temperature and one for salinity. Their computing formulas are similar and
some common arrays are accessed. After function fusion, the running speed of
the <italic>proft</italic> kernel is improved by 28.8 %.</p>
</sec>
<sec id="Ch1.S4.SS1.SSS2">
  <title>Special optimizations of the GPU</title>
      <p>Our special optimizations mainly focus on the improved utilization of the
read-only data cache and the L1 cache on the GPU. It is useful to alleviate
the bottleneck of memory bandwidth that is limited by using these fast
on-chip caches.</p>
      <p>There is a 48 KB read-only data cache in the K20X GPU. We can automatically
use this as long as the read-only condition is met. In the POM.gpu, we simply
add const __restrict__ qualifiers into the parameter pointers to
explicitly direct the compiler to implement the optimization. As an example,
consider the calculations of advection and the horizontal diffusion terms.
Because mpiPOM adopts the Arakawa C-grid, in the horizontal plane, updating
the temperature (<inline-formula><mml:math display="inline"><mml:mi>T</mml:mi></mml:math></inline-formula>) requires the velocity of longitude (<inline-formula><mml:math display="inline"><mml:mi>u</mml:mi></mml:math></inline-formula>), the velocity
of latitude (<inline-formula><mml:math display="inline"><mml:mi>v</mml:mi></mml:math></inline-formula>) and the horizontal kinematic viscosity (<italic>aam</italic>) on
the neighbouring grid points. In one kernel, the <inline-formula><mml:math display="inline"><mml:mi>u</mml:mi></mml:math></inline-formula> and <inline-formula><mml:math display="inline"><mml:mi>v</mml:mi></mml:math></inline-formula> arrays are
accessed twice, and the <italic>aam</italic> array is accessed four times. After
using the read-only data cache to improve the data locality, the running
speed of this kernel is improved by 18.8 %.</p>
      <p><?xmltex \hack{\newpage}?>To reuse the data in each thread, we use local memory blocking to pull the
data from global memory to the L1 cache. In this method, a small subset of a
data set is loaded into the fast on-chip memory and then the small data block
is repeatedly accessed by the program. This method is helpful in reducing the
need to access the off-chip with high latency memory. In the subroutines of
the vertical diffusion and source/sink terms, the chasing method is used to
solve a tridiagonal matrix along the vertical direction for each grid point
individually. Each thread only accesses its own tiles of row transformation
coefficients. As shown in Fig. <xref ref-type="fig" rid="Ch1.F5"/>, the arrays
are accessed twice within one thread, one from the surface (<inline-formula><mml:math display="inline"><mml:mrow><mml:mi>k</mml:mi><mml:mo>=</mml:mo><mml:mn mathvariant="normal">0</mml:mn></mml:mrow></mml:math></inline-formula>) to the
bottom (<inline-formula><mml:math display="inline"><mml:mrow><mml:mi>k</mml:mi><mml:mo>=</mml:mo><mml:mi>n</mml:mi><mml:mi>z</mml:mi><mml:mo>-</mml:mo><mml:mn mathvariant="normal">1</mml:mn></mml:mrow></mml:math></inline-formula>) and another from the bottom (<inline-formula><mml:math display="inline"><mml:mrow><mml:mi>k</mml:mi><mml:mo>=</mml:mo><mml:mi>n</mml:mi><mml:mi>z</mml:mi><mml:mo>-</mml:mo><mml:mn mathvariant="normal">1</mml:mn></mml:mrow></mml:math></inline-formula>) to the surface
(<inline-formula><mml:math display="inline"><mml:mrow><mml:mi>k</mml:mi><mml:mo>=</mml:mo><mml:mn mathvariant="normal">0</mml:mn></mml:mrow></mml:math></inline-formula>). After blocking the vertical direction arrays in local memory, the L1
cache is fully utilized, and the running speed of these subroutines is
improved by 35.3 %.</p>

      <?xmltex \floatpos{t}?><fig id="Ch1.F5" specific-use="star"><caption><p>A simple example of local memory
blocking.</p></caption>
            <?xmltex \igopts{width=384.112205pt}?><graphic xlink:href="https://gmd.copernicus.org/articles/8/2815/2015/gmd-8-2815-2015-f05.pdf"/>

          </fig>

      <p>In the current implementation, as in the original mpiPOM code, the
three-dimensional arrays of variables are stored sequentially as east–west (<inline-formula><mml:math display="inline"><mml:mi>x</mml:mi></mml:math></inline-formula>),
north–south (<inline-formula><mml:math display="inline"><mml:mi>y</mml:mi></mml:math></inline-formula>), and vertical (<inline-formula><mml:math display="inline"><mml:mi>z</mml:mi></mml:math></inline-formula>), i.e. <inline-formula><mml:math display="inline"><mml:mrow><mml:mi>i</mml:mi><mml:mo>,</mml:mo><mml:mi>j</mml:mi><mml:mo>,</mml:mo><mml:mi>k</mml:mi></mml:mrow></mml:math></inline-formula> ordering.
Two-dimensional arrays are stored in <inline-formula><mml:math display="inline"><mml:mrow><mml:mi>i</mml:mi><mml:mo>,</mml:mo><mml:mi>j</mml:mi></mml:mrow></mml:math></inline-formula> ordering. The vertical diffusion
is solved using a tridiagonal solver that is calculated sequentially in the
<inline-formula><mml:math display="inline"><mml:mi>z</mml:mi></mml:math></inline-formula> direction. For simplicity, in our kernel functions the grid is divided
along <inline-formula><mml:math display="inline"><mml:mi>x</mml:mi></mml:math></inline-formula> and <inline-formula><mml:math display="inline"><mml:mi>y</mml:mi></mml:math></inline-formula>. Each GPU thread then specifies an <inline-formula><mml:math display="inline"><mml:mrow><mml:mo>(</mml:mo><mml:mi>x</mml:mi><mml:mo>,</mml:mo><mml:mi>y</mml:mi><mml:mo>)</mml:mo></mml:mrow></mml:math></inline-formula> point in the
horizontal direction and performs all of the calculations from the surface to
the bottom. The thread blocks are divided as <inline-formula><mml:math display="inline"><mml:mrow><mml:mn>32</mml:mn><mml:mo>×</mml:mo><mml:mn mathvariant="normal">4</mml:mn></mml:mrow></mml:math></inline-formula> subdomains in the
<inline-formula><mml:math display="inline"><mml:mi>x</mml:mi></mml:math></inline-formula>–<inline-formula><mml:math display="inline"><mml:mi>y</mml:mi></mml:math></inline-formula> plane. In the <inline-formula><mml:math display="inline"><mml:mi>x</mml:mi></mml:math></inline-formula> direction, the block number must be a multiple of
32 threads to perform consecutive and aligned memory access within a warp
<xref ref-type="bibr" rid="bib1.bibx32" id="paren.27"/>. In the <inline-formula><mml:math display="inline"><mml:mi>y</mml:mi></mml:math></inline-formula> direction, we tested many thread
numbers, such as 4 and 8, and obtained similar performances. We ultimately
choose 4 because this value produced more blocks and allowed us to distribute
the workload more uniformly amongst the SMs. In addition, 128 (<inline-formula><mml:math display="inline"><mml:mrow><mml:mo>=</mml:mo><mml:mn>32</mml:mn><mml:mo>×</mml:mo><mml:mn mathvariant="normal">4</mml:mn></mml:mrow></mml:math></inline-formula>) threads are enough to maintain the full occupancy, which is the number of
active threads in each multiprocessor.</p>
      <p>In GPU computing, one is free to choose which arrays will be stored in an
on-chip cache. Our experience involves putting the data along the horizontal
direction into the read-only cache to reuse among threads, and putting the
data along with vertical direction into the local memory for reuse within one
thread.</p>
      <p>Furthermore, we improve the global memory bandwidth by disabling the Error
Checking and memory Correcting (ECC-off), as well as enhancing the clock on
the GPU (GPU boost). This method improves the performance of the POM.gpu by
13.8 %.</p>
</sec>
<sec id="Ch1.S4.SS1.SSS3">
  <title>Results of the computational optimizations</title>
      <p>We divide all of the POM.gpu subroutines into three categories based on their
different computational patterns. As shown in Table <xref ref-type="table" rid="Ch1.T2"/>, in the
POM.gpu, we deploy different optimizations in these categories to improve the
performance of POM.gpu; these categories are described as follows.
<list list-type="order"><list-item>
      <p>Category 1: advection and horizontal diffusion (<inline-formula><mml:math display="inline"><mml:mrow><mml:mi>a</mml:mi><mml:mi>d</mml:mi><mml:mi>v</mml:mi></mml:mrow></mml:math></inline-formula>)</p>
      <p>This category has six subroutines, and calculates the advection, horizontal
diffusion and the pressure gradient and Coriolis terms in the case of
velocity. Here, it is possible to reuse data among adjacent threads, and the
subroutines therefore benefit from using the read-only data cache. At the
same time, the variables are calculated in different loops or in different
functions such that the loop fusion and function fusion optimizations are
applied to this part as well.</p></list-item><list-item>
      <p>Category 2: vertical diffusion (<italic>ver</italic>)</p>
      <p>This category has four subroutines and calculates the vertical diffusion. In
this part, the chasing method is used in the tridiagonal solver in the
<inline-formula><mml:math display="inline"><mml:mi>k</mml:mi></mml:math></inline-formula> direction. The main feature is that the data are accessed twice within
one thread, once from the surface to the bottom and again from the bottom to
the surface. The subroutines are significantly sped up after grouping the
<inline-formula><mml:math display="inline"><mml:mi>k</mml:mi></mml:math></inline-formula>-direction variable in the local memories.
<?xmltex \hack{\newpage}?></p></list-item><list-item>
      <p>Category 3: vorticity (<italic>vort</italic>), baroclinicity (<italic>baro</italic>), continuity
equation (<italic>cont</italic>) and equation of state (<italic>state</italic>)</p>
      <p>This category is less time-consuming than the two categories described above,
but it also benefits from our optimizations. Because data reuse exists among
threads, the use of a read-only data cache improves data locality. For the
<italic>vort</italic> subroutine, there is data reuse within one thread, and thus the
loop fusion improves the data locality.</p></list-item></list></p>

<?xmltex \floatpos{t}?><table-wrap id="Ch1.T2" specific-use="star"><caption><p>Different subroutines adopt different optimizations
in the POM.gpu.</p></caption><oasis:table frame="topbot"><oasis:tgroup cols="8">
     <oasis:colspec colnum="1" colname="col1" align="left"/>
     <oasis:colspec colnum="2" colname="col2" align="center"/>
     <oasis:colspec colnum="3" colname="col3" align="center"/>
     <oasis:colspec colnum="4" colname="col4" align="center"/>
     <oasis:colspec colnum="5" colname="col5" align="center"/>
     <oasis:colspec colnum="6" colname="col6" align="center"/>
     <oasis:colspec colnum="7" colname="col7" align="center"/>
     <oasis:colspec colnum="8" colname="col8" align="left"/>
     <oasis:thead>
       <oasis:row>  
         <oasis:entry colname="col1">Subroutines</oasis:entry>  
         <oasis:entry colname="col2">Loop</oasis:entry>  
         <oasis:entry colname="col3">Function</oasis:entry>  
         <oasis:entry colname="col4">Read-only</oasis:entry>  
         <oasis:entry colname="col5">Local memory</oasis:entry>  
         <oasis:entry colname="col6">ECC-off and</oasis:entry>  
         <oasis:entry colname="col7">Speedup</oasis:entry>  
         <oasis:entry colname="col8"/>
       </oasis:row>
       <oasis:row rowsep="1">  
         <oasis:entry colname="col1"/>  
         <oasis:entry colname="col2">fusion</oasis:entry>  
         <oasis:entry colname="col3">fusion</oasis:entry>  
         <oasis:entry colname="col4">data cache</oasis:entry>  
         <oasis:entry colname="col5">blocking</oasis:entry>  
         <oasis:entry colname="col6">GPU boost</oasis:entry>  
         <oasis:entry colname="col7"/>  
         <oasis:entry colname="col8"/>
       </oasis:row>
     </oasis:thead>
     <oasis:tbody>
       <oasis:row>  
         <oasis:entry colname="col1">Adv. and hor. diff.</oasis:entry>  
         <oasis:entry colname="col2"><inline-formula><mml:math display="inline"><mml:mo>√</mml:mo></mml:math></inline-formula></oasis:entry>  
         <oasis:entry colname="col3"><inline-formula><mml:math display="inline"><mml:mo>√</mml:mo></mml:math></inline-formula></oasis:entry>  
         <oasis:entry colname="col4"><inline-formula><mml:math display="inline"><mml:mo>√</mml:mo></mml:math></inline-formula></oasis:entry>  
         <oasis:entry colname="col5"/>  
         <oasis:entry colname="col6"><inline-formula><mml:math display="inline"><mml:mo>√</mml:mo></mml:math></inline-formula></oasis:entry>  
         <oasis:entry colname="col7">2.05X</oasis:entry>  
         <oasis:entry colname="col8"/>
       </oasis:row>
       <oasis:row>  
         <oasis:entry colname="col1">Ver. diff.</oasis:entry>  
         <oasis:entry colname="col2"><inline-formula><mml:math display="inline"><mml:mo>√</mml:mo></mml:math></inline-formula></oasis:entry>  
         <oasis:entry colname="col3"><inline-formula><mml:math display="inline"><mml:mo>√</mml:mo></mml:math></inline-formula></oasis:entry>  
         <oasis:entry colname="col4"/>  
         <oasis:entry colname="col5"><inline-formula><mml:math display="inline"><mml:mo>√</mml:mo></mml:math></inline-formula></oasis:entry>  
         <oasis:entry colname="col6"><inline-formula><mml:math display="inline"><mml:mo>√</mml:mo></mml:math></inline-formula></oasis:entry>  
         <oasis:entry colname="col7">2.82X</oasis:entry>  
         <oasis:entry colname="col8"/>
       </oasis:row>
       <oasis:row>  
         <oasis:entry colname="col1">Baroclinicity</oasis:entry>  
         <oasis:entry colname="col2"><inline-formula><mml:math display="inline"><mml:mo>√</mml:mo></mml:math></inline-formula></oasis:entry>  
         <oasis:entry colname="col3"/>  
         <oasis:entry colname="col4"><inline-formula><mml:math display="inline"><mml:mo>√</mml:mo></mml:math></inline-formula></oasis:entry>  
         <oasis:entry colname="col5"/>  
         <oasis:entry colname="col6"><inline-formula><mml:math display="inline"><mml:mo>√</mml:mo></mml:math></inline-formula></oasis:entry>  
         <oasis:entry colname="col7">2.08X</oasis:entry>  
         <oasis:entry colname="col8"/>
       </oasis:row>
       <oasis:row>  
         <oasis:entry colname="col1">Continuity equation</oasis:entry>  
         <oasis:entry colname="col2"/>  
         <oasis:entry colname="col3"/>  
         <oasis:entry colname="col4"><inline-formula><mml:math display="inline"><mml:mo>√</mml:mo></mml:math></inline-formula></oasis:entry>  
         <oasis:entry colname="col5"/>  
         <oasis:entry colname="col6"><inline-formula><mml:math display="inline"><mml:mo>√</mml:mo></mml:math></inline-formula></oasis:entry>  
         <oasis:entry colname="col7">1.39X</oasis:entry>  
         <oasis:entry colname="col8"/>
       </oasis:row>
       <oasis:row>  
         <oasis:entry colname="col1">Vorticity</oasis:entry>  
         <oasis:entry colname="col2"><inline-formula><mml:math display="inline"><mml:mo>√</mml:mo></mml:math></inline-formula></oasis:entry>  
         <oasis:entry colname="col3"/>  
         <oasis:entry colname="col4"><inline-formula><mml:math display="inline"><mml:mo>√</mml:mo></mml:math></inline-formula></oasis:entry>  
         <oasis:entry colname="col5"/>  
         <oasis:entry colname="col6"><inline-formula><mml:math display="inline"><mml:mo>√</mml:mo></mml:math></inline-formula></oasis:entry>  
         <oasis:entry colname="col7">3.19X</oasis:entry>  
         <oasis:entry colname="col8"/>
       </oasis:row>
       <oasis:row>  
         <oasis:entry colname="col1">State equation</oasis:entry>  
         <oasis:entry colname="col2"/>  
         <oasis:entry colname="col3"/>  
         <oasis:entry colname="col4"><inline-formula><mml:math display="inline"><mml:mo>√</mml:mo></mml:math></inline-formula></oasis:entry>  
         <oasis:entry colname="col5"/>  
         <oasis:entry colname="col6"><inline-formula><mml:math display="inline"><mml:mo>√</mml:mo></mml:math></inline-formula></oasis:entry>  
         <oasis:entry colname="col7">1.35X</oasis:entry>  
         <oasis:entry colname="col8"/>
       </oasis:row>
     </oasis:tbody>
   </oasis:tgroup></oasis:table></table-wrap>

</sec>
</sec>
<sec id="Ch1.S4.SS2">
  <title>Communication optimizations among multiple GPUs</title>
      <p>In this section, we present the optimizing strategies for multiple GPUs. In
the mpiPOM, the entire domain is split along the horizontal directions and
each MPI process is responsible for the model's computation of one subdomain,
following <xref ref-type="bibr" rid="bib1.bibx18" id="normal.28"/>. In the POM.gpu, we attach one MPI process to
one GPU and move the complete computation to the GPU. The MPI process is in
charge of the computation within each subdomain and of the data transfer
between the GPU and the main memory. The data transfer between subdomains is
handled by the GPUs directly. <xref ref-type="bibr" rid="bib1.bibx42" id="normal.29"/> and
<xref ref-type="bibr" rid="bib1.bibx53" id="normal.30"/> proposed fine-grained overlapping methods of GPU
computation and CPU communication to improve the computing performance. An
important issue in their work is that the communications between multiple
GPUs explicitly require the participation of the CPU. In our current work, we
simply bypass the CPU in implementing the communication to fully exploit the
capability of the GPUs.</p>
      <p>At present, two MPI libraries, OpenMPI and MVAPICH2, provide support for the
direct communication from the GPU to the main memory. This capability is
referred to as CUDA-aware MPI. We attempted to use MVAPICH2 to implement
direct communication among multiple GPUs. However, we found that inter-domain
communication occupied nearly 18 % of the total runtime.</p>

      <?xmltex \floatpos{t}?><fig id="Ch1.F6"><caption><p>Data decomposition in the POM.gpu.</p></caption>
          <?xmltex \igopts{width=236.157874pt}?><graphic xlink:href="https://gmd.copernicus.org/articles/8/2815/2015/gmd-8-2815-2015-f06.pdf"/>

        </fig>

      <?xmltex \floatpos{t}?><fig id="Ch1.F7" specific-use="star"><caption><p>The workflow of multiple streams on the
GPU. The Inner/East/West/North/South regions and Halo refer to the
computation and update of the corresponding region. Comm. refers to the
communication between processes, which implies synchronization.</p></caption>
          <?xmltex \igopts{width=341.433071pt}?><graphic xlink:href="https://gmd.copernicus.org/articles/8/2815/2015/gmd-8-2815-2015-f07.pdf"/>

        </fig>

      <p>Instead, to fully overlap the boundary operations and MPI communications with
computation, we adopt the data decomposition method shown in
Fig. <xref ref-type="fig" rid="Ch1.F6"/>. The data region is decomposed into
three regions: the inner region, the outer region, and a halo region which
exchanges data with its neighbours. In our design, the inner region, which is
the most time-consuming, is allocated to stream 1. The East/West outer region
is allocated to stream 2 and the North/South outer region is allocated to
stream 3. In the East/West outer region, the width is set to 32 to ensure
consecutive and aligned memory access in a warp. All of the halo regions are
also allocated to stream 2.</p>
      <p>The workflow of multiple streams on the GPU is shown in
Fig. <xref ref-type="fig" rid="Ch1.F7"/>. The East, West, North and South regions are
common kernel functions that can run in parallel with the inner region
through different streams. The communication operations between domains are
implemented by an asynchronous CUDA memory copy. The corresponding
synchronization operations between the CPU and the GPU or between the MPI
processes are implemented by a synchronization CUDA function and a MPI
barrier function. To overlap the subsequent communication with the inner
region, stream 2 and stream 3 for the outer region have higher priority in
preempting the computing resource from stream 1 at any time. Based on this
workflow, the inter-domain communication is overlapped with the computation.
The experimental results show that our design can remove the communication
overhead taken by MVAPICH2.</p>
</sec>
<sec id="Ch1.S4.SS3">
  <?xmltex \opttitle{I\,$/$\,O optimizations between the GPUs and the CPUs}?><title>I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O optimizations between the GPUs and the CPUs</title>
      <p>The time consumed for I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O in the mpiPOM is not significant. However,
after we fully accelerate the model by GPU, it accounts for approximately
30 % of the total runtime. The computing phase and the I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O phase are
serial, which means that the GPU will remain idle until the CPU finishes the
I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O operations. Motivated by previous work on I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O overlapping
<xref ref-type="bibr" rid="bib1.bibx16" id="paren.31"/>, we designed a similar method following computations on
a GPU and I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O operations on a CPU to run in parallel.</p>
      <p>In the POM.gpu, we chose to launch more MPI processes. The MPI processes are
divided into computing processes and I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O processes with different MPI
communicators. The computing processes are responsible for launching kernel
functions as usual, and the I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O processes are responsible for output.
One I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O process attaches to one computing process and these two
processes set their contexts on the same GPU.</p>
      <p><?xmltex \hack{\newpage}?>Because the I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O processes must fetch data from the GPU, communication
is necessary between them. The I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O processes obtain the device buffer
pointers from the computing processes during the initialization phase. When
writing history files, the computing processes are blocked and remain idle
for a short time, waiting for I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O processes to fetch data. Then, the
computing processes continue their computation, and the I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O processes
complete their output in the background, as illustrated in
Fig. <xref ref-type="fig" rid="Ch1.F8"/>. This method can be further optimized by placing
the archive data in a set-aside buffer and carrying on the main calculation.
However, the method requires more memory, which is not abundant in current
K20X GPUs.</p>

      <?xmltex \floatpos{t}?><fig id="Ch1.F8" specific-use="star"><caption><p>One computing process and one I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O process both set their
contexts on the same GPU. During the data copy phase, the computing process
remains idle and the I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O process will copy data from the GPU to the CPU
through the <inline-formula><mml:math display="inline"><mml:mrow><mml:mi>c</mml:mi><mml:mi>u</mml:mi><mml:mi>d</mml:mi><mml:mi>a</mml:mi><mml:mi>M</mml:mi><mml:mi>e</mml:mi><mml:mi>m</mml:mi><mml:mi>c</mml:mi><mml:mi>p</mml:mi><mml:mi>y</mml:mi></mml:mrow></mml:math></inline-formula> function.</p></caption>
          <?xmltex \igopts{width=341.433071pt}?><graphic xlink:href="https://gmd.copernicus.org/articles/8/2815/2015/gmd-8-2815-2015-f08.pdf"/>

        </fig>

      <p>The advantage of this method is that it overlaps the I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O on the CPU
with the model calculation on the GPU. In serial I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O, the GPU computing
processes are blocked while data are sent to the CPU and written to disk. In
overlapping I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O, the computing processes only wait for the data to be
sent to the host. The bandwidth of data brought to the host is approximately
6 GB s<inline-formula><mml:math display="inline"><mml:msup><mml:mi/><mml:mrow><mml:mo>-</mml:mo><mml:mn mathvariant="normal">1</mml:mn></mml:mrow></mml:msup></mml:math></inline-formula>, but the output bandwidth to the disk is approximately
100 MB s<inline-formula><mml:math display="inline"><mml:msup><mml:mi/><mml:mrow><mml:mo>-</mml:mo><mml:mn mathvariant="normal">1</mml:mn></mml:mrow></mml:msup></mml:math></inline-formula>, as determined by the speed of the disk. Therefore, the
overlapping method significantly accelerates the entire application.</p>
</sec>
</sec>
<sec id="Ch1.S5">
  <title>Experiments</title>
      <p>In this section, we first describe the specification of our platform and
comparison methodology to validate the correctness of the POM.gpu.
Furthermore, we present the performance and scalability of the POM.gpu
compared with the mpiPOM.</p>
<sec id="Ch1.S5.SS1">
  <title>Platform setup</title>
      <p>The POM.gpu runs in a workstation consisting of two CPUs and four GPUs. The
CPUs are 2.6 GHz 8-core Intel SandyBridge E5-2670. The GPUs are Nvidia Tesla
K20X. The operating system is RedHat Enterprise Linux 6.3 <inline-formula><mml:math display="inline"><mml:mo>×</mml:mo></mml:math></inline-formula> 86_64.
All programs are complied with Intel compiler v14.0.1, CUDA 5.5 Toolkit,
Intel MPI Library v4.1.3 and MVAPICH2 v1.9.</p>
      <p>For comparison, the mpiPOM runs on the <inline-formula><mml:math display="inline"><mml:mrow><mml:mi>T</mml:mi><mml:mi>a</mml:mi><mml:mi>n</mml:mi><mml:mi>s</mml:mi><mml:mi>u</mml:mi><mml:mi>o</mml:mi><mml:mn>100</mml:mn></mml:mrow></mml:math></inline-formula> cluster at Tsinghua
University consisting of 740 nodes. Each node is equipped with two 2.93 GHz
6-core Intel Xeon X5670 CPUs and 32 GB of memory. The nodes are connected
through an InfiniBand network. The operating system
is RedHat Enterprise Linux 5.5 <inline-formula><mml:math display="inline"><mml:mo>×</mml:mo></mml:math></inline-formula> 86_64. Programs on this platform
are compiled with Intel compiler v11.1 and Intel MPI v4.0.2. The mpiPOM code
is compiled with its original compiler flags, i.e. “-O3 -fp-model precise”.</p>
</sec>
<sec id="Ch1.S5.SS2">
  <title>The test case and the verification of accuracy</title>
      <p>The “dam-break”
simulation <xref ref-type="bibr" rid="bib1.bibx35" id="paren.32"/> is conducted to verify the correctness and
test the performance and scalability of the POM.gpu. It is a baroclinic
instability problem that simulates flows produced by horizontal temperature
gradients. The model domain is configured as a straight channel with a
uniform depth of 50 m. Periodic boundary conditions are used in the
east–west direction, and the channel is closed in the north and south. Its
horizontal resolution is 1 km <inline-formula><mml:math display="inline"><mml:mo>×</mml:mo></mml:math></inline-formula> 1 km. The domain size of this test
case is 962 <inline-formula><mml:math display="inline"><mml:mo>×</mml:mo></mml:math></inline-formula> 722 horizontal grid points and <inline-formula><mml:math display="inline"><mml:mn>51</mml:mn></mml:math></inline-formula> vertical sigma
levels, which is limited by the capacity of one's GPU memory. Initially, the temperature in the
southern half of the channel is 15 and 25 <inline-formula><mml:math display="inline"><mml:msup><mml:mi/><mml:mo>∘</mml:mo></mml:msup></mml:math></inline-formula>C in the northern half.
The salinity is fixed at 35 psu. The fluid is then allowed to adjust. In the
first 3–5 days, geostrophic adjustments occur. Then, an unstable wave
develops due to baroclinic instability. Eventually, eddies are generated.
Figure <xref ref-type="fig" rid="Ch1.F9"/> shows the sea-surface height, sea-surface
temperature (SST), and currents after 39 days. The scales of the frontal wave
and eddies are determined by the Rossby radius of deformation. This dam-break
case uses a single-precision format.</p>

      <?xmltex \floatpos{p}?><fig id="Ch1.F9"><caption><p>The model results after 39 days of
simulation. For the top figure, the colour shading is the sea-surface height
(SSH), and vectors are ocean currents. For the bottom figure, the colour
shading is the sea-surface temperature (SST). Several warm and cold eddies
are generated in the middle of the domain where the SST gradient is largest;
their scales are determined by the Rossby radius of deformation.</p></caption>
          <?xmltex \igopts{width=241.848425pt}?><graphic xlink:href="https://gmd.copernicus.org/articles/8/2815/2015/gmd-8-2815-2015-f09.png"/>

        </fig>

      <p>To verify the accuracy, we check the binary output files of the mpiPOM and
the POM.gpu, as in <xref ref-type="bibr" rid="bib1.bibx26" id="normal.33"/>. The test results demonstrate that
the variables velocity, temperature, salinity and sea-surface height are all
identical.</p>
</sec>
<sec id="Ch1.S5.SS3">
  <title>Model performance</title>
      <p>To understand the advantages of the optimizations in Sect. <xref ref-type="sec" rid="Ch1.S4"/>,
we conducted different tests. The metrics of seconds per simulation day are
measured to compare the model performance.</p><?xmltex \hack{\newpage}?>
<sec id="Ch1.S5.SS3.SSS1">
  <title>Single GPU performance</title>
      <p>In our first test, we compare the performance of the mpiPOM using two
different CPUs, the Intel X5670 CPU (six cores) and the Intel E5-2670 CPU
(eight cores), with that obtained from the POM.gpu using one single GPU.
Figure <xref ref-type="fig" rid="Ch1.F10"/> shows that one K20X GPU can compete
with approximately 55 E5-2670 CPU cores to 95 X5670 CPU cores in the
simulation. From the parameters of the Intel E5-2670 CPU and Nvidia K20X GPU,
we find that the ratio of memory bandwidth and the ratio of floating points
performance are approximately <inline-formula><mml:math display="inline"><mml:mrow><mml:mn mathvariant="normal">1</mml:mn><mml:mo>:</mml:mo><mml:mn mathvariant="normal">5</mml:mn></mml:mrow></mml:math></inline-formula> and <inline-formula><mml:math display="inline"><mml:mrow><mml:mn mathvariant="normal">1</mml:mn><mml:mo>:</mml:mo><mml:mn>10</mml:mn></mml:mrow></mml:math></inline-formula>, respectively. This means, if
an application is strictly memory bandwidth limited, one GPU can compete with
5 CPUs; if an application is strictly computation limited, it can compete
with 10 CPUs. Since the mpiPOM is memory bandwidth limited, the POM.gpu
should provide an equivalent performance to the mpiPOM running on up to
<inline-formula><mml:math display="inline"><mml:mrow><mml:mn mathvariant="normal">5</mml:mn><mml:mo>×</mml:mo><mml:mn mathvariant="normal">8</mml:mn><mml:mo>=</mml:mo><mml:mn>40</mml:mn></mml:mrow></mml:math></inline-formula> CPU cores. Our procedure attempts to optimize memory access
and we can further increase this number to 55.</p>

      <?xmltex \floatpos{t}?><fig id="Ch1.F10"><caption><p>Performance comparison with
different hardware platforms.</p></caption>
            <?xmltex \igopts{width=236.157874pt}?><graphic xlink:href="https://gmd.copernicus.org/articles/8/2815/2015/gmd-8-2815-2015-f10.pdf"/>

          </fig>

<?xmltex \hack{\newpage}?>
</sec>
<sec id="Ch1.S5.SS3.SSS2">
  <title>Multiple GPU performance</title>
      <p>In the second test, we compare our communication overlapping method with the
MVAPICH2 library. Figure <xref ref-type="fig" rid="Ch1.F11"/> presents the weak scaling
performance on multiple GPUs, where the grid size for each GPU is kept at
<inline-formula><mml:math display="inline"><mml:mrow><mml:mn>962</mml:mn><mml:mo>×</mml:mo><mml:mn>722</mml:mn><mml:mo>×</mml:mo><mml:mn>51</mml:mn></mml:mrow></mml:math></inline-formula>. When four GPUs are used with MVAPICH2, approximately
18 % of the total runtime is consumed by inter-domain communication and
boundary operations. This overhead can be greatly reduced by our
communication overlapping method.</p>

      <?xmltex \floatpos{t}?><fig id="Ch1.F11"><caption><p>The weak scaling test between our
communication overlapping method and the MVAPICH2 subroutines.</p></caption>
            <?xmltex \igopts{width=236.157874pt}?><graphic xlink:href="https://gmd.copernicus.org/articles/8/2815/2015/gmd-8-2815-2015-f11.pdf"/>

          </fig>

      <p>In the third test, we fix the global grid size at <inline-formula><mml:math display="inline"><mml:mrow><mml:mn>962</mml:mn><mml:mo>×</mml:mo><mml:mn>722</mml:mn><mml:mo>×</mml:mo><mml:mn>51</mml:mn></mml:mrow></mml:math></inline-formula>, and
measure the strong scaling performance of POM.gpu.
Table <xref ref-type="table" rid="Ch1.T3"/> shows that the strong scaling efficiency is
99 % on two GPUs and 92 % on four GPUs. When more GPUs are used, the size
of each subdomain becomes smaller. This decreases the performance of POM.gpu
in two aspects. First, the communication overhead may exceed the computation
time of the inner region as the size of each subdomain decreases. As a
result, the overlapping methods in Sect. <xref ref-type="sec" rid="Ch1.S4.SS2"/> are not effective.
Second, there are many “small” kernels in the POM.gpu code, in which the
calculation is simple and less time-consuming. With fewer inner region
computations, the overhead of kernel launching and implicit synchronization
with kernel execution must be counted.</p>

<?xmltex \floatpos{t}?><table-wrap id="Ch1.T3"><caption><p>The strong scaling result of POM.gpu.</p></caption><oasis:table frame="topbot"><oasis:tgroup cols="4">
     <oasis:colspec colnum="1" colname="col1" align="center"/>
     <oasis:colspec colnum="2" colname="col2" align="center"/>
     <oasis:colspec colnum="3" colname="col3" align="center"/>
     <oasis:colspec colnum="4" colname="col4" align="center"/>
     <oasis:thead>
       <oasis:row rowsep="1">  
         <oasis:entry colname="col1">Number of GPUs</oasis:entry>  
         <oasis:entry colname="col2">1-GPU</oasis:entry>  
         <oasis:entry colname="col3">2-GPUs</oasis:entry>  
         <oasis:entry colname="col4">4-GPUs</oasis:entry>
       </oasis:row>
     </oasis:thead>
     <oasis:tbody>
       <oasis:row>  
         <oasis:entry colname="col1">Time (s)</oasis:entry>  
         <oasis:entry colname="col2">97.2</oasis:entry>  
         <oasis:entry colname="col3">48.7</oasis:entry>  
         <oasis:entry colname="col4">26.3</oasis:entry>
       </oasis:row>
       <oasis:row>  
         <oasis:entry colname="col1">Efficiency</oasis:entry>  
         <oasis:entry colname="col2">100 %</oasis:entry>  
         <oasis:entry colname="col3">99 %</oasis:entry>  
         <oasis:entry colname="col4">92 %</oasis:entry>
       </oasis:row>
     </oasis:tbody>
   </oasis:tgroup></oasis:table></table-wrap>

<?xmltex \hack{\newpage}?>
</sec>
<sec id="Ch1.S5.SS3.SSS3">
  <?xmltex \opttitle{I\,$/$\,O performance}?><title>I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O performance</title>
      <p>In the fourth test, we compare our I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O overlapping method with the
parallel NetCDF (PnetCDF) method and NO-I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O. NO-I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O means that
all I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O operations are disabled in the program and that the time
measured is the pure computing time. This simulation is run for 20 days, and
the history files are output daily. The final history files in NetCDF format
are approximately 12 GB. Figure <xref ref-type="fig" rid="Ch1.F12"/> shows that the
I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O overlapping method outperforms the PnetCDF method. For one and two
GPUs, the overall runtime decreases from 1694/1142 to 1239/688 s, which is
close to the NO-I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O. The extra overhead of our method compared with
NO-I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O involves the computing processes that need to be blocked until
the I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O processes obtain data from the GPUs. When running with four
GPUs, the output time exceeds the computation time. Then, the I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O phase
cannot be fully overlapped with the model computation phase. The overall
runtime equals the sum of the computation time and the non-overlapped
I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O time.</p>

      <?xmltex \floatpos{t}?><fig id="Ch1.F12"><caption><p>I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O test for the POM.gpu.</p></caption>
            <?xmltex \igopts{width=236.157874pt}?><graphic xlink:href="https://gmd.copernicus.org/articles/8/2815/2015/gmd-8-2815-2015-f12.pdf"/>

          </fig>

</sec>
<sec id="Ch1.S5.SS3.SSS4">
  <title>Comparison with a cluster</title>
      <p>In the last test, we compare the performance of POM.gpu on a workstation
containing four GPUs with that on the <inline-formula><mml:math display="inline"><mml:mrow><mml:mi>T</mml:mi><mml:mi>a</mml:mi><mml:mi>n</mml:mi><mml:mi>s</mml:mi><mml:mi>u</mml:mi><mml:mi>o</mml:mi><mml:mn>100</mml:mn></mml:mrow></mml:math></inline-formula> cluster. Three different
high-resolution grids (Grid-1: <inline-formula><mml:math display="inline"><mml:mrow><mml:mn>962</mml:mn><mml:mo>×</mml:mo><mml:mn>722</mml:mn><mml:mo>×</mml:mo><mml:mn>51</mml:mn></mml:mrow></mml:math></inline-formula>; Grid-2:
<inline-formula><mml:math display="inline"><mml:mrow><mml:mn>1922</mml:mn><mml:mo>×</mml:mo><mml:mn>722</mml:mn><mml:mo>×</mml:mo><mml:mn>51</mml:mn></mml:mrow></mml:math></inline-formula>; Grid-3: <inline-formula><mml:math display="inline"><mml:mrow><mml:mn>1922</mml:mn><mml:mo>×</mml:mo><mml:mn>1442</mml:mn><mml:mo>×</mml:mo><mml:mn>51</mml:mn></mml:mrow></mml:math></inline-formula>) are used.
Figure <xref ref-type="fig" rid="Ch1.F13"/> shows that our workstation with four
GPUs is comparable to 408 standard CPU cores (= 34
nodes <inline-formula><mml:math display="inline"><mml:mo>×</mml:mo></mml:math></inline-formula> 12 cores/node) in the simulation. Because the thermal
design power of one X5670 CPU is 95 W and that of one K20X GPU is 235 W, we
reduce the energy consumption by a factor of 6.8. Theoretically, as the
subdomain of each MPI process becomes smaller, the cache hit ratio of the
mpiPOM code will increase. This will greatly alleviate the memory
bandwidth-limited problem. However, in the simulation on 408 standard CPU
cores, the MPI communication may occupy more than 40 % of the total
execution time. When scaling to over 450 cores, the mpiPOM simulation may
instead become slower, as shown in Fig. <xref ref-type="fig" rid="Ch1.F13"/>.
Therefore, for high-resolution ocean modelling, our POM.gpu has a clear
advantage compared to the original mpiPOM.</p>

      <?xmltex \floatpos{t}?><fig id="Ch1.F13"><caption><p>Performance test of four GPUs
compared with the <italic>Tansuo100</italic> cluster.</p></caption>
            <?xmltex \igopts{width=236.157874pt}?><graphic xlink:href="https://gmd.copernicus.org/articles/8/2815/2015/gmd-8-2815-2015-f13.pdf"/>

          </fig>

</sec>
</sec>
</sec>
<sec id="Ch1.S6">
  <title>Code availability</title>
      <p>The POM.gpu version 1.0 is available at
<uri>https://github.com/hxmhuang/POM.gpu</uri>. To reproduce the test case in
Sect. <xref ref-type="sec" rid="Ch1.S5"/>, the run_exp002.sh script is provided to compile and
execute the POM.gpu code.</p>
</sec>
<sec id="Ch1.S7" sec-type="conclusions">
  <title>Conclusions and future work</title>
      <p>In this paper, we develop POM.gpu, a full GPU solution based on the mpiPOM.
Unlike previous GPU porting, the POM.gpu code distributes the model
computations on the GPU. Our main contributions include optimizing the code
on each of the GPUs, the communications between GPUs, and the I <inline-formula><mml:math display="inline"><mml:mo>/</mml:mo></mml:math></inline-formula> O
process between the GPUs and the CPUs. Using a workstation with four GPUs, we
achieve the performance of a powerful CPU cluster with 408 standard CPU
cores. Our model also reduces the energy consumption by a factor of 6.8. It
is a cost-effective and energy-efficient strategy for high-resolution ocean
modelling. We have described the method and tests in detail and, with the
availability of the POM.gpu code, our experiences may hopefully be useful to
developers and designers of other general circulation models.</p>
      <p><?xmltex \hack{\newpage}?>In our current POM.gpu, we design a large number of kernel functions because
we port the entire mpiPOM one subroutine at a time. This was done to simplify
the debugging of POM.gpu and to check that the results are consistent with
the mpiPOM. In our future work, we will adjust the code structure of POM.gpu
and adopt aggressive function fusion to further improve the performance.</p>
      <p>Previous studies proposed to take advantage of data locality between time
steps by time skewing <xref ref-type="bibr" rid="bib1.bibx27 bib1.bibx48" id="paren.34"/>, thus
transforming the problem of memory bandwidth into the problem of computation.
However, the real-world ocean models, including the mpiPOM, often involve
hundreds of thousands lines of code, and analysing the data dependency and
applying time skewing in such a context are challenging and difficult. We
leave that to the next-generation POM.gpu.</p>
</sec>

      
      </body>
    <back><app-group>
        <supplementary-material position="anchor"><p><bold>The Supplement related to this article is available online at <inline-supplementary-material xlink:href="http://dx.doi.org/10.5194/gmd-8-2815-2015-supplement" xlink:title="zip">doi:10.5194/gmd-8-2815-2015-supplement</inline-supplementary-material>.</bold></p></supplementary-material>
        </app-group><ack><title>Acknowledgements</title><p>The author would like to thank David Webb, Robert Marsh and the anonymous
reviewer for their valuable comments and improvements regarding the
presentation of this manuscript. This study was supported by funding from the
National Natural Science Foundation of China (41375102), the National Grand
Fundamental Research 973 Program of China (no. 2014CB347800), and the
National High Technology Development Program of China
(2011AA01A203).<?xmltex \hack{\\\\}?>Edited by: R. Marsh</p></ack><ref-list>
    <title>References</title>

      <ref id="bib1.bibx1"><label>Allen and Newberger(1996)</label><mixed-citation>Allen, J. S. and Newberger, P. A.: Downwelling Circulation on the Oregon
Continental Shelf. Part I: Response to Idealized Forcing, J. Phys. Oceanogr., 26, 2011–2035,
<ext-link xlink:href="http://dx.doi.org/10.1175/1520-0485(1996)026&lt;2011:DCOTOC&gt;2.0.CO;2" ext-link-type="DOI">10.1175/1520-0485(1996)026&lt;2011:DCOTOC&gt;2.0.CO;2</ext-link>, 1996.</mixed-citation></ref>
      <ref id="bib1.bibx2"><label>Berntsen and Oey(2010)</label><mixed-citation>Berntsen, J. and Oey, L.-Y.: Estimation of the internal pressure gradient in
<inline-formula><mml:math display="inline"><mml:mi mathvariant="italic">σ</mml:mi></mml:math></inline-formula>-coordinate ocean models: comparison of second-, fourth-, and
sixth-order schemes, Ocean Dynam., 60, 317–330, 2010.</mixed-citation></ref>
      <ref id="bib1.bibx3"><label>Blumberg and Mellor(1983)</label><mixed-citation>
Blumberg, A. F. and Mellor, G. L.: Diagnostic and prognostic numerical
circulation studies of the South Atlantic Bight, J. Geophys. Res.-Oceans, (1978–2012), 88, 4579–4592, 1983.</mixed-citation></ref>
      <ref id="bib1.bibx4"><label>Blumberg and Mellor(1987)</label><mixed-citation>
Blumberg, A. F. and Mellor, G. L.: A description of a three-dimensional
coastal ocean circulation model, Coast. Est. Sci., 4, 1–16, 1987.</mixed-citation></ref>
      <ref id="bib1.bibx5"><label>Browne et al.(2000)Browne, Dongarra, Garner, Ho, and
Mucci</label><mixed-citation>
Browne, S., Dongarra, J., Garner, N., Ho, G., and Mucci, P.: A portable
programming interface for performance evaluation on modern processors,
Int. J. High Perf. Comp. Appl., 14,
189–204, 2000.</mixed-citation></ref>
      <ref id="bib1.bibx6"><label>Chang and Oey(2014)</label><mixed-citation>Chang, Y.-L. and Oey, L.-Y.: Instability of the North Pacific subtropical
countercurrent, J. Phys. Oceanogr., 44, 818–833, 2014.
 </mixed-citation></ref><?xmltex \hack{\newpage}?>
      <ref id="bib1.bibx7"><label>Chapman et al.(2008)Chapman, Jost, and Van
Der Pas</label><mixed-citation>
Chapman, B., Jost, G., and Van Der Pas, R.: Using OpenMP: portable shared
memory parallel programming, vol. 10, The MIT Press, 2008.</mixed-citation></ref>
      <ref id="bib1.bibx8"><label>Ezer and Mellor(1992)</label><mixed-citation>
Ezer, T. and Mellor, G. L.: A numerical study of the variability and the
separation of the Gulf Stream, induced by surface atmospheric forcing and
lateral boundary flows, J. Phys. Oceanogr., 22, 660–682, 1992.</mixed-citation></ref>
      <ref id="bib1.bibx9"><label>Gopalakrishnan et al.(2010)Gopalakrishnan, Liu, Marchok, Sheinin,
Surgi, Tuleya, Yablonsky, and Zhang</label><mixed-citation>
Gopalakrishnan, S., Liu, Q., Marchok, T., Sheinin, D., Surgi, N., Tuleya, R.,
Yablonsky, R., and Zhang, X.: Hurricane Weather Research and Forecasting
(HWRF) model scientific documentation, edited by: Bernardet, L., 75, 2010.</mixed-citation></ref>
      <ref id="bib1.bibx10"><label>Gopalakrishnan et al.(2011)Gopalakrishnan, Liu, Marchok, Sheinin,
Surgi, Tong, Tallapragada, Tuleya, Yablonsky, and
Zhang</label><mixed-citation>
Gopalakrishnan, S., Liu, Q., Marchok, T., Sheinin, D., Surgi, N., Tong, M.,
Tallapragada, V., Tuleya, R., Yablonsky, R., and Zhang, X.: Hurricane Weather
Research and Forecasting (HWRF) model: 2011 scientific documentation, edited by: Bernardet, L.,  2011.</mixed-citation></ref>
      <ref id="bib1.bibx11"><label>Govett et al.(2010)Govett, Middlecoff, and
Henderson</label><mixed-citation>
Govett, M., Middlecoff, J., and Henderson, T.: Running the NIM
next-generation weather model on GPUs, in: Cluster, Cloud and Grid Computing
(CCGrid), 2010 10th IEEE/ACM International Conference on, 792–796, IEEE,
2010.</mixed-citation></ref>
      <ref id="bib1.bibx12"><label>Gropp et al.(1999)Gropp, Lusk, and Thakur</label><mixed-citation>
Gropp, W. D., Lusk, E. L., and Thakur, R.: Using MPI-2: Advanced features of
the message-passing interface, vol. 2, Globe Pequot, 1999.</mixed-citation></ref>
      <ref id="bib1.bibx13"><label>Guo et al.(2006)Guo, Miyazawa, and Yamagata</label><mixed-citation>
Guo, X., Miyazawa, Y., and Yamagata, T.: The Kuroshio Onshore Intrusion along
the Shelf Break of the East China Sea: The Origin of the Tsushima Warm
Current, J. Phys. Oceanogr., 36, 2006.</mixed-citation></ref>
      <ref id="bib1.bibx14"><label>Henderson et al.(2011)Henderson, Middlecoff, Rosinski, Govett, and
Madden</label><mixed-citation>
Henderson, T., Middlecoff, J., Rosinski, J., Govett, M., and Madden, P.:
Experience applying Fortran GPU compilers to numerical weather prediction,
in: Application Accelerators in High-Performance Computing (SAAHPC), 2011
Symposium, 34–41, IEEE, 2011.</mixed-citation></ref>
      <ref id="bib1.bibx15"><label>Huang and Oey(2015)</label><mixed-citation>
Huang, S.-M. and Oey, L.: Right-side cooling and phytoplankton bloom in the
wake of a tropical cyclone, J. Geophys. Res.-Oceans, 2015.</mixed-citation></ref>
      <ref id="bib1.bibx16"><label>Huang et al.(2014)Huang, Wang, Fu, Yang, Wang, and
Zhang</label><mixed-citation>Huang, X. M., Wang, W. C., Fu, H. H., Yang, G. W., Wang, B., and Zhang, C.: A
fast input/output library for high-resolution climate models, Geosci. Model
Dev., 7, 93–103, <ext-link xlink:href="http://dx.doi.org/10.5194/gmd-7-93-2014" ext-link-type="DOI">10.5194/gmd-7-93-2014</ext-link>, 2014.</mixed-citation></ref>
      <ref id="bib1.bibx17"><label>Isobe et al.(2012)Isobe, Kako, Guo, and Takeoka</label><mixed-citation>
Isobe, A., Kako, S., Guo, X., and Takeoka, H.: Ensemble numerical forecasts
of the sporadic Kuroshio water intrusion (kyucho) into shelf and coastal
waters, Ocean Dyn., 62, 633–644, 2012.</mixed-citation></ref>
      <ref id="bib1.bibx18"><label>Jordi and Wang(2012)</label><mixed-citation>
Jordi, A. and Wang, D.-P.: sbPOM: A parallel implementation of Princenton
Ocean Model, Environ. Model. Softw., 38, 59–61, 2012.</mixed-citation></ref>
      <ref id="bib1.bibx19"><label>Kagimoto and Yamagata(1997)</label><mixed-citation>
Kagimoto, T. and Yamagata, T.: Seasonal transport variations of the Kuroshio:
An OGCM simulation, J. Phys. Oceanogr., 27, 403–418, 1997.</mixed-citation></ref>
      <ref id="bib1.bibx20"><label>Korres et al.(2007)Korres, Hoteit, and
Triantafyllou</label><mixed-citation>
Korres, G., Hoteit, I., and Triantafyllou, G.: Data assimilation into a
Princeton Ocean Model of the Mediterranean Sea using advanced Kalman filters,
J. Marine Syst., 65, 84–104, 2007.</mixed-citation></ref>
      <ref id="bib1.bibx21"><label>Kurihara et al.(1995)Kurihara, Bender, Tuleya, and
Ross</label><mixed-citation>
Kurihara, Y., Bender, M. A., Tuleya, R. E., and Ross, R. J.: Improvements in
the GFDL hurricane prediction system, Mon. Weather Rev., 123,
2791–2801, 1995.</mixed-citation></ref>
      <ref id="bib1.bibx22"><label>Kurihara et al.(1998)Kurihara, Tuleya, and Bender</label><mixed-citation>
Kurihara, Y., Tuleya, R. E., and Bender, M. A.: The GFDL hurricane prediction
system and its performance in the 1995 hurricane season., Mon. Weather Rev., 126, 1306–1322, 1998.</mixed-citation></ref>
      <ref id="bib1.bibx23"><label>Leutwyler et al.(2014)Leutwyler, Fuhrer, Cumming, Lapillonne, Gysi,
Lüthi, Osuna, and Schär</label><mixed-citation>
Leutwyler, D., Fuhrer, O., Cumming, B., Lapillonne, X., Gysi, T., Lüthi,
D., Osuna, C., and Schär, C.: Towards Cloud-Resolving European-Scale
Climate Simulations using a fully GPU-enabled Prototype of the COSMO Regional
Model, in: EGU General Assembly Conference Abstracts, vol. 16, p. 11914,
2014.</mixed-citation></ref>
      <ref id="bib1.bibx24"><label>Lin et al.(2006)Lin, Xie, Chen, and Xu</label><mixed-citation>Lin, X., Xie, S.-P., Chen, X., and Xu, L.: A well-mixed warm water column in
the central Bohai Sea in summer: Effects of tidal and surface wave mixing,
J. Geophys. Res.-Oceans, 111, C11017, <ext-link xlink:href="http://dx.doi.org/10.1029/2006JC003504" ext-link-type="DOI">10.1029/2006JC003504</ext-link>, 2006.</mixed-citation></ref>
      <ref id="bib1.bibx25"><label>Linford et al.(2009)Linford, Michalakes, Vachharajani, and
Sandu</label><mixed-citation>
Linford, J. C., Michalakes, J., Vachharajani, M., and Sandu, A.: Multi-core
acceleration of chemical kinetics for simulation and prediction, in:
Proceedings of the Conference on High Performance Computing Networking,
Storage and Analysis, p. 7, ACM, 2009.</mixed-citation></ref>
      <ref id="bib1.bibx26"><label>Mak et al.(2011)Mak, Choboter, and Lupo</label><mixed-citation>
Mak, J., Choboter, P., and Lupo, C.: Numerical ocean modeling and simulation
with CUDA, in: OCEANS 2011, 1–6, IEEE, 2011.</mixed-citation></ref>
      <ref id="bib1.bibx27"><label>McCalpin and Wonnacott(1999)</label><mixed-citation>
McCalpin, J. and Wonnacott, D.: Time skewing: A value-based approach to
optimizing for memory locality, Tech. rep., Technical Report DCS-TR-379,
Department of Computer Science, Rugers University, 477–480, 1999.</mixed-citation></ref>
      <ref id="bib1.bibx28"><label>Michalakes and Vachharajani(2008)</label><mixed-citation>
Michalakes, J. and Vachharajani, M.: GPU acceleration of numerical weather
prediction, Parallel Proc. Lett., 18, 531–548, 2008.</mixed-citation></ref>
      <ref id="bib1.bibx29"><label>Miyazawa et al.(2009)Miyazawa, Zhang, Guo, Tamura, Ambe, Lee, Okuno,
Yoshinari, Setou, and Komatsu</label><mixed-citation>
Miyazawa, Y., Zhang, R., Guo, X., Tamura, H., Ambe, D., Lee, J.-S., Okuno,
A.,
Yoshinari, H., Setou, T., and Komatsu, K.: Water mass variability in the
western North Pacific detected in a 15-year eddy resolving ocean reanalysis,
J. Oceanogr., 65, 737–756, 2009.</mixed-citation></ref>
      <ref id="bib1.bibx30"><label>Newberger and Allen(2007a)</label><mixed-citation>
Newberger, P. and Allen, J. S.: Forcing a three-dimensional, hydrostatic,
primitive-equation model for application in the surf zone: 1. Formulation,
J. Geophys. Res.-Oceans, (1978–2012), 112,
2007a.</mixed-citation></ref>
      <ref id="bib1.bibx31"><label>Newberger and Allen(2007b)</label><mixed-citation>
Newberger, P. A. and Allen, J. S.: Forcing a three-dimensional, hydrostatic,
primitive-equation model for application in the surf zone: 2. Application to
DUCK94, J. Geophys. Res.-Oceans, 112, 2007b.</mixed-citation></ref>
      <ref id="bib1.bibx32"><label>NVIDIA(2015)</label><mixed-citation>NVIDIA: CUDA C Best Practices Guide, available at:
<uri xlink:href="http://docs.nvidia.com/cuda/cuda-c-best-practices-guide/index.html#coalesce\%d-access-to-global-memory">http://docs.nvidia.com/cuda/cuda-c-best-practices-guide/index.html#coalesce%d-access-to-global-memory</uri> (last access: April 2015), 2015.</mixed-citation></ref>
      <ref id="bib1.bibx33"><label>Oey et al.(2013)Oey, Chang, Lin, Chang, Xu, and Lu</label><mixed-citation>
Oey, L., Chang, Y.-L., Lin, Y.-C., Chang, M.-C., Xu, F.-H., and Lu, H.-F.:
ATOP-the Advanced Taiwan Ocean Prediction System based on the mpiPOM Part 1:
model descriptions, analyses and results, Terr Atmos Ocean Sci, 24, 2013.</mixed-citation></ref>
      <ref id="bib1.bibx34"><label>Oey(2005)</label><mixed-citation>
Oey, L.-Y.: A wetting and drying scheme for POM, Ocean Modelling, 9,
133–150,
2005.</mixed-citation></ref>
      <ref id="bib1.bibx35"><label>Oey(2014)</label><mixed-citation>Oey, L.-Y.: Geophysical Fluid Modeling with the mpi version of the Princeton
Ocean Model (mpiPOM). Lecture Notes, 70 pp.,
<uri>ftp://profs.princeton.edu/leo/lecture-notes/OceanAtmosModeling/Notes/GFModellingUsingMpiPOM.pdf</uri> (last access: January 2014),
2014.</mixed-citation></ref>
      <ref id="bib1.bibx36"><label>Oey and Chen(1992a)</label><mixed-citation>
Oey, L.-Y. and Chen, P.: A model simulation of circulation in the northeast
Atlantic shelves and seas, J. Geophys. Res.-Oceans, 97, 20087–20115, 1992a.</mixed-citation></ref>
      <ref id="bib1.bibx37"><label>Oey and Chen(1992b)</label><mixed-citation>
Oey, L.-Y. and Chen, P.: A nested-grid ocean model: With application to the
simulation of meanders and eddies in the Norwegian Coastal Current, J. Geophys. Res.-Oceans, (1978–2012), 97, 20 063–20 086,
1992b.</mixed-citation></ref>
      <ref id="bib1.bibx38"><label>Oey et al.(1985a)Oey, Mellor, and Hires</label><mixed-citation>
Oey, L.-Y., Mellor, G. L., and Hires, R. I.: A three-dimensional simulation
of
the Hudson-Raritan estuary. Part I: Description of the model and model
simulations, J. Phys. Oceanogr., 15, 1676–1692,
1985a.</mixed-citation></ref>
      <ref id="bib1.bibx39"><label>Oey et al.(1985b)Oey, Mellor, and Hires</label><mixed-citation>
Oey, L.-Y., Mellor, G. L., and Hires, R. I.: A three-dimensional simulation
of the Hudson-Raritan estuary. Part II: Comparison with observation, J. Phys.
Oceanogr., 15, 1693–1709, 1985b.</mixed-citation></ref>
      <ref id="bib1.bibx40"><label>Oey et al.(1985c)Oey, Mellor, and Hires</label><mixed-citation>
Oey, L.-Y., Mellor, G. L., and Hires, R. I.: A three-dimensional simulation
of
the Hudson-Raritan estuary. Part III: Salt flux analyses, J. Phys. Oceanogr., 15, 1711–1720, 1985c.</mixed-citation></ref>
      <ref id="bib1.bibx41"><label>Oey et al.(2003)Oey, Lee, and Schmitz</label><mixed-citation>Oey, L.-Y., Lee, H.-C., and Schmitz, W. J.: Effects of winds and Caribbean
eddies on the frequency of Loop Current eddy shedding: A numerical model
study, J. Geophys. Res.-Oceans,  108, 3324, <ext-link xlink:href="http://dx.doi.org/10.1029/2002JC001698" ext-link-type="DOI">10.1029/2002JC001698</ext-link>, 2003.</mixed-citation></ref>
      <ref id="bib1.bibx42"><label>Shimokawabe et al.(2010)Shimokawabe, Aoki, Muroi, Ishida, Kawano,
Endo, Nukada, Maruyama, and Matsuoka</label><mixed-citation>
Shimokawabe, T., Aoki, T., Muroi, C., Ishida, J., Kawano, K., Endo, T.,
Nukada,  A., Maruyama, N., and Matsuoka, S.: Proceedings of the International
Conference for High Performance Computing, Networking, Storage and Analysis,
1–11, An 80-fold speedup, 15.0 TFlops full GPU acceleration of  non-hydrostatic weather model ASUCA production code,
2010.</mixed-citation></ref>
      <ref id="bib1.bibx43"><label>Siewertsen et al.(2013)Siewertsen, Piwonski, and
Slawig</label><mixed-citation>Siewertsen, E., Piwonski, J., and Slawig, T.: Porting marine ecosystem model
spin-up using transport matrices to GPUs, Geosci. Model Dev., 6, 17–28, <ext-link xlink:href="http://dx.doi.org/10.5194/gmd-6-17-2013" ext-link-type="DOI">10.5194/gmd-6-17-2013</ext-link>, 2013.</mixed-citation></ref>
      <ref id="bib1.bibx44"><label>Smolarkiewicz(1984)</label><mixed-citation>
Smolarkiewicz, P. K.: A fully multidimensional positive definite advection
transport algorithm with small implicit diffusion, J. Comp.
Phys., 54, 325–362, 1984.</mixed-citation></ref>
      <ref id="bib1.bibx45"><label>Sun et al.(2014)Sun, Oey, Xu, Lin, Huang, and
Chang</label><mixed-citation>Sun, J., Oey, L., Xu, F., Lin, Y., Huang, S., and Chang, R.: The Influence of
Ocean on Typhoon Nuri (2008), in: AGU Fall Meeting Abstr., 1,
L3360, available at: <uri>http://adsabs.harvard.edu/abs/2014AGUFM.A33L3360S</uri>, 2014.</mixed-citation></ref>
      <ref id="bib1.bibx46"><label>Sun et al.(2015)Sun, Oey, Chang, Xu, and Huang</label><mixed-citation>
Sun, J., Oey, L.-Y., Chang, R., Xu, F., and Huang, S.-M.: Ocean response to
typhoon Nuri (2008) in western Pacific and South China Sea, Ocean Dynam.,
65, 735–749, 2015.</mixed-citation></ref>
      <ref id="bib1.bibx47"><label>Varlamov et al.(2015)Varlamov, Guo, Miyama, Ichikawa, Waseda, and
Miyazawa</label><mixed-citation>Varlamov, S. M., Guo, X., Miyama, T., Ichikawa, K., Waseda, T., and Miyazawa,
Y.: M2 baroclinic tide variability modulated by the ocean circulation south
of Japan, J. Geophys. Res.-Oceans, 2015.
 </mixed-citation></ref><?xmltex \hack{\newpage}?>
      <ref id="bib1.bibx48"><label>Wonnacott(2000)</label><mixed-citation>
Wonnacott, D.: Using time skewing to eliminate idle time due to memory
bandwidth and network limitations, in: Parallel and Distributed Processing
Symposium, 2000. IPDPS 2000, Proceedings, 14th International, 171–180,
IEEE, 2000.</mixed-citation></ref>
      <ref id="bib1.bibx49"><label>Xu and Oey(2011)</label><mixed-citation>
Xu, F.-H. and Oey, L.-Y.: The origin of along-shelf pressure gradient in the
Middle Atlantic Bight, J. Phys. Oceanogr., 41, 1720–1740,
2011.</mixed-citation></ref>
      <ref id="bib1.bibx50"><label>Xu and Oey(2014)</label><mixed-citation>
Xu, F.-H. and Oey, L.-Y.: State analysis using the Local Ensemble Transform
Kalman Filter (LETKF) and the three-layer circulation structure of the Luzon
Strait and the South China Sea, Ocean Dynam., 64, 905–923, 2014.</mixed-citation></ref>
      <ref id="bib1.bibx51"><label>Xu and Oey(2015)</label><mixed-citation>
Xu, F.-H. and Oey, L.-Y.: Seasonal SSH variability of the Northern South
China  Sea, J. Phys. Oceanogr., 45, 1595–1609, 2015.</mixed-citation></ref>
      <ref id="bib1.bibx52"><label>Xu et al.(2013)Xu, Oey, Miyazawa, and Hamilton</label><mixed-citation>
Xu, F.-H., Oey, L.-Y., Miyazawa, Y., and Hamilton, P.: Hindcasts and
forecasts
of Loop Current and eddies in the Gulf of Mexico using local ensemble
transform Kalman filter and optimum-interpolation assimilation schemes, Ocean
Model., 69, 22–38, 2013.</mixed-citation></ref>
      <ref id="bib1.bibx53"><label>Yang et al.(2013)Yang, Xue, Fu, Gan, Li, Xu, Lu, Sun, Yang, and
Zheng</label><mixed-citation>
Yang, C., Xue, W., Fu, H., Gan, L., Li, L., Xu, Y., Lu, Y., Sun, J., Yang,
G.,
and Zheng, W.: A peta-scalable CPU-GPU algorithm for global atmospheric
simulations, in: Proceedings of the 18th ACM SIGPLAN symposium on Principles
and practice of parallel programming,  1–12, ACM, 2013.</mixed-citation></ref>
      <ref id="bib1.bibx54"><label>Yin and Oey(2007)</label><mixed-citation>
Yin, X.-Q. and Oey, L.-Y.: Bred-ensemble ocean forecast of Loop Current and
rings, Ocean Model., 17, 300–326, 2007.</mixed-citation></ref>
      <ref id="bib1.bibx55"><label>Zavatarelli and Mellor(1995)</label><mixed-citation>
Zavatarelli, M. and Mellor, G. L.: A numerical study of the Mediterranean Sea
circulation, J. Phys. Oceanogr., 25, 1384–1414, 1995.</mixed-citation></ref>
      <ref id="bib1.bibx56"><label>Zavatarelli and Pinardi(2003)</label><mixed-citation>Zavatarelli, M. and Pinardi, N.: The Adriatic Sea modelling system: a nested
approach, Ann. Geophys., 21, 345–364,
<uri>10.5194/angeo-21-345-2003</uri>, 2003.</mixed-citation></ref>
      <ref id="bib1.bibx57"><label>Zhenya et al.(2010)Zhenya, Haixing, Xiaoyan
et al.</label><mixed-citation>
Zhenya, S., Haixing, L., Xiaoyan, L., and Zhao, W.: The Application of GPU in Ocean
General Circulation Mode POP, Comp. Appl. Softw., 27, 27–29,
2010.</mixed-citation></ref>

  </ref-list><app-group content-type="float"><app><title/>

    </app></app-group></back>
    </article>
