number of resident blocks become limited by the registers/block limits of the device, dropping to 2 and then 1 resident blocks. Performance increases steadily from there as we increase the number of threads assigned to the operation until we reach a matrix size of $64 \times 64$ where we reach the block limit of 1024 threads. To handle larger sizes, we must use a blocked version of the algorithm or the randomized SVD as we see in Sections \[sec:block\_global\] and \[sec:randomized\], respectively.

[0.45]{} ![Performance of the batched shared memory SVD on a P100 GPU for 1000 matrices of varying size in single and double precision arithmetics.](smem_perf_1.pdf "fig:")

[0.45]{} ![Performance of the batched shared memory SVD on a P100 GPU for 1000 matrices of varying size in single and double precision arithmetics.](smem_perf_2.pdf "fig:")

Global Memory One-Sided Block Jacobi {#sec:block_global}
====================================

When we can no longer store the entire matrix in shared memory, we have to operate on the matrix in the slower global memory. Instead of repeatedly reading and updating the columns one at a time, block algorithms that facilitate cache reuse have been developed [@bevcka1999block1; @bevcka1999block2; @bevcka2015new]. The main benefit of the block Jacobi algorithm is its high degree of 