我应该在C ++中手动写出“子结果”吗?

时间:2019-07-26 20:37:52

标签: c++

在我的一段代码中,我从3个mat4中计算出一个const vec3

const vec3 position{...}, orientation{...}, scale{...};

float mat[4][4]
{
    {
        (2 * scale.x * cos(orientation.y + orientation.z) + scale.x * cos(orientation.x + orientation.y + orientation.z) - scale.x * cos(orientation.x - orientation.y + orientation.z) + 2 * scale.x * cos(orientation.y - orientation.z) - scale.x * cos(orientation.x + orientation.y - orientation.z) + scale.x * cos(orientation.x - orientation.y - orientation.z)) / 4,
        (-scale.x * cos(orientation.x + orientation.y) + scale.x * cos(orientation.x - orientation.y)) / 2,
        (-2 * scale.x * sin(orientation.y + orientation.z) - scale.x * sin(orientation.x + orientation.y + orientation.z) + scale.x * sin(orientation.x - orientation.y + orientation.z) + 2 * scale.x * sin(orientation.y - orientation.z) - scale.x * sin(orientation.x + orientation.y - orientation.z) + scale.x * sin(orientation.x - orientation.y - orientation.z)) / 4,
        0
    },
    {
        (-scale.y * cos(orientation.x + orientation.z) + scale.y * cos(orientation.x - orientation.z)) / 2,
        scale.y * cos(orientation.x),
        (scale.y * sin(orientation.x + orientation.z) + scale.y * sin(orientation.x - orientation.z)) / 2,
        0
    },
    {
        (2 * scale.z * sin(orientation.y + orientation.z) + scale.z * sin(orientation.x + orientation.y + orientation.z) + scale.z * sin(orientation.x - orientation.y + orientation.z) + 2 * scale.z * sin(orientation.y - orientation.z) - scale.z * sin(orientation.x + orientation.y - orientation.z) - scale.z * sin(orientation.x - orientation.y - orientation.z)) / 4,
        (-scale.z * sin(orientation.x + orientation.y) - scale.z * sin(orientation.x - orientation.y)) / 2,
        (2 * scale.z * cos(orientation.y + orientation.z) + scale.z * cos(orientation.x + orientation.y + orientation.z) + scale.z * cos(orientation.x - orientation.y + orientation.z) - 2 * scale.z * cos(orientation.y - orientation.z) + scale.z * cos(orientation.x + orientation.y - orientation.z) + scale.z * cos(orientation.x - orientation.y - orientation.z)) / 4,
        0
    },
    {
        (-2 * position.y * cos(orientation.x + orientation.z) + 2 * position.x * cos(orientation.y + orientation.z) + position.x * cos(orientation.x + orientation.y + orientation.z) - position.x * cos(orientation.x - orientation.y + orientation.z) + 2 * position.y * cos(orientation.x - orientation.z) + 2 * position.x * cos(orientation.y - orientation.z) - position.x * cos(orientation.x + orientation.y - orientation.z) + position.x * cos(orientation.x - orientation.y - orientation.z) + 2 * position.z * sin(orientation.y + orientation.z) + position.z * sin(orientation.x + orientation.y + orientation.z) + position.z * sin(orientation.x - orientation.y + orientation.z) + 2 * position.z * sin(orientation.y - orientation.z) - position.z * sin(orientation.x + orientation.y - orientation.z) - position.z * sin(orientation.x - orientation.y - orientation.z)) / 4,
        (2 * position.y * cos(orientation.x) - position.x * cos(orientation.x + orientation.y) + position.x * cos(orientation.x - orientation.y) - position.z * sin(orientation.x + orientation.y) - position.z * sin(orientation.x - orientation.y)) / 2,
        (2 * position.z * cos(orientation.y + orientation.z) + position.z * cos(orientation.x + orientation.y + orientation.z) + position.z * cos(orientation.x - orientation.y + orientation.z) - 2 * position.z * cos(orientation.y - orientation.z) + position.z * cos(orientation.x + orientation.y - orientation.z) + position.z * cos(orientation.x - orientation.y - orientation.z) + 2 * position.y * sin(orientation.x + orientation.z) - 2 * position.x * sin(orientation.y + orientation.z) - position.x * sin(orientation.x + orientation.y + orientation.z) + position.x * sin(orientation.x - orientation.y + orientation.z) + 2 * position.y * sin(orientation.x - orientation.z) + 2 * position.x * sin(orientation.y - orientation.z) - position.x * sin(orientation.x + orientation.y - orientation.z) + position.x * sin(orientation.x - orientation.y - orientation.z)) / 4,
        1
    }
};

如您所见,计算仅包括一些简单的操作(+-*/sin和{{ 1}}),但其中许多出现了很多次。此类操作的示例是:

cos

我不希望处理器多次计算它们,所以我尝试用“ shortucts”替换它们:

orientation.y + orientation.z
orientation.x + oy_plus_oz
sin(orientation.x - oy_plus_oz)
//many more...

是否有更好/更快的方法,还是完全不需要?关键是此代码应尽可能快(避免多次不必要地计算相同值)

1 个答案:

答案 0 :(得分:2)

  

是否有更好/更快的方法,还是完全没有必要?关键是该代码应尽可能快(避免多次不必要地多次计算相同的值)。

优化的编译器将寻找等效表达式,这些表达式的计算速度更快,包括将子表达式排除在外。

如果不查看生成的代码并测量实际的执行时间(这是哪种最佳解决方案可能取决于您所针对的CPU),就无法说出哪种方法最终获得最佳代码。

但是,通常来说,首先计算重复表达式通常对人类来说更清晰,有助于调试,也可以简化优化程序的寿命。

此外,由于这与浮点计算有关,因此顺序很重要,因此仔细检查传递给优化器的构建标志非常重要。