# Robust 3D Joint Inversion of Gravity and Magnetic Data: A High-Performance Computing Approach
## 2 Methods
### Coding Guidelines  
For the computational implementation, memory management, the number of calculations to be performed, and the size of the arrays involved in operations were considered important points to optimize and achieve better performance. The Fortran 2008 standard [79] was used as the programming language because (1) it allowed the management of the memory size used by each array in a simple way, (2) also allowed to implement of the parallelization of matrix-vector type multiplications through the recently (2021) released free Compute Unified Device Architecture (CUDA) Fortran libraries within the Nvidia Corporation (NVIDIA) (Santa Clara, CA, USA) high-performance computing software development kit (HPC SDK v23.9), (3) as well as better performance compared to other high-level programming languages without complicating its parallel programming thanks to the similar syntax between the language and the parallelization library in contrast with other low-level programming languages. CUDA is a general parallel computing library developed by NVIDIA, which is a powerful tool compatible with popular programming languages. Although it is convenient to process with concatenated arrays and vectors to describe the procedure, it was decided to perform the calculations of each type of geophysical data separately. This allowed to reduce the size of all the matrices to be multiplied by 50% since 2/4 parts of the concatenated matrices are filled with zeros. This implied performing a larger number of operations, but smaller in size, allowing faster processing and using a smaller amount of memory to store the temporary arrays. Even with these considerations, the memory usage and processing time grow exponentially as the inversion domain increases, depending on the number of cells to be processed and not on their dimensions. In order to take full advantage of the computational power available during the modeling process, three different routines were programmed: A single-core version on the Central Processing Unit (CPU) with the amount of RAM available as the only limiting factor for the inversion domain size at the request of very long processing times, which has been compiled with two different compilers, gfortran and nvfortran, and showed consistently to be at least 4\(\times\) times faster (Table 1). A parallel version that uses the Graphics processing unit (GPU) to perform all matrix-vector multiplications in the process in parallel, which is many times faster at the cost of relying on the amount of available VRAM memory, a much more difficult computational resource to obtain in large quantities. Finally, a CPU-GPU hybrid version aims to be a balance between speed and resource usage by performing only the calculations of structural similarity regularizer in parallel. Table 1 summarizes the performance of different processing routines for different inversion domain sizes based on RAM usage, VRAM usage, processing time, and how many times faster it is compared to the slower single-core version. Meanwhile, a visual comparison is presented in Figure 2. Performance tests were conducted on an easy to access desktop hardware (CPU: Ryzen 53600 3.95 GHz, GPU: NVIDIA 2060 super with 2176 CUDA cores and 8 GB VRAM; Memory: 2 \(\times\) 16 GB), and processing times may vary in a different setup.