【发布时间】:2013-04-17 20:17:58
【问题描述】:
我有一个沿对角线存储在平面缓冲区中的二维矩阵。例如,一个 4x4 矩阵的索引会像这样分散:
0 2 5 9
1 4 8 12
3 7 11 14
6 10 13 15
使用这种表示法,在给定原始索引和 X/Y 偏移量的情况下,计算相邻元素索引的最有效方法是什么?例如:
// return the index of a neighbor given an offset
int getNGonalNeighbor(const size_t index,
const int x_offset,
const int y_offset){
//...
}
// for the array above:
getNGonalNeighbor(15,-1,-1); // should return 11
getNGonalNeighbor(15, 0,-1); // should return 14
getNGonalNeighbor(15,-1, 0); // should return 13
getNGonalNeighbor(11,-2,-1); // should return 1
我们假设这里永远不会发生溢出并且没有回绕。
我有一个涉及大量triangular number 和三角根计算的解决方案。它还包含许多分支,如果可能的话,我更愿意用代数代替(这将在分散控制流很昂贵的 GPU 上运行)。我的解决方案有效,但非常冗长。我觉得必须有一种更简单且计算密集度更低的方式来做到这一点。
如果有人可以为这个特定的问题/表示命名,也许会对我有所帮助。
如果有人感兴趣,我可以发布我的完整解决方案,但正如我所说,对于这样一个简单的任务来说,它很长而且相对复杂。简而言之,我的解决方案是:
- 将原始索引转换为更大的三角矩阵以避免处理 2 个三角形(例如 13 将变为 17)
对于 4x4 矩阵,这将是:
0 2 5 9 14 20 27
1 4 8 13 19 26
3 7 12 18 25
6 11 17 24
10 16 23
15 22
21
- 使用偏移的曼哈顿距离和索引的三角根计算此表示中邻居对角线的索引。
- 使用偏移量计算邻居在这条对角线上的位置
- 通过删除填充转换回原始表示。
出于某种原因,这是我能想到的最简单的解决方案。
编辑:
有循环累积偏移量:
我意识到,考虑到三角形数字的属性,将矩阵分成两个三角形会更容易(让我们称 0 到 9 '上三角形'和 10 到 15 '下三角形')并有一个循环在内部进行测试,通过在上三角加一并在下三角减一(如果有意义的话)来累积偏移量。但对于我的解决方案,必须不惜一切代价避免循环,尤其是行程计数不平衡的循环(再次,非常对 GPU 不利)。
所以我更多的是寻找代数解决方案而不是算法解决方案。
构建查找表:
同样,由于 GPU 的原因,最好避免构建查找表并在其中进行随机访问(非常昂贵)。代数解更可取。
矩阵的性质:
- 矩阵的大小是已知的。
- 目前我只考虑方阵,但矩形矩阵的解决方案也不错。
- 正如我示例中的函数名称所暗示的,将解决方案扩展到 N 维体积(因此 N 边形展平)也将是一大优势。
【问题讨论】:
-
查看模式:0 2 将始终是第一行中的第一个元素,然后对于每个 (0,j) s.t. j 大于 1,它增加了 +1( 2+3 =5, +4 =9, +5 = 14...) 与第一列相同。再想一想,在查看列号和移动column-column时给出了模式。生病尝试更好地解释:0,1,3,6,10 每次增加 x+1。对于第 1 列(以 2 开头),您以 +2、+3、+4 开头,每列都相同
-
您似乎在描述上三角形的行为(在这种情况下,索引小于 9)。问题是下三角形会发生变化,如果索引在一个三角形中而邻居在另一个三角形中,则会变得混乱。这就是为什么我将整个矩阵包装在一个三角形矩阵中并使用您描述的属性。
-
我正在查看问题开头的 4x4 矩阵。
-
上三角和下三角我的意思是如果你把矩阵分成两个三角形:从 0 到 9 和 10 到 15。你所描述的看起来像三角形数字序列,当你从一个开始时它会中断这些三角形的另一个。以 10 为例,上面的元素是 7,它在第 4 条对角线上,但 10-4=6。
-
所以在对角线之后它反转并与 x-1 一起
标签: c++ c multidimensional-array indexing diagonal