A
可以被表示为A(i,j,k)
,其中每个索引的范围从零到某个上限,并且内存中每个元素的位置如下所示:A(i,j,k) = A0 + i * A_stride_i + j * A_stride_j + k * A_stride_k
其中A0
是基本指针,A_stride_i
等是维度步长。
由于这些数据集可能是其他数据集的子集,而不是各自占用独立的malloc'ed内存块,因此它们可能重叠(其中重叠意味着A(i,j,k) < B(m,n,p)
既不总是真也不总是假),如果它们重叠,则它们可能相互交错或相互碰撞(其中碰撞意味着某些六元组索引的A(i,j,k) == B(m,n,p)
)。
问题就在这里。对于两个数据集的一些操作(例如复制),仅当数组彼此不发生碰撞时才有效,但如果它们以交替的非碰撞方式重叠,则有效。我想为两个数据集添加一个函数,判断它们是否发生碰撞。
是否存在一种现有算法可以以合理高效且简单的方式执行此操作?
检查数据集是否重叠相当容易,因此关键问题是:给定这种形式的两个重叠数据集,有什么有效的算法可以确定它们是否交错或碰撞?
示例:
作为一个简单的例子,假设我们有从0到F(十六进制)的内存位置:
0 1 2 3 4 5 6 7 8 9 A B C D E F
为了简单起见,我在这里只考虑二维数组。假设我们有一个大小为2,3的数组(即,0 <= i < 2
和0 <= j < 3
),其中stride_i = 1
,stride_j = 4
,基地址为2。它将占用以下位置(其i,j对表示已占用位置):
0 1 2 3 4 5 6 7 8 9 A B C D E F
* * * * * *
同样地,如果我们有另一个大小和步幅相同的数组,从基地址为4开始,它将如下所示:
0 1 2 3 4 5 6 7 8 9 A B C D E F
o o o o o o
在我描述问题时使用的术语中,这些数组“重叠”,但它们不会发生冲突。
限制和假设:
我们可以假设步幅为正数,并且如果需要,它们按递增顺序排列。虽然实际库中没有这两个条件,但重新排列数组定义以达到这一点相当简单。
我们可以假设数组不自我交错。这也没有被库强制执行,但会是一个病态情况,并且可以单独进行警告。即(假设步幅按递增顺序排列,i从零到max_i等):
stride_j >= max_i * stride_i stride_k >= max_j * stride_j
当然,对于不需要这些假设的方法,我们会给予加分,因为将数组定义重新排列为规范顺序是一项有点费力的工作,最好避免。
这两个数组不能假定具有相等的大小或步幅。
我认为在构建过程中跟踪事物没有价值——在测试时不存在构建时不存在的信息。此外,“构建”可能仅仅是“考虑具有此基指针、这些步幅和这些大小的较大数组的子集”。
最坏情况:
svick的答案提醒我应该添加一些关于我预计出现的一些典型“更糟”的情况的内容。其中最糟糕的情况之一是当我们有一个数组,表示一些非常大的复数值,存储在连续的(实数,虚数)对中,然后我们有两个子数组分别包含实部和虚部——因此,您在数组中有几百万个元素,在这些数组之间交替出现。由于这不是一个不太可能的情况,所以应该能够用除了极差性能之外的其他东西进行测试。
A_stride_j >= max(k) * A_stride_k
这样可以确保数组没有交错。 - svick