{'fraction_non_alphanumeric': 0.02928928761074313, 'fraction_numerical': 0.011151169615158883, 'mean_word_length': 5.033046703759905, 'pattern_counts': {'":': 0, '<': 2, '<?xml version=': 0, '>': 2, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
OpenACC Acceleration of an Agent-Based Biological Simulation Framework

Computational biology has increasingly turned to agent-based modeling to explore complex biological systems. Biological diffusion (diffusion, decay, secretion, and uptake) is a key driver of biological tissues. GPU computing can vastly accelerate the diffusion and decay operators in the partial differential equations used to represent biological transport in an agent-based biological modeling system. In this paper, we utilize OpenACC to accelerate the diffusion portion of PhysiCell, a cross-platform agent-based biosimulation framework. We demonstrate an almost 40x speedup on the state-of-the-art NVIDIA A100 GPU compared to a serial run on AMD's EPYC 7742. We also demonstrate 9x speedup on the 64 core AMD EPYC 7742 multicore platform. By using OpenACC for both the CPUs and the GPUs, we maintain a single source code base, thus creating a portable yet performant solution. With the simulator's most significant computational bottleneck significantly reduced, we can continue cancer simulations over much longer times.


Introduction and Motivation
Computational biology has increasingly turned to agent-based modeling-which represents individual biological cells as discrete software agents-to explore complex biological systems where many cells interact through exchange of mechanical forces, exchange of diffusing chemical factors, and other biomechanical feedback [1]. Biological diffusion (diffusion, decay, secretion, and uptake) is a key driver of biological tissues. Blood vessels release nutrients (oxygen, glucose, and other key metabolites) that diffuse through tissues to be consumed by cells and then absorb diffusible waste products, while cells secrete and absorb diffusible chemical factors to communicate and coordinate their behaviors [2], [3]. See Figure 1 for a typical 3-D simulation model. Therefore, most modern agent-based biological modeling systems are hybrid: they combine discrete cell agents with partial differential equations (PDEs) to represent biological transport, such as where ρ is a vector of diffusible substrates, and each cell agent i has position x i and volume V i , a vector of secretion rates S i and uptake rates U i , and a "target" extracellular substrate vector ρ * i [4]. (Vector-vector products are taken element-wise, and δ is the Dirac delta function.) Numerical stability and accuracy require that these PDEs be solved with relatively small step sizes ∆t, making solution of biological diffusion PDEs a rate-limiting step in hybrid agent-based biological models that can limit the maximum size and duration of simulations. This, in turn, can hinder high-throughput simulation model exploration (e.g., [5], [6]) or newer model calibration techniques like approximate Bayesian computation [7], [8], both of which require running thousands or millions of simulations quickly.
GPU computing can vastly accelerate the diffusion and decay operators in the Equation 1, Figure 1: Typical PhysiCell model. The "cancer-immune-sample" is a typical example of a complex biological system modeled with the PhysiCell framework. Tumor cells (A: colored from blue to yellow by aggressiveness) grow, divide, and die based upon local availability of oxygen that diffuses from the computational boundary. Tumor cell consumption of oxygen leads to formation of oxygen gradients (B) and eventual necrosis (death) in the center (brown cells). Tumor cells also release a diffusible immunostimulatory factor (C) that attracts immune cells (red), who move by biased random migration towards tumor cells, attach, and preferentially kill highly immunogenic tumor cells (yellow) (D). Readers can interactively run a 2D version of this model in a web browser at https://nanohub.org/tools/pc4cancerimmune. but the tight coupling with a cell-based sourceswhich dynamically move and change their sizes and rate constants-makes overall solution more challenging. Moreover, the number of discrete cell agents can change by orders of magnitude over the course of a cancer simulation. Recent examples (e.g., [9]) have confirmed the potential for GPU-accelerated agent-based models, but to date have generally been limited to simplified systems that do not include complex intracellular-level dynamics (e.g., by coupling Boolean network models [10]) or complex cell-cell interactions and other rules.
In this paper, we carefully utilize OpenACC, a directive-based programming model to accelerate the diffusion portion in Equation 1 in PhysiCell [11], a cross-platform agent-based biosimulation framework that has been adopted in cancer [12], [13], infectious diseases [14], [15] and other complex biological problems. Prior to this work, PhysiCell had been optimized for multicore simulations with OpenMP. With default settings, PhysiCell advances the numerical solution of Equation 1 with 10 diffusion steps (∆t diff ) before advancing the cell-cell mechanical interactions by one mechanics step (∆t mech ); cell biological processes (e.g., cell cycle progression, death, and "decision making" are advances on a much slower cell time scale ∆t cell ∼ 60∆t mech . This separation of time scales allowed us to prioritize GPU optimization to the biological diffusion solver. Using NVIDIA HPC SDK OpenACC 21.3, we demonstrate an almost 40x speedup using managed memory on the state-of-the-art NVIDIA Ampere 100 (A100) GPU compared to a serial AMD EPYC core 7742 for a 360 simulated minutes input dataset.We also demonstrate 9x speedup on the 64 core AMD EPYC 7742 multicore platform using NVIDIA HPC SDK OpenACC 21.3. By using OpenACC for both the CPUs and the GPUs, we maintain a single source code base, thus creating a portable yet performant solution.
This is a critical step towards a portable GPU acceleration of a detailed agent-based simulation platform for complex biological systems. With the simulator's most significant computational bottleneck significantly reduced, we can look towards continuing cancer simulations over much longer times. It also represents a key step towards converting this code from purely CPU-based towards an MPI+X paradigm. In doing so, large 3-D simulation domains are decomposed into smaller subdomains residing on individual HPC nodes with MPI data exchange. In each compute node's subdomain, cell "logic" continues to be parallelized for multicore SMP with OpenMP and critical lowlevel mechanics like biological diffusion and cellcell mechanical interactions are parallelized on the GPU (or other specialized accelerators) via OpenACC. This will help grow the code to allow 3-D multiscale simulations of cancer and diseases in unprecedented detail on emerging leadership class high performance computing resources: a critical step towards advancing cancer patient digital twins that can simulate clinically significant tumors fast enough to be clinically actionable for patient care decisions [16].

Design and Implementation
This section narrates the design and implementation choices we employed while parallelizing and accelerating PhysiCell on a heterogeneous system.
The compiler directives that it provides can be used to annotate loops and regions of code that exhibit parallelism. The programmer can also specify a target at compile time to let the compiler know what type of hardware is being targeted by the annotated code regions. Supported hardware includes multicore CPUs (both x86 and ARM), as well as various types of accelerators, including NVIDIA GPUs, AMD GPUs, and FPGAs.
OpenACC employs a host/device execution model. This means that most of a programmer's application executes within a host thread and compute intensive parallel regions (denoted by directive annotations) are offloaded either to multiple host cores (multicore CPU) or an accelerator (such as a GPU). The OpenACC specification refers to the host thread as the host and the parallel hardware, whether it be a multicore CPU or an accelerator, as the device. The job of the device is to execute portions of the code that are annotated with directives.
Since many parallel regions contain multidimensional loop nests and modern accelerators support multiple levels of parallelism, OpenACC provides clauses the programmer can use within a directive to describe hierarchical parallelism within their code. Accelerators and multicore CPUs both support coarse-grained parallelism: fully parallel execution across execution units with limited synchronization support. OpenACC exposes coarse-grained parallelism via the gang clause. Most accelerators and some multicore CPUs also support fine-grained parallelism: multiple execution threads within a single execution unit. OpenACC exposes fine-grained parallelism via the worker clause. Last, most accelerators and multicore CPUs support SIMD operations within execution units. OpenACC exposes these operations via the vector clause. It is the job of the programmer to understand the difference between these levels of parallelism and know which portions of their code can execute in what manner in order to properly annotate their source code for parallel execution.
One defining characteristic of a host/device execution model is that device memory may be separate from host memory. For example, GPUs have their own onboard memory, which is separate from the rest of the system's memory. In such a system, the host thread is unable to read or write device memory, since it is not part of the host thread's virtual memory space, and the device is similarly unable to read or write host memory in most cases. Instead, all data movement between host and device memory must be performed by the host thread through explicit system calls. Fortunately, OpenACC provides directives for managing data movement between the host and device, and the compiler takes care of generating the appropriate system calls based on the specified target accelerator. When running on NVIDIA GPUs, OpenACC applications compiled with NVIDIA's compiler can take advantage of a feature called managed memory, where data movement between the host and the device is handled automatically by the underlying CUDA runtime, alleviating the programmer of this responsibility. However, abdicating control of data movement to the CUDA runtime may come at a performance cost. Typically, data transfer overhead is where most parallel applications that utilize an accelerator suffer performance losses. If data movement is not efficiently managed, these losses can even be so big as to outweigh the computational benefit of using the accelerator, resulting in a slowdown of overall application performance.
The natural question is could we have used OpenMP offloading [26] for this code. The offloading model is beginning to mature as we speak based on the validation and verification findings [27], [28]. We also note that the model is being used on mini-applications [29] and other applications including Pseudo-Spectral Direct Numerical Simulation-Combined Compact Difference (PSDNS-CCD3D) [30] and Quicksilver [31] among others [32], [33], [34], [30], [35]. We chose to go with OpenACC instead of the OpenMP offloading model. Based on our experience, the latter still has room for improvement before it could be more easily adopted for real-world applications, whereas OpenACC has already proven its easier adaptability, stability, and maturity. Having said that, for our continued efforts on PhysiCell in the near future, we plan to explore the OpenMP offloading model as well.

Using OpenACC programming model for PhysiCell
PhysiCell-GPU is designed to run the diffusion portion of PhysiCell (BioFVM [4]) in an accelerated mode. BioFVM simulates the diffusive transport of substrates, while PhysiCell simulates the cells [11]. BioFVM has been parallelized on multicore systems using directive-based programming model, OpenMP [26] that was established in 1998 and is widely used for parallel programming. While parallelization on several cores can be beneficial, we hypothesized that the move to the GPU would see even greater performance in key sections of the code that would benefit from being accelerated on GPUs.
To test this, we have explored the usage of OpenACC in order to achieve performance while maintaining cross-platform portability in BioFVM. Irrespective of using OpenACC or OpenMP, the fundamental idea of a directivebased programming model for GPUs includes taking an approach similar to the low-level programming framework for GPUs, such as CUDA [36], where data needed for compute is passed to the GPU and the parallel functions are computed on the GPU, and then finally pulling the updated data back to the host for further processing.
Preliminary profiling results showed that the diffusion core was a significant portion of the total runtime; this is consistent with our earlier discussion that there are 600 diffusion steps (∆t diff ) (which requires computing updates for each voxel location in space as well as secretion and uptake for each cell agent) for every cell biology step (∆t cell ). Given our analysis of the parallel regions, we began to incrementally port the diffusion core of the code to GPU while carefully leaving intact biology-focused functionality in the individual cell agents, including their interactions with diffusing substrates. We started with a 2-D BioFVM test case to assess and understand the data that are required by the diffusion and supplementary functions, then began running a custom test case to cement the initial understanding. In terms of the porting process, data is handled first, then functions, then supplementary functions such as AXPY (a basic linear algebra subroutine). The overall design goal is to create a GPU accelerated diffusion portion while maintaining one-to-one equivalence of calculations between the original BioFVM and the GPU-optimized BioFVM.

Profiling; Identifying Hot Spots
We initially profiled the "cancer-immunesample" sample project that is bundled with every PhysiCell download [11]. This 3-D sample is representative of (CPU-based) PhysiCell models: the model includes multiple diffusible substrates (oxygen and an inflammatory factor), and multiple cell types (red immune cells attack tumor cells), heterogeneous cell properties (blue tumor cells are less aggressive and less immunogenic; yellow tumor cells are more aggressive but also more immunogenic), and customized cellcell mechanical interaction rules (immune cells seek tumor cells, test for contact, adhere with spring-like terms, test tumor cell properties, and probabilistically induce death). (See Figure 1.) This profiling was used in order to identify the hot spots that would be candidates for acceleration. The NVPROF command-line profiler confirmed the insight that diffusion was the dominating portion of the total runtime. Figure 2 shows that the diffusion function dominated the total time, and hence was our target of optimization. For profiling, we used an internal UD system called Skywalker with an NVIDIA V100 GPU for the initial profile, and recreated the profile for the pie chart using NVPROF from Cuda release version 11.0.
As we developed the OpenACC accelerated code, we periodically profiled the work in progress using the NVIDIA Nsight Systems profiler [37] and an NVIDIA V100 GPU with 32 GB of High Bandwidth Memory (HBM2).

Elements of Parallelism
In PhysiCell, diffusion involves a number of computational steps and function calls. The data that are invoked by these functions are handled with care to ensure a good computation vs memory transfer balance. After initialization of the GPU copy of p-density-vectors in GPU memory, updates are only processed to the host if the users request (user manually managed memory) or when there is a page-fault on the data initiated by the host (OpenACC managed memory). Because the data are ported to arrays, each part of the diffusion section is carefully mapped from its original state operating on vectors to operating on arrays.
Data p-density-vectors is the main array for the data that would be updated from the diffusion functions and transferred between device and host. Originally, this data structure is a "vector of vectors" or a 2D vector (each voxel in the simulation grid holds a vector of diffusible substrate values). The p-density-vector on the host are std::vectors and the p-density-vector-GPU on device are array. transfer-3D() and transfer-2D() are called to initialize the memory space on the GPU and to copy the data currently in p-densityvectors. The functions translate-vector-to-array() and translate-array-to-vector() translate the data back and forth between array and vector types on the host. This is used after the host-side mirror of the GPU array data is updated to the host. If there is any work done in p-density-vectors on the host, then these methods will convert the data to array form and initiate the update to the device.
The rest of the data needed by the diffusion section are initialized in the transfer-3D() and transfer-2D(). These data are essential to the computation and are converted to array form like p-density-vectors, but the data are not typically updated back and forth between host and device. If the need arises, a function could easily be made to create a host-side mirror and OpenACC directives to handle the memory updates.
The following psudeo-code shows the pattern which surrounds the OpenACC pragmas that handle data flow between the device and host. This example shows an array of arrays named physicell array undergo a deep copy, each inner array gets allocated on the device while keeping the pointers intact, so that the outer array can be referenced. The this keyword is crucial to the process, as that lets the compiler know to keep the newly created data on the device interlocked with the surrounding data.
Compute x-diffusion-GPU-2D() exists for the direct computation step for diffusion. In 2D, this is performed in X and Y and in 3D in X, Y, and Z vectors. The algorithm from the original PhysiCell stayed the same, while the syntax was changed to account for the new array format of the crucial data. Slight modifications are made to the original design, including creating a separate AXPY-GPU function, wrapped in an OpenACC routine directive to enable GPU execution. Storing the specific size of the p-densityvectors in GPU memory is important for many loop bounds in the x-diffusion-GPU-2D() section. apply-dirichlet-conditions-GPU() is an important auxiliary function that was initially not set to need to run on the GPU. We learned that with the Dirichlet condition on the GPU, it eliminated the need for a high rate of update with fresh data between Dirichlet and Diffusion computation steps. The original version utilized OpenMP parallel for across the top-level loop, and our version kept to  axpy-acc() helps manage the more complex diffusion section by replacing the inline axpy and naxpy (basic linear algebra subroutines) in each x, y, and z diffusion function with a single function. Abstracting AXPY away from the multiple inline improves readability and promotes a modular design.

Methods of Validation for Data Integrity
We used three methods to validate that the OpenACC implementation did not affect the scientific results of the code.

Method 1: 1-D convergence test
Our first validation test method uses an 1-D convergence test from the original BioFVM method paper [4] to ensure that the expected numerical accuracy was maintained. Briefly, this tests the ∞ norm of the numerical solution against a known analytical solution at multiple times for a 1-D problem with diffusion, zero flux (Neumann) boundary conditions, and a nontrivial initial condition. See [4] for further details.

Method 2: p-density-vectors cross check
In Method 2, we compared the data from the PhysiCell-GPU against the original CPU-based PhysiCell in each voxel. As noted previously, PhysiCell-GPU uses an array version of the data structure p-density-vector to represent the micro environment data on the GPU. PhysiCell originally used C++ std::vectors, which have an issue porting easily to GPU. In the past, there has been a limited implementation of std::vector by the PG Group, but given the complexity of PhysiCell's p-density-vector data structure and the microenvironment C++ class structure, this implementation would not work in this case. P-density-vector is a pointer to a std::vector<std::vector<double>>, and this extra layer prevents us from utilizing the feature. PhysiCell-GPU has a number of differences we needed to ensure did not introduce any difference against the reference. Testing for compiler, compile flag, and architecture difference was important to assess PhysiCell-GPU.
Method 3: Visual Inspection of output Methods 1 and 2 gave quantitative ways to validate PhysiCell-GPU against simple examples with known analytic solutions. We devised Method 3 to give a test against more realistic conditions in a higher dimensional geometry that more closely replicates typical modeling conditions, but where analytic solutions are not available. To verify the success of the port in terms of keeping full integrity of the data after going through diffusion on the GPU, visual inspection was used on the output for a fast yet reliable method. We had created a Python script to display the necessary data from the Microenvironment on a plot. By design, a small change in functional performance would cause a dramatic change in cell data and therefore the visualization, thus helping us to readily identify errors. Figure 3 shows an example of vastly different outputs caused by a simple "off by one" error in the Dirichlet function; Figure 4 shows the same visual inspection test after the bug was fixed. While techniques (noted above) were used that inspected every element, the visual inspection method was often used before any other as a glaring indicator of data corruption.

Experimental Setup and Input Datasets
This section highlights the experimental set up details for the results. We have primarily used two NVIDIA DGX machines. The hardware and the software details are described below in Table 1.
While the original PhysiCell code was compiled using OpenMP-enabled gcc version 7.5.0, we used the NVIDIA HPC SDK's nvc 21.3 compiler for parallelizing and accelerating the code. This compiler supports both OpenMP parallelization, as well as OpenACC offloading. The full code corresponding to this paper is available on GitHub [38].

Input Datasets
PhysiCell input is written in XML. In the original PhysiCell code the parameters changed were x min, x max, y min, y max, z min, z max, max time, and omp num threads. The set of results came from x,y,and z min set at -1000 along with x,y, and z max set at 1000 with the max time units at 60 simulated minutes. The parameter omp num threads was set at 1 and 32, representing a serial implementation and a optimal performance CPU thread count respectively. The second set of results kept all parameters the same expect increasing the max time units to 180 simulated time, and a third for 360 simulated minutes. This input set represent a cell at the size of 1cm.

Results
This section presents the results on the CPUs and the GPUs. Table 2 presents results for singlecore CPU, 64 cores CPU, NVIDIA's V100 GPU, and NVIDIA's A100 GPU using two implementations namely the manual and the managed memory implementations for the different input datasets.
The OpenMP CPU results use NVIDIA's NVHPC 21.3 showing the time taken using 1 thread on AMD EPYC Rome to simulate a serial version. Using 1 thread is close to running the code in the native serial manner, but it is not exact, as the code has been optimized from the native serial version. We were forced to take this approach because a native serial version of the code is not available. We then show the runtime using 64 cores to demonstrate the speedup of approximately 7.6x when running the OpenMP version on a high end CPU. Figure 5 shows that a speedup of almost 40x using OpenACC to target an NVIDIA A100 GPU using managed memory was achieved over the serial CPU configuration for 360 simulated minutes as the dataset. Overall, the NVIDIA A100 GPU shows a better speedup with the same code over the V100 GPU because of the more advanced architecture and faster memory interconnect of the A100s.
The table also shows the execution time of the manual and the managed memory implementations for the GPUs. The manual implementation copies the data back and forth between the host and device using explicit OpenACC data management directives and translation between vector and array data types. The managed memory results refer to compiling the code with the managed memory flag turned on, which is similar to CUDA's managed memory implementation; programmer intervention with respect to data movement is not required. The addresses in host and device point to the same address location, and use page-faults to trigger data updates/migrations. In our case, the managed memory implementation     Table   has the benefit of less memory transfer time compared to manual memory implementation in exchange for less fine-grain control of the GPU resident data. This relationship can be observed in Figure 5 in the form of relative speedups. This shows that while data transfer from the CPU to the GPU is relatively expensive upfront, the benefit is seen over more timesteps with more realistic simulation lengths. This is due to the fact that data can remain on the GPU in between timesteps, which reduces the amortized cost of the upfront data transfers and increases the benefit of the accelerated diffusion as the number of timesteps is increased. Figure 6 shows an Nsight Systems profile of the code running on the GPU using managed memory. We observe the large upfront data transfer cost in green, followed by the computation that makes up each timestep in blue. Note that there are no large pieces of data movement to or from the GPU in between the timesteps shown. Overall, we see speedups that benefit the domain application by allowing larger problem sizes and longer simulation times in less wall time.
The times for the Manual GPU A100 run show that there was a greater memory transfer time than the Manual GPU V100 run. This was unexpected and not caused by the A100 GPU itself, as we have tested on a standalone A100 PCIE based card and saw no extra memory This is the first work to apply portable GPU acceleration (via OPenACC) to biological diffusion in PhysiCell-a critical bottleneck to larger and longer simulations. Others have recently applied MPI accelerations to BioFVM [39] and PhysiCell to advance towards billion-cell simulations [40]. However, these require significant code refactoring and high performance computing resources to attain their full performance. They have not been optimized to leverage workstation (or single compute node) GPU resources. Ultimately, a hybrid OpenACC-MPI architecture could attain still better performance by leveraging our OpenACC-based GPU acceleration on individual compute nodes, with MPI and domain decomposition to attain billion-cell scalability.

GPU-accelerated Long-time Simulations
To assess the potential scientific impact of the GPU-accelerated code, we performed tests on PhysiCell's built-in cancer_immune_sample sample project that originated in [11]. (See the brief description of this sample project in Figure  1.) To maintain our focus on the GPU acceleration of the diffusion code, we disabled cell mechanics and phenotype changes, thus leaving cell positions, sizes, and behaviors fixed. To emulate a typical scientific workflow, we performed a full data save every 7 simulated days. In the original work [11] and subsequent 3D parameter space investigations [5], simulations were limited to 21 days (3 data checkpoints) dues to CPU limitations, each requiring approximately 48 hours (wall time) to complete. Based on our profiling, we estimate that diffusion consumed approximately 65% (∼30 hours) of the wall time for each simulation in prior studies.
After recompiling the CPU-based code with the same nvc++ compiler, we simulated the 3-D model (diffusion only) with default parameter values on an AMD EPYC 64-core CPU. The CPU-only code only reached the first checkpoint (7 days) and was not able to complete the full 21day simulation within the maximum 4-hour time limit on the DGX system (a typical constraint on large-scale model exploration on shared systems); based on the simulation's progress by this time limit and prior benchmarking [4], we estimate that the CPU-only code would require approximately 9.3 hours (wall time) to complete the full 21-day simulation on the system. Only the first checkpoint (equal to a 7 day simulation) finished at 3 hours, 6 minutes and 4 seconds of wall time. We next asked how far an OpenACC GPUaccelerated simulation (managed memory, A100 GPU) could be extended within a maximum 4hour time limit by increasing the test's maximum simulation time and continuing to save data every 7 simulated days. Whereas the CPU-only code (64 cores; AMD EPYC) only reached the first 7-day checkpoint, the OpenACC code was able to reach and pass the 42-day checkpoint (6 checkpoints), requiring 3 hours, 24 minutes to simulate 42 days of wall time. By contrast, we estimate that CPU-only code would have required over 18 hours to complete the same computations. This shows that using the GPUaccelerated diffusion code should enable longduration simulations (e.g., of cancer and disease progression) that were previously only feasible on systems that permit submitted jobs to run for hours or days. However, many shared computational resources are not available for the length of time that would be required. Without accelerated computing, a timeout of resources would be reached long before the desired results were computed. This is particularly relevant for the emerging field of cancer forecasting [41] and cancer patient digital twins [16], [42]: after calibration, a clinical teams will use the patient's digital twin to simulate thousands of candidate treatment plans (virtual control, standard of care, and multiple combination therapies under a variety of dosing options) over weeks or months, each with tens of replicates to estimate uncertainty. These multiweek simulations must execute quickly to allow timely clinical decision support; supporting clinical workflows at scale will further increase the need for rapidly executing long-duration forecasting simulations.

Conclusion
Code profiling of a complex, multiscale biological agent-based code revealed that for typical simulation models, approximately 65% of execution time (wall time) is spent on biological diffusion, making this a logical first target for GPU optimization. Offloading numerical operations to solve the diffusion along with careful management of memory transfers between host and device memory resulted in an approximately 40-fold reduction in execution time for the biological diffusion solver. Multiple testing methods were used to validate the GPU code against the original CPU code.
In real-world testing against a complex 3-D cancer immunology example, switching from a 64-core CPU implementation to a managed memory OpenACC GPU implementation reduced execution time (wall time) for 21 days of biological diffusion and data saves from 9.3 hours to 1.7 hours-a reduction of over 80%. Based on earlier profiling that diffusion is responsible for over 65% of total execution time, we estimate that full simulation code-once again include cell mechanics and biological calculations responsible for the remaining 35% of execution timewould require approximately 50% less execution time once using the GPU-accelerated diffusion algorithms developed in this paper. Furthermore, the GPU-accelerated code was able to complete a diffusion-only simulation twice as long as the CPU-based code in roughly one third of the time, allowing us to simulate farther in time than was previously feasible while observing new biological dynamics.
A full 21-day simulation might be expected to take ∼ 1 0.65 × 9.3 hours (14-15 hours) to execute, and so the GPU-accelerated full model should see its total wall time reduced to 7-8 hours. This could potentially allow us to double the duration of each simulation for the same amount of execution time, thus exposing new biological dynamics. This confirms the scientific benefit of accelerating targeted portions of the code with careful GPU optimization.

Acknowledgement
This material is based upon work supported by the National Science Foundation under Grant No. 1814609.

Future Work
The current implementation yielded a significant performance increase that in turn "unlocked" new scientific possibilities in the code, particularly longer-time simulations. However, more could be done. First, the OpenACC acceleration of the biological diffusion still relies upon CPU operations for the cell-based secretion and uptake of biological substrates. These may account for the difference between the 40× speedup in simpler performance benchmarking and the "real world" 3D test (5-6× speedup) where cell secretion and uptake play a greater role. Moving these operation on the GPU could further reduce the need for costly memory transfers, allowing all computations to "reside" on the device for 10 computational diffusion steps (with size ∆t diff ∼ 0.01 min) without need for memory transfer. Second, cell mechanics operations are governed by biased random migration and interaction potentials, which are well-suited to GPU computations [43]. Furthermore, there are 60 mechanics steps (with step size ∆tmech ∼ 0.1 min) for every cell step (with size ∆t cell ∼ 6 min). Thus, moving cell mechanics solvers would not only accelerate those computations, but drastically re-duce the the need for host-device memory transfers: computations could "reside" on the device for 600 computational steps before transferring data to host memory.
Future work will explore these refinements. Biological diffusion-which present work accelerated by a factor of 40-accounts for approximately 65% of execution time in typical simulations. Cell updates-dominated by 10 mechanics steps for every biological step-accounts for another 25-30% of execution time. If the mechanics code (approximately 25% of original execution time) could be similarly accelerated by a factor of 40, then the overall simulation execution time should be reduced on the order of 85-90%: a substantial speedup.
A 10× to 100× speedup would enable exciting new scientific possibilities. If simulation sizes were left unchanged, then the speedup would enable much faster execution times for individual simulations; this is critical for data assimilation and parameter estimation techniques like approximate Bayesian computing that must rapidly run many simulations sequentially. Similarly, leaving the simulation size unchanged, we could simulate to longer times, which will be of great use to digital twin efforts in medicine. If execution time were left unchanged, then larger domains with more agents could be simulated, enabling studies of more complex tissues and even small organisms. Lastly, the increased "computational budget" afforded by a more complete GPU acceleration could allow us to introduce multiple agents per biological cell allowing sophisticated simulations of not only cell morphology (e.g., as in subcellular element models [1], [44]), but even introducing agents for subcellular components and biophysical processes, such as movement, fission, and fusion of Golgi bodies during signaling [45], [46]. This could be transformative in relating emerging high-resolution microsopy [47], [48] to intracellular biophysics and functional biology.