【问题标题】:Optimize small 3d vector struct for performance优化小型 3d 矢量结构以提高性能
【发布时间】:2013-10-19 08:08:48
【问题描述】:

我对 C++ 相当陌生,并且有以下问题,我们称之为问题。在我的计算机模拟中,我经常使用向量。我为自己构建了一个表示向量的小结构,并且想学习如何使操作(例如normalize() 函数更有效。此外,使用 C++ 的valarray 有什么好处吗?它似乎有预先实现了一些有用的方法。

我几乎只使用normalize() 函数和向量的加法/减法/乘法。由于我的所有向量都只有三个元素,因此我对在我的项目中包含 3rd 方库犹豫不决。

这是我的结构:

struct vector_t {
    int _i, _j, _k;
    vector_t(int i, int j, int k) {
        _i = i;
        _j = j;
        _k = k;
    }
    vector_t() {}
    inline int getI() { 
        return _i; 
    }
    inline int getJ() { 
        return _j; 
    }
    inline int getK() { 
        return _k; 
    }
    inline void setI(int val) { 
        _i = val; 
    }
    inline void setJ(int val) { 
        _j = val; 
    }
    inline void setK(int val) { 
        _k = val; 
    }
    void normalize() {
        float length = sqrt(_i*_i + _k*_k + _j*_j);
        _i /= length;
        _j /= length;
        _k /= length;
    }
};

还有我的问题:

  • 如何加快normalize() 函数的速度,或者这已经是最有效的方法了吗?
  • 在实现这样的结构/类同时保持较低的内存和计算机时间使用率的同时,还有什么更 C++ 风格的方法?
  • 我应该更喜欢 valarray 而不是我自己的类型吗?

【问题讨论】:

  • 如果您的成员都是整数,则规范化将“非常糟糕”。
  • 使用快速倒数平方根函数计算1 / length,然后将每个元素乘以该因子。除了是比sqrt 更快的函数之外,它还用 3 个昂贵的除法运算换取了 3 个相对便宜的乘法运算。
  • @janoliver 简单,假设您的向量是 1,1,1。归一化将使其成为 0.33,0.33,0.33(因为归一化意味着长度 = 1)。当您默认为 int 时,您的向量随后被转换为零向量。
  • 如果你想要真正的速度,我推荐 Eigen:eigen.tuxfamily.org/index.php?title=Main_Page 应该有任何额外的依赖。
  • 如果您担心进行数值计算的绝对最佳方式,您应该阅读 CPU 制造商的手册,并在此基础上编写精心设计的基于内在函数(或纯汇编)的代码。或使用a library where the authors did just that

标签: c++ vector struct


【解决方案1】:

使用fast reciprocal square root function 计算 1 / 长度,然后将每个元素乘以该因子。除了比sqrt 更快的功能之外,它还用 3 个昂贵的除法运算换取了 3 个相对便宜的乘法运算:

struct vector_t {
    float _i, _j, _k;

    // ...

    void normalize() {
        float r_length = Q_rsqrt(_i*_i + _k*_k + _j*_j);
        _i *= r_length;
        _j *= r_length;
        _k *= r_length;
    }
};

注意:您可能需要考虑如何处理i == j == k == 0 的病理情况。

【讨论】:

  • 谢谢,我改了代码,实现了这个功能:stackoverflow.com/questions/17789928/…
  • 是的,这基本上与我上面链接的例程相同。请注意,如果您可以假设仅 x86,那么还有更快的替代方案。
  • 当 SSE 完全粉碎它时,人们仍在将其作为一种快速解决方案来推动它,这让我感到很困扰。是的,它比 x87 FPU 做得更好,但你想要 SSE 的性能。 assemblyrequired.crashworks.org/2009/10/16/timing-square-root
  • @r_ahlskog:最大的区别在于快速的rsqrt 是可移植的,而 SSE 是仅 x86 的。
  • @PaulR,是的,它需要 SSE,在 ARM 上你会找到提供 VRSQRTE 和 VRSQRTS 的 NEON,PowerPC 有 AltiVec,我不熟悉,但我想它有类似的功能。
【解决方案2】:

这不会有很大的不同,但你的构造函数应该是这样的:

vector_t(int i, int j, int k)
: _i(i), _j(j), _k(k)
{
}

对于优化,您应该查看 SSE:http://www.cortstratton.org/articles/OptimizingForSSE.php

【讨论】:

  • 好点,谢谢。然而,我认为编译器足够聪明,可以消除任何速度差异。
猜你喜欢
  • 2014-12-17
  • 2021-03-13
  • 2014-10-08
  • 2016-02-15
  • 2016-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多