dot product. Each of the $b$ GPU threads loads one element of $\boldsymbol{v}$ and one element of $\boldsymbol{x}$, multiplies them together, and stores the thread-local result in shared memory. The final dot product is obtained by a parallel reduction involving all the threads in a block.

    2.  Update $\boldsymbol{x}$ by $\boldsymbol{x} = \boldsymbol{x} - \tau (\boldsymbol{v}^* \boldsymbol{x}) \boldsymbol{v}$. Again, only $b$ elements of $\boldsymbol{x}$ are modified. Since the dot product $\boldsymbol{v}^* \boldsymbol{x}$ has already been computed and $\tau$ is a scalar, this update can be done in a straightforward element-wise fashion, i.e., each thread updates one element of $\boldsymbol{x}$.

3.  Among the $b$ elements of $\boldsymbol{x}$ that are updated by the first Householder transformation, only the lowest element will not be affected by the next Householder transformation. Before applying the next transformation, the last thread in each block writes its element of $\boldsymbol{x}$ into $\boldsymbol{X}_\text{local}$. Then thread $i$ ($i>=1$) takes the element of $\boldsymbol{x}$ from thread ($i-1$), while thread 0 loads a new element from $\boldsymbol{X}_\text{local}$.

4.  Now all threads are ready to repeat steps 1, 2, and 3 for the next Householder transformation.

5.  The CUDA kernel finishes when all transformations are applied. The updated $\boldsymbol{X}_\text{local}$ is then copied 