在不少高性能计算中,矩阵转置扮演了一个使用比较频繁的角色。因此如果在某个处理过程中,矩阵转置占的比重比较大,且算法没设计好的话就可能会成为该处理过程的计算瓶颈。这里我将介绍向量化矩阵转置的算法过程。
为了简单、清晰地介绍如何向量化矩阵转置,我们这里使用4x4、以行为主的矩阵作为例子进行讲解。我们假设有这么一个矩阵:
[ a b c d
e f g h
i j k l
m n o p ]
那么这个矩阵转置后的形式应该是:
[ a e i m
b f j n
c g k o
d h l p ]
我们在处理过程中,往往先用四个向量寄存器将每一行的四个元素数据先读取出来。我们这里就假设vec1读取(a, b, c, d)这一向量;vec2读取(e, f, g, h)这一向量;vec3读取(i, j, k, l)这一向量;vec4读取(m, n, o, p)这一向量。然后,我们需要将这四个向量中的数据元素做相应整理,然后再写回相应的存储地址中。
我们可以先观察源矩阵与目的矩阵之间的关系,然后再结合vec1到vec4这四个向量寄存器中的数据元素的排布,可以先发现,目的矩阵的第一行头两个元素分别是vec1的第一个元素和vec2的第一个元素;目的矩阵第二行的头两个元素分别是vec1的第二个元素和vec2的第二个元素。目的矩阵的第三、第四行的头两个元素也可以此类推,这样我们可以先对vec1与vec2做转置操作,可得到——vec1 = (a, e, b, f);vec2 = (c, g, d, h)。
而目的矩阵第一行的后两个元素分别是vec3的第一个元素与vec4的第一个元素,我们可以跟上面一样,以此类推,将vec3与vec4做一次转置操作,得到——vec3 = (i, m, j, n); vec4 = (k, o, l, p)。这样,矩阵转置的第一步就完成了。
我们接下去再看vec1与vec3的关系,可以得出vec1的头两个元素与vec3头两个元素结合在一起就能直接得到目的矩阵的第一行元素,而后面的也同样如此。所以我们对vec1与vec3做一次双元素的转置操作,可以得到——vec1 = (a, e, i, m); vec3 = (b, f, j, n)。同样,vec2与vec4也执行一次双元素的转置,最终获得vec2 = (c, g, k, o); vec4 = (d, h, l, p)。最后,我们再依次将vec1、vec3、vec2、vec4向量寄存器写入相应的存储地址即大功完成。