【问题标题】:Quick access to a cell in 2D matrix which wraps around快速访问环绕的二维矩阵中的单元格
【发布时间】:2016-12-15 10:13:27
【问题描述】:

我有一个环绕的矩阵。

m_matrixOffset 指向环绕矩阵的第一个单元格(0, 0)。因此,要访问一个单元格,我们有下面的函数 GetCellInMatrix 。每次有人访问一个单元格时都会执行回绕(在 while 循环中)的逻辑。每秒执行数千次。有没有办法使用一些查找或其他方式来优化它。 MAX_ROWS 和 MAX_COLS 可能不是 2 的幂。

struct Cell
{
    Int rowId;
    Int colId;
}
int matData[MAX_ROWS][MAX_COLS];


int GetCellInMatrix(const Cell& cellIndex)
{
        Cell newCellIndex = cellIndex + m_matrixOffset ;

        while (newCellIndex.rowId > MAX_ROWS)
        {
            newCellIndex.rowId -= MAX_ROWS;
        }

        while (newCellIndex.colId > MX_COLS)
        {
            newCellIndex.y -= MAX_COLS;
        }

    return data[newCellIndex.rowId][newCellIndex.colId];
}

【问题讨论】:

    标签: c++ math matrix


    【解决方案1】:

    您可能对余数除法的概念感兴趣,通常实现为a % b 表示余数。

    这样

    return data[newCellIndex.rowId % MAX_ROWS][newCellIndex.colId % MAX_COLS];
    

    它之前不需要while 循环。


    根据评论,如果在每个查询中都进行余数计算,则隐含的整数除法成本太高。假设m_matrixOffset 在大量查询中保持不变,则使用余数运算减少其坐标一次。那么newCellIndex 小于最大值的两倍,因此最多只需要减少一次。因此,将while 替换为if 是安全的,无需进行比较。


    如果您可以牺牲内存换取空间,则将矩阵维度加倍并用重复的矩阵元素填充多余的条目。在更新矩阵时,您必须确保此模式成立。

    然后,再次假设 m_matrixOffsetCellIndex 都在行和列的最大值之内,您可以访问扩展矩阵的单元格而无需进一步缩减。这将是“查找表”想法的一种变体。


    或者使用真正的查找表,但是您随后执行 3 个数组单元格查找,如

    return data[repeatedRowIndex[newCellIndex.rowId]][repeatedColIndex[newCellIndex.colId]];
    

    【讨论】:

    • 我们早先这样做了,但这会导致性能问题,因为这在 CPU 上的开销很大。由于我们访问细胞数千次(如果不是数百万次),因此它不是最优的
    • 那么你需要分别获得资格。量化矩阵偏移量。如果您可以保证矩阵偏移量也小于矩阵维度(通过计算一次余数),那么您有最大值。减一,可以将while替换成if,比一比省力。
    【解决方案2】:

    这取决于包裹相对于矩阵是小还是大。

    最常见的情况是您只需要最近的邻居。因此,将矩阵 N+2 乘以 M+2 并复制换行。这使得读取速度快,但写入有点繁琐(通常是一个很好的权衡)。

    如果这样不好,请专门化功能。找出哪些单元是边缘单元并进行特殊处理(您必须能够做到这一点,而不是简单地将逻辑硬编码到访问中,当然,如果只有一个或两个单元更改每个将保持的通道,而不是如果您每次通过生成一个随机列表)。

    【讨论】:

    • 你的意思是如果有一个矩阵 (512, 512),我需要一个环绕矩阵 (1024, 10234)?
    • 通常的模式是我们在矩阵上有一个随机点,我们需要所有的邻居。因此,如果我们将矩阵设为 514 x 514 而不是 512 x 512,我们就不需要特殊的代码来读取邻居。支持更远的邻居变得越来越昂贵。
    猜你喜欢
    • 2022-11-16
    • 1970-01-01
    • 2010-12-30
    • 1970-01-01
    • 2017-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-11
    相关资源
    最近更新 更多