我应该在C++中手动写出"sub-results"吗?
Should I manually write out "sub-results" in C++?
在我的一段代码中,我从 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
}
};
如您所见,计算只包含几个简单的操作(+
、-
、*
、/
、sin
和cos
(,但其中许多操作出现了很多次。此类操作的示例包括:
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(。
但是,一般来说,首先计算重复表达式通常对人类来说更清晰,有助于调试,并且还可以简化优化器的工作。
此外,由于这是关于浮点计算的,因此顺序很重要,因此仔细检查传递给优化器的构建标志非常重要。
相关文章:
- ZeroMQ 发布-订阅通信:SUB 不接收任何内容
- nng to pynng pub/sub. 客户端未收到任何消息
- 如何为 Festvox 安装 g++ 编译的 "sub" 库?
- glUniform4fv results in GL_INVALID_OPERATION
- ZeroMQ SUB 从不接收消息
- 将cpp_redis pub/sub与条件变量一起使用时出现问题
- 这是当前草案中[Expr.Ref]/(4.2)和[Expr.sub]/1之间的矛盾
- 我应该在C++中手动写出"sub-results"吗?
- protobuf "oneof" sub-protobuf 对象指针终止程序
- 是否可以使用包含{sub,super}类函数指针的回调表
- 如果 PUB 首先启动并连接到 XPUB/XSUB 代理,则消息将被丢弃,直到 SUB 未连接
- C 中Google Pub/sub的消费者示例
- 是否可以在LLVM中将"sub"标签插入到BasicBlock中?
- ZMQ Python PUB/SUB 有效,但我的 C++ Subscriber with Python Publish
- C++和Python ZeroMQ 4.x PUB/SUB示例不起作用
- C++ - 创建游戏实体时,我应该使用"sub classes"还是结构?
- 循环访问 QFutureSyncer:<T>:results
- 实现一个函数 StrSep(s, sub, part1, part2) 来接收字符串和子字符串 (sub) 并返回 :
- ZeroMQ 中的 SUB 订阅者是否像 ROS 中那样具有任何"callback"机制?
- 如何在 MFC 中创建"CArray<CArray<CString>>& results"?