【问题标题】:Simultaneously multiply all struct-elements with a scalar同时将所有结构元素与标量相乘
【发布时间】:2015-04-17 02:25:58
【问题描述】:

我有一个表示向量的结构。该向量由两个单字节整数组成。我使用它们将值保持在 0 到 255 之间。

typedef uint8_T unsigned char;

struct Vector
{
  uint8_T x;
  uint8_T y;
};

现在,我的程序中的主要用例是将向量的两个元素与一个 32 位浮点值相乘:

typedef real32_T float;

Vector Vector::operator * ( const real32_T f ) const {
  return Vector( (uint8_T)(x * f), (uint8_T)(y * f) );
};

这需要经常执行。有没有办法可以同时执行这两个乘法?也许通过矢量化、SSE 或类似方法?或者 Visual Studio 编译器是否已经同时执行此操作?

另一个用例是在两个向量之间进行插值。

Vector Vector::interpolate(const Vector& rhs, real32_T z) const
{
  return Vector(
        (uint8_T)(x + z * (rhs.x - x)),
        (uint8_T)(y + z * (rhs.y - y))
        );
}

这已经使用了优化的插值方法 (https://stackoverflow.com/a/4353537/871495)。

但是向量的值再次乘以相同的标量值。 是否有可能提高这些操作的性能?

谢谢

(我正在使用带有 64 位编译器的 Visual Studio 2010)

【问题讨论】:

  • 为什么不进行优化编译,然后分析代码。如果这不是问题,那就没有意义了。
  • 我确信编译器已经为你做了这个。
  • 好的,谢谢。我知道这部分会减慢我的程序,但如果没有优化它的潜力,那么我必须查看我的代码的其他部分。

标签: c++ vectorization sse simultaneous vector-multiplication


【解决方案1】:

根据我的经验,Visual Studio(尤其是像 VS2010 这样的旧版本)本身并没有做很多矢量化。他们在较新的版本中对其进行了改进,因此如果可以的话,您可能会看看编译器的更改是否会加快您的代码速度。

根据使用这些函数的代码和编译器所做的优化,甚至可能不是计算会减慢程序的速度。函数调用和缓存未命中可能会造成更大的伤害。

您可以尝试以下方法:

  • 如果尚未完成,请在头文件中定义函数,以便编译器可以内联它们
  • 如果您在紧密循环中使用这些函数,请尝试在不调用任何函数的情况下“手动”进行计算(暂时公开变量),看看它是否会产生速度差异)
  • 如果您有很多向量,请查看它们在内存中的布局方式。将它们连续存储以最大限度地减少缓存未命中。
  • 要使 SSE 工作得非常好,您必须同时使用 4 个值 - 因此将 2 个向量与 2 个浮点数相乘。在循环中,使用步长 2 并编写一个静态函数,该函数使用 SSE 指令一次计算 2 个向量。由于您的向量未对齐(几乎不会与 8 位变量对齐),因此代码的运行速度甚至可能比您现在的要慢,但值得一试。
  • 如果适用,并且如果您不依赖从 floatuint8_t 的铸件发生的夹紧(例如,如果您的浮点数在 [0,1] 范围内),请尝试在任何地方使用 float。这可以让编译器做更好的优化。

【讨论】:

  • 谢谢。大多数答案指出,从 int 到 float 的转换可能很慢。我没有使用 floata 因为我不需要它们的精度。但我没有内存消耗问题。我将首先尝试一下,因为它很容易实现。
【解决方案2】:

您还没有展示完整的算法,但是整数和浮点数之间的转换是一个非常缓慢的操作。消除此操作并仅使用一种类型(如果可能,最好是整数)可以大大提高性能。

或者,您可以使用lrint() 进行转换,如here 所述。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多