我有一个沿对角线存储在平面缓冲区中的二维矩阵。例如,一个 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
我们在这里假设永远不会发生溢出并且没有回绕。
我有一个涉及很多三角数的解决方案和三角根计算的解决方案。它还包含很多分支,如果可能的话,我更愿意用代数代替(这将在分散控制流很昂贵的 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 边展平)也将是一个很大的优势。