maximize the use of the reflectors which have been stored in registers. Figure \[fig:qr\_fig\] shows one step of a panel factorization and the application of its reflectors to the trailing submatrix. Since threads are limited to 1024 per block on current architectures, we use the approach developed in [@journals/concurrency/KurzakLDB10] to factorize larger matrices. We first factorize panels up to the thread block limit in a single kernel call. The panels below the first are then factorized by first loading the triangular factor into shared memory and then proceeding with the panel factorization as before, taking the triangular portion into consideration when computing reflectors and updates. To keep occupancy up for the small matrices on devices where the resident block limit could be reached before the thread limit, we assign multiple operations to a single thread block. For a batch of $N$ matrices of dimensions $m \times n$, kernels can be launched using $N/b$ thread blocks of size $m \times b$, where each thread block handles $b$ operations.

![Left: matrix rows allocated to thread registers in a warp. Right: parallel warp reduction using shuffles within registers.[]{data-label="fig:register_storage_reduction"}](reg_svd.pdf){width="0.6\linewidth"}

![One step of the QR factorization where a panel P is factored to produce a 