我正在研究一个物理引擎,我觉得它有助于更好地理解执行许多简单或复杂数学运算的速度和性能影响。
物理引擎的很大一部分正在清除不必要的计算,但是在什么时候计算足够小以至于不需要进行比较检查?
- 例如:测试两条线段是否相交。在直接进入简单的数学之前是否应该检查它们是否彼此靠近,或者从长远来看,额外的操作会减慢这个过程?
不同的数学计算需要多少时间
- 例如:(3+8) vs (5x4) vs (log(8)) 等。
不平等检查需要多长时间?
- 例如:>、<、=
我正在研究一个物理引擎,我觉得它有助于更好地理解执行许多简单或复杂数学运算的速度和性能影响。
物理引擎的很大一部分正在清除不必要的计算,但是在什么时候计算足够小以至于不需要进行比较检查?
不同的数学计算需要多少时间
不平等检查需要多长时间?
您必须进行分析。
基本运算,如加法或乘法应该只需要一条asm
指令。
编辑:根据评论,虽然采用一条 asm 指令,但乘法可以扩展到微指令。
对数需要更长的时间。
也是一个asm
指令。
除非你分析你的代码,否则没有办法知道你的瓶颈在哪里。
除非您调用数学运算数百万次(甚至可能调用),否则算法或其他一些高级优化的良好选择将比优化小东西带来更大的速度增益。
您应该编写易于阅读且易于修改的代码,并且只有当您对性能不满意时,才开始优化 - 首先是高级,然后才是低级。
您可能还想尝试动态编程或缓存。
关于 2 和 3,我可以向您推荐英特尔® 64 和 IA-32 架构优化参考手册。附录 C 介绍了各种指令的延迟和吞吐量。但是,除非您手动编写汇编代码,否则您的编译器将应用自己的优化,因此直接使用这些信息会相当困难。
更重要的是,您可以使用 SIMD 对代码进行矢量化并并行运行计算。此外,如果您的内存布局不理想,内存性能可能会成为瓶颈。我链接到的文档有关于这两个问题的章节。
但是,正如@Ph0en1x 所说,第一步是选择(或编写)一种有效的算法,使其适用于您的问题。只有这样,您才应该开始考虑低级优化。
至于 1,在一般情况下,我会说,如果您的算法以这样一种方式工作,它对于何时执行某些测试具有一些可调整的阈值,您可以进行一些分析并打印出某种性能图,并且确定这些阈值的最佳值。
好吧,这取决于您的硬件。具有指令延迟的非常好的表是http://www.agner.org/optimize/instruction_tables.pdf
1.很大程度上取决于代码。也不要忘记它不仅取决于计算,还取决于预测比较结果的好坏。
2.一般加减法很快,浮点数的乘法有点慢。浮点除法相当慢(如果您需要除以常数 c,通常最好预先计算 1/c 并乘以它)。库函数通常(我敢说总是)比简单的运算符慢,除非编译器决定使用 SSE。例如,可以使用一条 SSE 指令计算 sqrt() 和 1/sqrt()。
3.从大约一个周期到几十个周期。当前的处理器对条件进行预测。如果预测是正确的,它会很快。但是,如果预测错误,处理器必须丢弃所有预加载的指令(IIRC Sandy Bridge 最多预加载 30 条指令)并开始处理新指令。
这意味着如果你有一个代码,在大多数情况下都满足一个条件,它会很快。同样,如果您的代码大部分时间都不满足条件,它会很快。简单的交替条件(TFTFTF…)通常也很快。
您通常可以认为不等式检查、递增、递减、位移、加法和减法非常便宜。乘法和除法通常要贵一些。对数等复杂的数学运算要昂贵得多。
确定在您的平台上进行基准测试。使用带有紧密循环的人工测试进行基准测试时要小心——这往往会给你带来误导性的结果。尝试在尽可能真实的代码中进行基准测试。理想情况下,在实际条件下分析实际代码。
至于线交叉等的优化,这取决于数据集。如果您进行了很多检查并且大多数行都很短,那么可能值得快速检查以排除 X 或 Y 范围不重叠的情况。
据我所知,所有“不平等检查”都需要相同的时间。
关于其余的计算,我建议您进行一些测试,例如
然后你可以比较计算。
请记住: