多维度数组寻址

在进行并行编程,如cuda编程,进行grid、block、thread等索引和实际的计算多维数组对应时,如模型输出后对内存上的输出排列按照特定的数组结构进行分解时,往往都会设计数组地址的计算。
在内存中,数据都是一维度线性存在的,但我们在写程序时,往往会按照二维、多维的逻辑进行计算,这就涉及到底层一点的代码,会有多维索引和实际内存地址的相互转换。

一维数组内存地址转换

这个没太多说的,和实际内存排列一致,也就是偏移是一致的,一般加个内存起始地址就对应上了。

二维数组内存地址转换

这里要说明一个约定俗成的说法:一般写法array[…][z][y][x] 即多维数组,从左往右,越右边的轴越内层,比如x在这里就是最内层的轴,即代表了该数组最小单元里有多少个元素。
对于二维数组array[y][x] 常见的x,y轴排列,可以想象成一页,一页有行和列。x和y没必要非得去对应行或者列,x对应行也好,对应列也好,只是一个叫法。所以为什么会有轴这个叫法,也是翻译过来的,x轴和y轴,代表了不同层级的元素数量。比如x轴这里是最内层的元素数量,y作为更高一层的,代表了有y个x轴。如果还有z轴,代表了有z个y轴的数量(y轴就像页了,有y个x轴组成),以此类推更多维度。
所以对于二维数组array[y][x]的内存如何计算?可以想象成一页,最内层的x在某一行的位置,那么前边所有行可以理解成是满的,那么当前数组索引对应的实际内存地址应该是前边所有行满的数量加上当前行的即x的值。
轴是从0开始计算的,所以y的值代表了实际前边已经满的行数量,x的值是最后行里的实际位置。也可以理解成偏移量。所以内存地址为y_value*dimx+x_value

三维数组内存地址转换

前边二维想象成页的话,三维可以想象成立方体了,其中的一页页(xy轴)堆叠起来,这个一页页的数量就代表了z轴的值。
所以,z本身的值就是前边所有满的页,在加上最后页的计算(同理二维时的计算),就是最终三维的计算了.所以三维度数组就是:z_value*dimx*dimy+y_value*dimx+x_value,

多维数组内存地址转换

有了前边二维到三维的层层递进,就不难理解更多的多维度了,反正就是从最外层往最内层一层层推即可。以最外层轴的数值乘以所有内层轴的维度数,层层计算最后累加即可。
有个注意的点儿就是,当轴为1时,其值就只能是0,那么,比如三维数组的z轴是1,那么根据公式:z_value*dimx*dimy+y_valuedimx+x_value, 其中z_value只能是0,所以就可以简化为:y_valuedimx+x_value,进一步的,对于轴为1的情况,在计算内存地址时是可以省略掉。

正在加载今日诗词....