我应该在C++中手动写出"sub-results"吗?

Should I manually write out "sub-results" in C++?

本文关键字:sub-results C++ 我应该      更新时间:2023-10-16

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

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
    }
};

如您所见,计算只包含几个简单的操作(+-*/sincos(,但其中许多操作出现了很多次。此类操作的示例包括:

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

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

float oy_plus_oz = orientation.y + orientation.z;
float cos_oy_plus_oz = cos(oy_plus_oz);
float ox_plus_oy_plus_oz = orientation.x + oy_plus_oz;
float ox_minus_oy_plus_oz = orientation.x - oy_plus_oz;
float oy_minus_oz = orientation.y - orientation.z;
float ox_plus_oy_minus_oz = orientation.x + oy_minus_oz;
float ox_minus_oy_minus_oz = orientation.x - oy_minus_oz;
float cos_ox_plus_oy_plus_oz = cos(ox_plus_oy_plus_oz);
float cos_ox_minus_oy_plus_oz = cos(ox_minus_oy_plus_oz);
float two_mult_sx = 2 * scale.x;
float cos_oy_minus_oz = cos(oy_minus_oz);
float cos_ox_plus_oy_minus_oz = cos(ox_plus_oy_minus_oz);
float cos_ox_minus_oy_minus_oz = cos(ox_minus_oy_minus_oz);
float ox_plus_oy = orientation.x + orientation.y;
float ox_minus_oy = orientation.x - orientation.y;
float cos_ox_plus_oy = cos(ox_plus_oy);
float cos_ox_minus_oy = cos(ox_minus_oy);

有没有更好/更快的方法来做到这一点,还是完全没有必要?关键是这段代码应该尽可能快(避免多次对同一值进行不必要的计算(。

有没有更好/更快的方法来做到这一点,还是完全没有必要?关键是这段代码应该尽可能快(避免多次对同一值进行不必要的计算(。

优化编译器将查找计算速度更快的等效表达式,包括分解子表达式。

如果不查看生成的代码并测量实际执行时间,就不可能说哪种方式最终会得到最好的代码(最佳解决方案可能取决于您的目标 CPU(。

但是,一般来说,首先计算重复表达式通常对人类来说更清晰,有助于调试,并且还可以简化优化器的工作。

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