我有一个代表向量的结构。该向量由两个1字节整数组成。我使用它们将值保持在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) );
};
这需要经常执行。有没有办法可以同时执行这两个乘法?也许通过矢量化,上交所或类似的方式?还是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)。
但是向量的值再次乘以相同的标量值。
有可能改善这些操作的性能吗?
谢谢
(我正在将Visual Studio 2010与64位编译器一起使用)
最佳答案
以我的经验,Visual Studio(尤其是像VS2010这样的较旧版本)并不能单独进行很多矢量化处理。他们在较新的版本中对其进行了改进,因此,如果可以,您可能会发现更改编译器是否可以加快代码的速度。
根据使用这些功能的代码以及编译器所做的优化,可能甚至不会使计算速度变慢。函数调用和缓存未命中可能会造成更大的伤害。
您可以尝试以下方法:
如果尚未完成,请在头文件中定义函数,以便编译器可以内联它们
如果您在紧密的循环中使用这些函数,请尝试在不进行任何函数调用的情况下“手动”执行计算(暂时公开变量),看看是否会造成速度差异)
如果您有很多向量,请查看它们在内存中的布局方式。连续存储它们以最大程度地减少缓存未命中。
为了使SSE真正运作良好,您必须一次处理4个值-因此将2个向量与2个浮点数相乘。在一个循环中,使用2的步长并编写一个静态函数,该函数使用SSE指令一次计算2个向量。由于向量不对齐(几乎不会使用8位变量),因此代码甚至可能比现在运行的速度慢,但是值得一试。
如果适用,并且您不依赖于从float
到uint8_t
的转换时发生的钳位(例如,如果浮点数在[0,1]范围内),请尝试在所有地方使用float
。这可以使编译器做得更好。
关于c++ - 同时将所有结构元素与标量相乘,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28543755/