0
我複製了Moro的正態分佈的反累積函數的代碼,其中我添加了一個額外的錯誤處理來處理超出範圍(0,1)的輸入。當我用全部有效輸入測試代碼時,速度減慢了大約25%(6ns vs 8ns)。我很好奇,爲什麼即使不執行拋出異常仍然會降低性能?爲什麼添加潛在異常會導致性能下降,即使從未拋出?
碼反向功能:
double Inverse(double u)
{
double a[4] = {
2.50662823884,
-18.61500062529,
41.39119773534,
-25.44106049637 };
double b[4] = {
-8.47351093090,
23.08336743743,
-21.06224101826,
3.13082909833 };
double c[9] = {
0.3374754822726147,
0.9761690190917186,
0.1607979714918209,
0.0276438810333863,
0.0038405729373609,
0.0003951896511919,
0.0000321767881768,
0.0000002888167364,
0.0000003960315187 };
// Assert(0 < u && u < 1);
if (u >= 1 || u <= 0){
throw std::invalid_argument("Input out of range.");
}
/*return the inverse of cumulative normal distribution fonction*/
double x, r;
x = u - 0.5;
if (fabs(x)<0.42) {
r = x*x;
r = x*(((a[3] * r + a[2])*r + a[1])*r + a[0])/((((b[3] * r + b[2])*r + b[1])*r + b[0])*r + 1.0);
return(r);
}
r = u;
if (x>0.0) r = 1 - u;
r = log(-log(r));
r = c[0] + r*(c[1] + r*(c[2] + r*(c[3] + r*(c[4] + r*(c[5] + r*(c[6] + r*(c[7] + r*c[8])))))));
if (x<0.0) r = -r;
return(r);
}
而且測試代碼
int m = 1000000, n = 1000;
double z, p, dz = 1.0/double(m)/double(n);
clock_t t1, t2;
t1 = clock();
z = 1e-9;
p = 0.0;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
z += dz * 0.999;
p = Inverse(z);
}
}
t2 = clock();
cout << z << '\t' << p << endl;
cout << "Inverse" << '\t' << float(t2 - t1)/CLOCKS_PER_SEC << endl;
你正在做一個'if'。這意味着你要做更多的指示,這意味着更多的工作 – NathanOliver
這兩個額外的納秒真的值得額外的努力嗎?這個差別最多隻是一個環境問題。 – Rakete1111
這就是爲什麼必須快速執行的功能不應檢查其輸入,而是記錄預期範圍。讓用戶確保他們沒有違反該功能的要求。 –