gpt4 book ai didi

c++ - 寻找加速功能的方法

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:02:32 27 4
gpt4 key购买 nike

我试图加速跨多个文件的一大块代码,发现一个函数使用了大约 70% 的总时间。这是因为这个函数被调用了 477+ 百万次。

指针数组par只能是两个预设之一

par[0] = 0.057;
par[1] = 2.87;
par[2] = -3.;
par[3] = -0.03;
par[4] = -3.05;
par[5] = -3.5;

OR

par[0] = 0.043;
par[1] = 2.92;
par[2] = -3.21;
par[3]= -0.065;
par[4] = -3.00;
par[5] = -2.65;

所以我尝试根据它是哪个预设插入数字,但未能找到任何显着的时间节省。

powexp 函数似乎每次都会被调用,它们分别占总时间的 40% 和 20%,所以只有 10%此函数中不是 powexp 的部分使用总时间。找到加快速度的方法可能是最好的,但是 pow 中使用的指数都不是整数,除了 -4 我不知道 1/(x*x*x*x)pow(x, -4) 快。

double Signal::Param_RE_Tterm_approx(double Tterm, double *par) {

double value = 0.;

// time after Che angle peak
if (Tterm > 0.) {

if ( fabs(Tterm/ *par) >= 1.e-2) {
value += -1./(*par)*exp(-1.*Tterm/(*par));

}
else {
value += -1./par[0]*(1. - Tterm/par[0] + Tterm*Tterm/(par[0]*par[0]*2.) - Tterm*Tterm*Tterm/(par[0]*par[0]*par[0]*6.) );
}

if ( fabs(Tterm* *(par+1)) >= 1.e-2) {
value += *(par+2)* *(par+1)*pow( 1.+*(par+1)*Tterm, *(par+2)-1. );

}
else {
value += par[2]*par[1]*( 1.+(par[2]-1.)*par[1]*Tterm + (par[2]-1.)*(par[2]-1.-1.)/2.*par[1]*par[1]*Tterm*Tterm + (par[2]-1.)*(par[2]-1.-1.)*(par[2]-1.-2.)/6.*par[1]*par[1]*par[1]*Tterm*Tterm*Tterm );
}

}

// time before Che angle peak
else {

if ( fabs(Tterm/ *(par+3)) >= 1.e-2 ) {
value += -1./ *(par+3) *exp(-1.*Tterm/ *(par+3));

}
else {
value += -1./par[3]*(1. - Tterm/par[3] + Tterm*Tterm/(par[3]*par[3]*2.) - Tterm*Tterm*Tterm/(par[3]*par[3]*par[3]*6.) );
}

if ( fabs(Tterm* *(par+4) >= 1.e-2 ) {
value += *(par+5)* *(par+4) *pow( 1.+ *(par+4)*Tterm, *(par+5)-1. );

}
else {
value += par[5]*par[4]*( 1.+(par[5]-1.)*par[4]*Tterm + (par[5]-1.)*(par[5]-1.-1.)/2.*par[4]*par[4]*Tterm*Tterm + (par[5]-1.)*(par[5]-1.-1.)*(par[5]-1.-2.)/6.*par[4]*par[4]*par[4]*Tterm*Tterm*Tterm );
}
}

return value * 1.e9;

}

最佳答案

我首先重写了它以便更容易理解:

#include <math.h> 

double Param_RE_Tterm_approx(double Tterm, double const* par) {
double value = 0.;

if (Tterm > 0.) {
// time after Che angle peak

if ( fabs(Tterm/ par[0]) >= 1.e-2) {
value += -1./(par[0])*exp(-1.*Tterm/(par[0]));
} else {
value += -1./par[0]*(1. - Tterm/par[0] + Tterm*Tterm/(par[0]*par[0]*2.) - Tterm*Tterm*Tterm/(par[0]*par[0]*par[0]*6.) );
}

if ( fabs(Tterm* par[1]) >= 1.e-2) {
value += par[2]* par[1]*pow( 1.+par[1]*Tterm, par[2]-1. );
} else {
value += par[2]*par[1]*( 1.+(par[2]-1.)*par[1]*Tterm + (par[2]-1.)*(par[2]-1.-1.)/2.*par[1]*par[1]*Tterm*Tterm + (par[2]-1.)*(par[2]-1.-1.)*(par[2]-1.-2.)/6.*par[1]*par[1]*par[1]*Tterm*Tterm*Tterm );
}

} else {
// time before Che angle peak

if ( fabs(Tterm/ par[3]) >= 1.e-2 ) {
value += -1./ par[3] *exp(-1.*Tterm/ par[3]);
} else {
value += -1./par[3]*(1. - Tterm/par[3] + Tterm*Tterm/(par[3]*par[3]*2.) - Tterm*Tterm*Tterm/(par[3]*par[3]*par[3]*6.) );
}

if ( fabs(Tterm* par[4]) >= 1.e-2 ) {
value += par[5]* par[4] *pow( 1.+ par[4]*Tterm, par[5]-1. );

} else {
value += par[5]*par[4]*( 1.+(par[5]-1.)*par[4]*Tterm + (par[5]-1.)*(par[5]-1.-1.)/2.*par[4]*par[4]*Tterm*Tterm + (par[5]-1.)*(par[5]-1.-1.)*(par[5]-1.-2.)/6.*par[4]*par[4]*par[4]*Tterm*Tterm*Tterm );
}
}

return value * 1.e9;
}

然后我们可以看看它的结构。

有两个主要分支——Tterm 负(之前)和正(之后)。这些对应于在 par 数组中使用 0、1、2 或 3、4、5。

然后在每种情况下,我们都会做两件事来增加值(value)。在这两种情况下,对于小的情况我们使用多项式,而对于大的情况我们使用指数/幂方程。

作为一个猜测,这是因为多项式是小值指数的一个不错的近似值——误差是可以接受的。您应该做的是确认猜测——看一下基于“大”幂/指数的方程的泰勒级数展开,看看它是否与多项式一致。或者用数字检查。

如果是这种情况,则意味着该等式具有可接受的已知误差量。 exppow更快版本通常具有已知的最大错误量;考虑使用这些。

如果不是这种情况,仍然可能存在可接受的误差量,但泰勒级数近似可以为您提供有关可接受误差量的“代码”信息。

下一步我要拆开这个等式的 8 个部分。每个分支中有正/负,第一个和第二个value+=,然后是多项式/指数情况。

我猜测 exp 占用 pow 时间的 1/3 是因为你在你的函数中有 3 次 pow 调用到 1 次 exp 调用,但你可能会发现一些有趣的东西,比如“我们所有的时间实际上在 Tterm > 0. case"或者你有什么。

现在检查调用点。您传递此函数的 Tterm 中是否存在模式?即,您是否倾向于按大致排序的顺序传递 Tterms?如果是这样,你可以在调用这个函数的之外测试调用哪个函数,分批进行。

简单地分批执行并优化编译和内联函数体可能会产生惊人的差异;编译器在矢量化工作方面做得越来越好。

如果这不起作用,您可以开始线程。在现代计算机上,你可以有 4-60 个线程独立解决这个问题,这个问题看起来你几乎可以得到线性加速。基本的线程库(如 TBB)非常适合此类任务。

对于下一步,如果您正在获取大量数据并且需要进行大量处理,则可以将其填充到 GPU 上并在那里解决。可悲的是,GPU<->RAM 通信很小,所以简单地在 GPU 上用这个函数做数学运算并用 RAM 来回读/写不会给你太多的性能。但如果在 GPU 上可以完成比这更多的工作,那可能是值得的。

关于c++ - 寻找加速功能的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56959472/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com