1

我正在为我的 3D 几何库开发一个 4x4 矩阵 C++ 类。我对如何以更有效的方式表示矩阵数据值有些困惑。

那是因为矩阵和四元数常见问题解答说:

使用二维数组也会导致 CPU 性能损失,因为 C 编译器通常会使用乘法运算来解析数组索引操作。因此,坚持使用线性阵列会更有效。

  1. 访问多维数组真的比线性数组慢吗?
  2. 我真的应该更喜欢线性数组而不是多维来存储 4x4 矩阵数据值吗?
4

2 回答 2

3

我知道的大多数实现都使用带有包装器的 1D 数组,或者通过 MACROS 或方法来访问 2D 数据。我自己不能说哪个更快,我几乎看不出这真的很重要。

然而,话虽如此,我仍然建议使用一维数组,原因如下:

  1. 更容易动态分配和释放(如果您想动态分配数据并维护 matrix[i][j] 模式,那么您正在分配一个数组数组 - 分配速度较慢更容易出现错误,您必须分别释放每个数组)
  2. 如果您动态分配并且必须将数据复制到 3d 方库,例如 OpenGL 或 OpenCV,您就会遇到一些麻烦,因为它们需要数据是连续的。
  3. 从文件或其他持久存储中存储和读取矩阵会更容易。
  4. 即使您不动态分配,您也必须进行各种丑陋的铸造来处理将内存转移到 3d 方库。
  5. 使用方法创建结构非常容易,无需乘法或不明确的索引即可有效地二维访问您的数据。或者就此而言,使用 MACROS 为您封装丑陋的乘法。
  6. 您甚至可以创建一个看起来像下一个示例的结构,并保持一维数组的相同优点和二维数组的可读性:

template<typename T>
struct Matrix4x4
{
    struct index
    {
        int row, col;
        index(int r = 0, int c = 0)
            : row(r), col(c){}
        index(index const & cp)
            : row(cp.row), col(cp.col)
        {
        }
        //Assignment ommited for brevity
    };
    /*
        Constructors, Assignments etc. ommited for brevity
    */
    T m00, m01, m02, m03;
    T m10, m11, m12, m13;
    T m20, m21, m22, m23;
    T m30, m31, m32, m33;

    T * toArray() const
    {
        return &m00;
    }
    T * toArray()
    {
        return &m00;
    }

    T * row(int r)
    {
        return (&m00) + r*4;
    }
    T * row(int r) const
    {
        return (&m00) + r*4;
    }

    T & operator()(int r, int c)
    {
        return *row(r)[c];
    }
    T const & operator()(int r, int c) const
    {
        return *row(r)[c];
    }

    T & operator[](index const & idx)
    {
        return row(idx.row)[idx.col];
    }
    T const & operator[](index const & idx) const
    {
        return row(idx.row)[idx.col];
    }

};

在您的代码中,您可以执行以下操作:

typedef Matrix4x4<double> Matrix4x4d;

Matrix4x4d mat;
/* You can do any of the following */
mat.m23 = 6.0;
mat(2,3) = 6.0;
mat[Matrix4x4d::index(2,3)] = 6.0;
mat.row(2)[3] = 6.0;
mat.toArray()[2*4 + 3] = 6.0;

#define M(m,r,c) (*((&m.m00) + r*4 + c))

M(mat,2,3) = 6.0;

多年来,我自己实现了几个矩阵库,并且总是选择一维解决方案。

于 2012-11-10T14:58:35.627 回答
0

您可以在第一维中存储指向一维数组的指针,然后在第二维中存储具有行长的一维数组。

据我回忆,间接比乘法成本更低。

访问/编辑成员的语法是相同的。唯一的区别是分配/解除分配数组的时间。

于 2012-11-06T19:47:30.320 回答