我正在编写一个物理模拟编码,现在我觉得需要优化它。我正在考虑改进一点:我的一个方法之一(在几种情况下我称之为十亿次)每次定义一个概率分布。这是代码:
void myClass::myMethod(){ //called billions of times in several cases
uniform_real_distribution<> probd(0,1);
uniform_int_distribution<> probh(1,h-2);
uniform_int_distribution<> probv(1,v-2);
//rest of the code
}
我可以将分发作为类的成员传递,这样我就不必每次都定义它们吗?只需在构造函数中初始化它们,并在h和v更改时重新定义它们?这可能是一个很好的优化进展吗?最后一个问题,当使用标志-O3或-O2编译时,编译器(在我的情况下是g ++)是否已经纠正了这个问题?
提前谢谢!
更新:我对它进行了编码并对两者进行了计时:程序实际上变慢了(几个百分点)所以我回到了我的开始:在每个循环中创建概率分布
答案 0 :(得分:5)
答案答:我不应该这么认为,对于统一分布,它只是将参数值复制到位,可能只需要少量算术,并且可以很好地优化。
但是,我相信分发对象可以有状态。它们可以使用来自对生成器的调用的部分随机数据,并且允许保留下次使用分布时使用的其余随机性,以便减少对生成器的调用总数。因此,当您销毁分发对象时,您可能会丢弃一些可能代价高昂的随机数据。
答案B:停止猜测并测试它。
为您的代码计算时间,然后将static
添加到probd
的定义中并再次计时。
答案 1 :(得分:2)
顺便提一下,如果你遇到性能问题,除了优化明显的点(内部循环中使用的非最佳算法,连续内存分配,删除无用的大对象副本,......)之外,你应该尝试使用分析器来找到代码中真正的“热点”,集中精力优化它们,而不是随机遍历所有代码。
答案 2 :(得分:2)
uniform_real_distribution
维护类型为param_type
的状态,即两个double
值(使用默认模板参数)。构造函数赋予这些并且在其他方面是微不足道的,析构函数是微不足道的。
因此,与初始化1指针(或引用)或通过double
进行间接寻址相比,在函数中构造临时值会产生2 this
个值的开销。从理论上讲,它可能因此更快(但出现更快,或者运行速度更快更有必要)。由于它没有太大的作用,因此即使它是微观优化也是值得尝试和计时是否存在差异。
大约3-4个额外的周期通常是可以忽略的,但是因为你说“数十亿次”,它当然可以很好地产生可测量的差异。在3GHz机器上,3个周期乘以10亿次是1秒。
当然,没有剖析的优化总是有点......尴尬。您可能会发现代码中不同的部分被称为数十亿次,可以节省更多的周期。
修改强>
由于您不打算对其进行修改,并且由于第一个分布是使用文字值初始化的,因此您实际上可能使其成为常量(例如constexpr
或命名空间级别{{1 }})。无论如何,这应该允许编译器在任何情况下生成最有效的代码。