【问题标题】:What is the better Matrix4x4 class design c++ newbie什么是更好的Matrix4x4类设计c++新手
【发布时间】:2013-04-04 11:18:08
【问题描述】:

用什么方法来存储矩阵值会更好?

float m1,m2,m3 ... ,m16

float[4][4].

我首先尝试了 float[16],但是当我在调试和测试时 VS 不会显示数组内部的内容 :( 可以实现 cout 并尝试从控制台测试应用程序读取答案。

然后我尝试使用 float m1、m2、m3 等进行测试和调试,这些值可以在 VS 中读取,因此看起来更容易使用。

我的问题是因为我对 c++ 相当陌生,什么是更好的设计?

我发现float m1,m2 ... ,m16 在调试时更易于使用。

如果有人可以根据经验说或者有基准数据,我的直觉认为这并不重要,因为矩阵数据在内存中的布局应该相同,所以我会很高兴吗?

编辑: 更多信息是列主矩阵。 据我所知,视图转换管道只需要一个 4x4 矩阵。 所以没什么大不了的,所以我有一些恒定的值。

忙于编写一个简单的软件渲染器,以此来学习更多 c++ 并获得更多经验并学习/提高我的线性代数技能。可能只会使用每个片段着色和一些简单的照明模型,到目前为止,我已经看到 4x4 矩阵是我渲染所需的最大矩阵。

编辑2: 发现为什么我无法读取数组数据,它是我使用的浮点指针,调试菜单只显示指针值我确实发现了一种在手表中查看数组值的方法,你必须在哪里做指针,n 其中 n =你想看到的元素。

所有回答谢谢的人我现在将使用 Vector4 m[4] 答案。

【问题讨论】:

  • 在 VS 调试中甚至可以看到数组值。再检查一遍
  • 您可以自定义 autoexp.dat 以指示调试器显示您对矩阵的需求。也就是说......如果没有更多细节,就无法确定最佳实现(从性能的角度来看)。您将如何使用该矩阵?您将应用哪些操作?你会支持哪些算法?通常“拆分”的变量非常好,但是...如果它真的是一个瓶颈...配置文件配置文件然后测量。
  • std::array<float, 16>.
  • 我会重新检查一遍,也许我做了一些愚蠢的事情。本机编程和 C++ 和环境的新手。

标签: c++ class graphics matrix


【解决方案1】:

您应该考虑使用Vector4float [4] 成员,以及Matrix4Vector4 [4] 成员。使用 operator [],您有两个有用的类,并保持访问元素的能力:[i][j] - 在大多数情况下,元素数据将是连续的,前提是您不使用 virtual 方法。

您也可以通过这种方式从向量 (SIMD) 指令中受益,例如,Vector4

union alignas(16) { __m128 _v; float _s[4]; }; // members

inline float & operator [] (int i) { return _s[i]; }
inline const float & operator [] (int i) const { return _s[i]; }

Matrix4

Vector4 _m[4]; // members

inline Vector4 & operator [] (int i) { return _m[i]; }
inline const Vector4 & operator [] (int i) const { return _m[i]; }

【讨论】:

  • 是的,经过深思熟虑后,我删除了我的评论。干得好:)
  • 如果您允许 SIMD 支持,则不允许访问单个元素。这是一个巨大的性能风险,请选择更友好的 SIMD 方式,通过 swizzle 操作和选择来获取和设置单个元素。
  • @JasperBekkers - 它只需要明智地使用。即矢量变换的点积。我宁愿两个选项都可用。
  • 当我重构代码时我会牢记这一点,因为我确实有一个 Vector4 类。但我是 C++ 和工作环境的新手,所以完全没有 SSE 指令的经验。
  • @ThubiedeJong - 你可以忽略 SSE 的东西,只使用 float[4] 成员。如果您可以保持 SIMD 单元充足,则可以进行“批处理”。
【解决方案2】:

float m1, m2 .. m16; 在使用循环遍历事物时变得非常尴尬。使用某种数组要容易得多。而且,最有可能的是,当您像“手工编码”一样使用循环时,编译器至少会生成高效代码,除非您实际编写内联汇编程序或使用 SSE 内在函数。

【讨论】:

  • 经验法则:X m1, m2; 可以,X m1, m2, m3, m4;(以及更多)必须转换为数组。 X m1, m2, m3 的情况不确定。
【解决方案3】:

16 位浮点数的解决方案只要代码不进化就可以了(维护起来很麻烦,而且不可读)

float[4][4] 是一种更好的设计(就大小参数化而言),但您必须了解指针的概念。

【讨论】:

  • 定义“好”!如果你想遍历元素怎么办?
  • @OliCharlesworth 我想他的意思是“根据你的问题很好”(性能)。如果矩阵大小是固定的并且必须真正优化代码,那么直接变量访问比任何(双...)指针间接访问快得多(这就是为什么 LL 3X3 和 4X4 矩阵是这样实现的)。 不代表可读性性能不是可读性的好朋友
  • 公平点。取决于用例。 (而我所说的“精细解决方案”是指“当你是初学者时,需要一小段时间来开发”)
  • @Adriano:编译器应该能够生成相同的代码来访问具有文字索引的数组(例如this->m[1][2])和访问命名成员(例如this->m6)。因此,使用数组不应该损害手动展开的性能。如果您愿意,它可以让您选择以编程方式迭代...
  • 我写了两个测试类,一个使用静态二维浮点数组,另一个使用 16 个浮点变量。编译器为每个矩阵乘法函数生成 相同 程序集 - 这是对元素使用友元访问。使用内联访问器函数和 -O1,2d 数组通过不需要的 push-pop %ebx 击败 16 个浮点数。使用 -O2 ,二维数组以 1 次操作击败 16 个浮点数。 16 个浮点数的内联访问器看起来像一个大 case 语句 - 二维数组的内联访问器只是返回 m[x][y]。数组版本还允许您使用更自然的 [row][col] 表示法。
【解决方案4】:

我会使用一个包含 16 个浮点数的数组,例如 float m[16];,唯一的原因是使用 Matrix4fv 后缀函数很容易将其传递给 openGL 等库。

float m[4][4]; 这样的二维数组应该 也可以在内存中配置为与float m[16] 相同(请参阅May I treat a 2D array as a contiguous 1D array?),并且使用[row][col](或[col][row] 我不确定哪个在 openGL 方面是正确的)索引(比较 m[1][1]m[5])。

【讨论】:

    【解决方案5】:

    对矩阵元素使用单独的变量可能会产生问题。在处理像 100x100 这样的大矩阵时,您打算做什么?

    当然你需要使用一些类似数组的结构,我强烈建议你至少使用数组

    【讨论】:

    • hmm,这有点危险(尤其是对于 C++ 初学者): V.push_back(v) 是安全的,但是 V[i].push_back(float f) 可以引发异常(取决于 V [i].容量)。
    • 他也在询问性能。 float[] 可以像 具有多个变量的简单实现一样快,但关于 std::vector 你可以确定它慢得多
    • 对于矩阵而不是使用push_back的,大小初始化可以在构造函数中完成
    • @fatik_h : 是的,只要 OP 只是读取矩阵而不是动态修改它。
    • 我在文献中发现的最大矩阵是 4x4。
    猜你喜欢
    • 2010-10-22
    • 2022-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多