内置函数beta是一个聚合函数,在分布式表上,内置函数用的是分布式计算,而插件函数因为没有分布式计算,是把所有数据取到发起节点上来再计算,所以慢。若内置函数不是聚合函数,算法差不多时,它的性能与插件函数是一样。
插件开发教程第3节讲了如何开发用于处理分布式SQL的聚合函数,可参考教程把插件getBeta改成分布式聚合函数。
我写了一个DolphinDB插件函数getBeta,实现的功能与内置函数beta一样。另外写了一个如下所示的向量化自定义函数:
def betaVec(x, y){ sumX = x.sum() sumY = y.sum() sumXY = sum(x*y) sumX2 = sum(x*x) n = x.size() return (sumXY - sumX*sumY/n)/(sumX2 - sumX*sumX/n) }
对一组1亿个元素的向量的进行计算:
x=rand(1.0, 100000000) y=rand(1.0, 100000000) timer(10) demo::getBeta(x,y) //2171ms timer(10) beta(x, y) //2122ms timer(10) betaVec(x, y) //7385ms
测试结果表明,内置函数和插件函数耗时基本相同,自定义函数耗时多3倍。
但是在DolphinDB database集群上对分布式表中一个月的股票行情数据进行计算:
db=database("dfs://STOCK_SHL2_TAQ") t=db.loadTable("SHL2_TAQ") timer data = select beta(close, low) as beta_u from t where date between 2020.06.01:2020.06.30 group by date, symbol, bar(time, 5) //25,751 ms timer data = select demo::getBeta(close, low) as beta_u from t where date between 2020.06.01:2020.06.30 group by date, symbol, bar(time, 5) // 686,371 ms timer data = select betaVec(close, low) as beta_u from t where date between 2020.06.01:2020.06.30 group by date, symbol, bar(time, 5) //688,915ms
测试结果为:内置函数性能是插件函数的26倍。插件函数与自定义函数性能差不多。
我的问题就是:插件函数在计算一组向量时与内置函数几乎一样,但在分布式计算时为什么差了这么多倍?
下面附上我的插件代码,请大佬帮我看一下哪里有问题?
1.getBeta函数加在demo插件中,在src/demo.cpp中加入下面代码:
extern "C" ConstantSP getBeta(Heap* heap, vector<ConstantSP>& arguments );
2.在src/demo.cpp中加入下面代码:
ConstantSP beta(const ConstantSP& a, const ConstantSP& b){ INDEX len=std::min(a->size(),b->size()); INDEX obs=0; double sumAB=0; double sumA=0; double sumB=0; double sumB2=0; double bufA[Util::BUF_SIZE]; double bufB[Util::BUF_SIZE]; const double* pa; const double* pb; INDEX start=0; while(start<len){ int count=std::min(len-start,Util::BUF_SIZE); pa=a->getDoubleConst(start,count,bufA); pb=b->getDoubleConst(start,count,bufB); for(int i=0;i<count;++i) if(pa[i]!=DBL_NMIN && pb[i]!=DBL_NMIN){ sumB2+=pb[i]*pb[i]; sumAB+=pa[i]*pb[i]; sumA+=pa[i]; sumB+=pb[i]; ++obs; } start+=count; } ConstantSP result(Util::createNullConstant(DT_DOUBLE)); if(obs >= 2){ double varB = sumB2-sumB*sumB/obs; if(varB > 0) result->setDouble((sumAB - sumA*sumB/obs)/varB); } return result; } ConstantSP getBeta(Heap* heap, vector<ConstantSP>& arguments ) { std::string usage = "Usage:getBeta(x,y)"; if(!arguments[0]->isScalar() && !arguments[0]->isArray()) throw IllegalArgumentException(__FUNCTION__, usage + "x must be a scalar or vector."); if(!arguments[1]->isScalar() && !arguments[1]->isArray()) throw IllegalArgumentException(__FUNCTION__, usage + "y must be a scalar or vector."); return beta(arguments[0],arguments[1]); }
3.在PluginDemo.txt中追加:
getBeta,getBeta,system,2,2,0
4.编译命令:
g++ -DLINUX -fPIC -std=c++11 -O3 -c src/Demo.cpp -I../include -o Demo.o g++ -fPIC -shared -o libPluginDemo.so Demo.o -lDolphinDB -L /root/Downloads/v1.00.20/server