行主序下多维度张量间索引转换公式咨询
行主序下多维度张量间索引转换公式咨询
嗨,这个问题的核心其实是行主序(row-major)存储规则下的多维索引与线性索引的双向转换,不管两个张量的维度数谁多谁少,都可以通过「先转线性索引,再转目标多维索引」的两步法搞定,咱们一步步说清楚:
核心思路
因为两个张量的元素总数完全相同,所以它们的元素在内存里的行主序排列是一一对应的——先把原张量的多维索引转换成全局的线性索引(也就是元素在内存中的位置偏移,从0开始计数),再把这个线性索引转换成目标张量的多维索引即可。
第一步:从原张量A的多维索引计算线性索引
假设A是m维张量,维度为 m₁ × m₂ × ... × mₖ,给定的多维索引是 (i₁, i₂, ..., iₖ)(索引从0开始),行主序下的线性索引idx计算公式为:
idx = i₁ × (m₂×m₃×...×mₖ) + i₂ × (m₃×...×mₖ) + ... + iₖ₋₁ × mₖ + iₖ
简单来说,就是每个维度的索引,乘以它右侧所有维度的乘积(这个乘积也叫该维度的「步长」),最后把所有项相加。
拿你的例子验证:
A的维度是2×2×2,索引是(1,0,0):
- 第一个维度的步长:
2×2=4 - 第二个维度的步长:
2 - 第三个维度的步长:
1
计算得:idx = 1×4 + 0×2 + 0×1 = 4
第二步:把线性索引转换成目标张量B的多维索引
假设B是n维张量,维度为 n₁ × n₂ × ... × nₜ,现在要把线性索引idx转换成多维索引(j₁, j₂, ..., jₜ),需要从最右侧的维度开始,依次取余和整除:
- 计算最右侧维度的索引:
jₜ = idx % nₜ,然后更新idx = idx // nₜ(整除,向下取整) - 往左推一个维度:
jₜ₋₁ = idx % nₜ₋₁,更新idx = idx // nₜ₋₁ - 重复这个过程,直到所有维度的索引都计算完成,最后剩下的
idx就是最左侧的j₁
再拿你的例子验证:
B的维度是2×4,线性索引是4:
- 先算右侧的j₂:
4 % 4 = 0,更新idx = 4 // 4 = 1 - 再算左侧的j₁:
1 % 2 = 1,更新idx = 1 // 2 = 0
最终得到B的索引是(1, 0),和预期一致。
关于维度数m和n的差异
不管是m > n(原张量维度更多)还是m < n(目标张量维度更多),这个两步法都是通用的:
- 如果m > n:比如A是3维,B是2维,第一步转线性索引,第二步分解成2维即可
- 如果m < n:比如A是1维(线性索引就是本身),B是3维,直接用第二步把线性索引分解成3维索引就行
小补充:索引从1开始的情况
如果你的张量索引是从1开始计数的,只需要在计算前把每个索引减1(转成0基索引),完成转换后再把结果加1即可,核心逻辑不变。
备注:内容来源于stack exchange,提问作者user366312




