插件函数的性能在计算一组向量时与内置函数几乎一样,但在分布式计算时为什么差了好多倍

我写了一个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)
//25751 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* heapvector<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
请先 登录 后评论

1 个回答

Juntao Wang

内置函数beta是一个聚合函数,在分布式表上,内置函数用的是分布式计算,而插件函数因为没有分布式计算,是把所有数据取到发起节点上来再计算,所以慢。若内置函数不是聚合函数,算法差不多时,它的性能与插件函数是一样。

插件开发教程第3节讲了如何开发用于处理分布式SQL的聚合函数,可参考教程把插件getBeta改成分布式聚合函数。

请先 登录 后评论