# Calculating the Moore-Penrose Generalized Inverse on Massively Parallel Systems
## 6 Computational Experiment and Analysis  
To test the efficiency gained by using the GPU algorithm described in this paper, we measured and compared the execution time of the parallel algorithm from Section 5 that runs on the GPU and the serial algorithm that runs on the CPU (we used the cuBLAS library for matrix multiplication on the CPU). We also compared our implementation with the  
Figure 6: Step 1 of [PERSON]’s matrix inverse algorithm: CUDA version. algorithm that uses the SVD to calculate the pseudoinverse: we used the algorithm from the OpenCV library (v.4.5.5, Intel Corporation, Santa Clara, USA) [46], which is executed solely on the CPU, and the algorithm from the PyTorch library (Linux Foundation, San Francisco, CA, USA) [47], which uses the GPU and CUDA internally. We compared the results for matrices of various shapes and both single and double precision. Tables 1 and 2 show the average time in milliseconds needed for calculating the Moore-Penrose generalized inverse for the float and double matrices, respectively, using the different algorithms and computing architectures. The OpenCV and PyTorch implementations are labeled as CPU-SVD and GPU-SVD, respectively. The recursive algorithm discussed in Section 5 is labeled as R and for the execution on the GPU, we measured the execution time of the algorithm that uses a custom matmul kernel (GPU-R-v1) and the algorithm where matrix multiplication is performed using the cuBLAS library (GPU-R-v2). The values in the table represent the mean of five measurements. Note that we measured only the time needed to calculate the pseudoinverse, not the time needed to transfer the memory between the CPU and GPU. Figures 7 and 8 show the data included in Tables 1 and 2 for the float and double data types, respectively. The tests were performed on a computer that has GeForce GTX 1080 Ti GPU, Intel(R) Core(TM) i7-9700 CPU 3.00 GHz (Santa Clara, CA, USA), and 16 GB of DDR4 ram memory (JEDEC, Arlington, VA, USA) (2400 MT/s speed). We used CUDA 11.7, cuBLAS 3.10, PyTorch 1.12.1 (with CUDA 10.2), and OpenCV 4.6. It can be observed that the recursive implementation was faster than the SVD-based algorithm even when comparing CPU-R and GPU-SVD. The CPU implementations were notably faster for small matrices (with approximately less than 25,000 elements). For the larger matrices, we found that the CPU-R algorithm still outperformed GPU-SVD and was comparable to GPU-R-v1. However, when working with matrices with a few million elements (3072 \(\times\) 2048), the implementation of matrix multiplication on the GPU becomes more important, especially in the case of double-precision multiplications, where GPU-R-v2 outperformed all the other algorithms. This gap further increased when working with \begin{table}
\begin{tabular}{c c c c c c} \hline \hline \multirow{2}{*}{**Matrix**} & \multicolumn{5}{c}{**Float**} \\ \cline{2-6}  & **CPU-SVD** & **CPU-R** & **GPU-SVD** & **GPU-R-v1** & **GPU-R-v2** \\ \hline \(12\times 8\) & 0 & 0 & 1 & 0 & 1 \\ \(48\times 32\) & 0 & 0 & 1 & 3 & 4 \\ \(192\times 128\) & 7 & 1 & 4.2 & 13.2 & 16 \\ \(384\times 256\) & 59.6 & 3.8 & 10.4 & 26.8 & 32.2 \\ \(768\times 512\) & 474 & 23.6 & 28.8 & 57.4 & 65.8 \\ \(1536\times 1024\) & 3749.4 & 95 & 117.8 & 128.8 & 135.2 \\ \(3072\times 2048\) & 30,734.6 & 437 & 704.2 & 343.8 & 294 \\ \(6144\times 4096\) & 246,801.8 & 2597.4 & 5993.2 & 1392 & 720.2 \\ \hline \hline \end{tabular}
\end{table} 
Table 1: Time in milliseconds to calculate the pseudoinverse for float (single precision) matrices.