【问题标题】:Best way to store floating points [closed]存储浮点数的最佳方法[关闭]
【发布时间】:2013-09-09 17:14:12
【问题描述】:

我有一个类必须存储 4 个浮点数。 将浮点数存储在数组中还是作为类的 4 个成员更有效?尤其是结合 stl-containers 和参数传递。

【问题讨论】:

  • 测量它。实际上,不要这样做,因为它不会对速度产生任何明显的影响。
  • 更重要的是您希望如何使用这些值以及它们如何相互关联。否则性能差异可以忽略不计。
  • 两者都只是内存位置的偏移量...
  • 这个问题不是关于 best way to handle floating points 而是关于 存储浮点值 的最佳方式,但绝对不清楚其目的是什么(至于处理部分)。
  • 这取决于您如何访问它们。效率可能并不重要。

标签: c++ stl floating-point


【解决方案1】:

不可能有任何区别。两个类结构的内存布局将完全相同;因此,大多数生成的代码也将是相同的(因此,性能将是相同的)。

我可以看到这两个选项之间的唯一区别是,如果浮点数存储为数组,则可以对它们进行索引。根据您打算如何使用它们,这可能有用也可能没用。

【讨论】:

  • 您列出了阵列的专业人士,但没有列出单独的浮动。 Pro:如果它们不在数组中,您可以通过名称轻松访问它们。
【解决方案2】:

这有强烈的过早优化的味道。相反,根据它们的目的有意义地命名浮动。它们是四个不相关的值吗?使它们成为单独的属性。它们是四个序列值吗?使它成为一个数组。如果有的话,实际的性能差异应该可以忽略不计。

【讨论】:

  • 有点过早的优化。但我问自己这个问题是否有益。
【解决方案3】:

形式上它取决于编译器,但速度和大小应该相同。

以常量为索引的全局数组对于编译器而言与全局变量完全相同:它们都只转换为内存中的静态地址。

用常量索引的成员数组与成员变量完全相同:它们都转换为距this 有固定偏移量的地址。

当然,g++(但很可能其他编译器也是)能够使用更大的寄存器将多个相邻变量的副本与单个内存操作合并。

但问题是:浮点数在逻辑上是一个数组还是四个独立值?

换句话说,你会需要v[i],而i 是一个变量吗?如果你这样做了,那么使用四个成员会很烦人,因为它需要switch,如果你从不需要它,使用v[0] 而不是x 会很烦人。

【讨论】:

  • 浮点数在逻辑上属于一起。我特别想知道如何处理 stl-containers。当我有类似的东西时:
    std::vector vec (10000);
    generate (vec.begin(), vec.end(), [&]()->ClassA{
    ClassA tmp(0,0,0,0);
    return tmp;
    });
    例如,使用数组作为交换运算符会更好吗?跨度>
  • @Hymir 你可以使用swap 不是“效率特性”。
【解决方案4】:

我在某处读到,编译器往往有一个优化例程,它内联所有固定长度

【讨论】:

    【解决方案5】:

    您可以将浮点数存储在数组中并提供命名访问器。两全其美;)

    struct Vector4f
    {
        float a[4];
        float x() const { return a[0]; }
        float y() const { return a[1]; }
        float z() const { return a[2]; }
        float w() const { return a[3]; }
    };
    

    【讨论】:

    • Best of both worlds ;) -- 绝对没有。这只是一场维护噩梦。充其量是个玩笑,但在回答初学者的问题时很危险。如果你真的认为你需要它,再想一想......
    【解决方案6】:

    请考虑 C++ 常见问题解答中的这一警告:Arrays Are Evil。最后一段:

    为了解决这个问题,数组确实是邪恶的。你可能不这么认为,如果 你是 C++ 新手。但是在你写了一大堆代码之后 数组(特别是如果你让你的代码防泄漏并且 异常安全),你会学到——很难。或者你会学到简单的 相信那些已经做过类似事情的人。这 选择权在你。

    编辑:在看到@Eric 的评论后,我调查并发现了这个有见地的问题:Should arrays be used in C++?。那里的一些答案表明,将成员变量声明为固定大小的数组确实可以适当地使用 C++ 中的数组。

    不过,一般来说,正如 C++ 常见问题解答所断言的那样,在 C++ 中应谨慎使用数组。

    【讨论】:

    • 那种谩骂一般不适用于这种情况。
    • 我阅读了那个链接。简而言之,他非常有偏见,试图证明在任何情况下都应该使用容器类而不是其他任何东西。感谢上帝,这些人不在 C++ 审查委员会,只维护他们可怜的网站!
    • @Simple Fellow - 您可能想阅读what others on SO have said about the C++ FAQ Lite。我见过的大多数 cmets 都非常积极。 for example。也就是说,我当然愿意阅读 C++ FAQ Lite 的批评者所写的内容。
    • @Simple Fellow - 另请注意change history for the C++ FAQ Lite 可以追溯到1994 年。作者welcomes contributions from others
    • @DavidRR 这是 2013 年!
    【解决方案7】:

    据我所知,访问数组中的 4 个浮点数比访问类中声明的 4 个实例变量要快

    C++ 编译器为数组生成的代码使用索引寻址模式,这对于英特尔处理器来说更容易和更快。

    很久以前,我一直在为 3D 图形开发 OpenGL。这些函数可以将顶点作为 x、y、z 值、顶点结构或具有 3 个成员的浮点数组。需要数组的函数比它们的对应函数更快。

    速度还取决于您将执行哪种计算。

    您没有提到太多关于设计或领域的内容,但还要检查将它们存储在数组或实例变量中是否更有意义。请记住,优化代码的代价是可读性降低,有时还会出现维护问题。

    【讨论】:

    • 求有趣的答案! :)
    • 我不确定这个答案是否准确
    • 我使用 Apple LLVM 5.0 编译代码,该代码使用 x->f[2] 访问具有四个 float 的数组的结构,而其他代码使用 x->c 访问具有四个独立成员的结构。在这两种情况下,生成的汇编代码都使用8(%rdi) 来引用该成员。实际上,访问单个成员的代码的实现本质上是访问数组元素的代码子集,因为在单个成员的结构中对.MemberName 的任何引用都等效于带有数组的结构中的一些.Array[Index]。 (反之则不然,因为索引可能是非常量的。)
    • 并非每个编译器都会生成完全相同的指令并执行相同的优化。 “所有编译器都不相等”,否则如何从英特尔编译器获得比 VC 和 C++ 构建器编译器更快的 exe?
    • 问题是关于数组成员与单独的成员。您提到的经验是函数参数,这根本不是一回事。成员变量应该没有区别。
    猜你喜欢
    • 2021-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 2020-08-10
    相关资源
    最近更新 更多