请移步zhuanlan.zhihu.com/p/302208545… 观看原文。
命题:如果有一个n维行优先的数组的shape为shapeo×shape1×...×shapen−1,对于线性索引为L,,如果其满足
L=index0×stride0+index1×stride1+index2×stride2+...+indexn−1×striden−1
,则有:
index0=⌊stride0L⌋
证明:
假如index0>⌊stride0L⌋,不妨设index0=⌊stride0L⌋+1,,则有index0∗stride0=(⌊stride0L⌋+1)∗stride0>L,这和 L=index0×stride0+index1×stride1+index2×stride2+...+indexn−1×striden−1的前提相矛盾,故假设不成立。
假如index0<⌊stride0L⌋,不妨设index0=⌊stride0L⌋−1,则有:
index0∗stride0+index1∗stride1+index2∗stride2+...+indexn−1∗striden−1=(⌊stride0L⌋−1)∗stride0+index1∗stride1+index2∗stride2+...+indexn−1∗striden−1
由于有(⌊stride0L⌋−1)∗stride0≤L−stride0,故上式有:
(⌊stride0L⌋−1)∗stride0+index1∗stride1+index2∗stride2+...+indexn−1∗striden−1≤L−stride0+index1∗stride1+index2∗stride2+...+indexn−1∗striden−1
假如index1...indexn−1都取最大值,那么对于第k个维度而言, 由于stridek=∏m=k+1n−1shapem,所以有:
(shapek−1)stridek=(shapek−1)m=k+1∏n−1shapem=m=k∏n−1shapem−m=k+1∏n−1shapem,k≤n−2(shapek−1)stridek=shapen−1−1,k=n−1
故将第二个维度及其之后的维度的shape最大值及其stride相乘有下式:
k=1∑n−1(shapek−1)stridek=k=1∑n−2(m=k∏n−1shapem−m=k+1∏n−1shapem)+shapen−1−1=m=1∏n−1shapem−1<stride0
所以
L−stride0+index1∗stride1+index2∗stride2+...+indexn−1∗striden−1<L−stride0+m=1∏n−1shapem−1<L−stride0+stride0=L
亦即:
(⌊stride0L⌋−1)∗stride0+index1∗stride1+index2∗stride2+...+indexn−1∗striden−1≤L−stride0+index1∗stride1+index2∗stride2+...+indexn−1∗striden−1<L
这和前提相矛盾,故假设不成立。
所以命题得证。
通过这个命题,我们可以从线性索引求得逻辑索引,首先通过⌊stride0L⌋求index_0,有:
L=⌊stride0L⌋×stride0+index1×stride1+index2×stride2+...+indexn−1×striden−1
之后,设offset=L−⌊stride0L⌋×stride0=L%stride0,则有:
offset=index1×stride1+index2×stride2+...+indexn−1×striden−1
用同样的方法,我们可以求得index1、index2、.....indexn−1,
这在写CUDA算子,如cat算子等的时候特别有用,从tid算得本线程要负责的元素的逻辑索引,从而进行相关拷贝操作。