美文网首页软件测试职业探索程序员软件测试
优化算法在参数配置调优中的应用(python实现)

优化算法在参数配置调优中的应用(python实现)

作者: 胖艺 | 来源:发表于2018-01-21 13:11 被阅读158次

    引言

    系统运行的表现通常会受到多种参数变量的影响。参数取值的两两组合,其可能的组合数是非常大的。如何比较好且快速地找到合适的参数呢?今天要讨论的就是使用优化技术来试图解决这样一种问题。由于python对计算和算法提供了很好支持,本文采用python来进行问题的描述和解决。

    问题描述

    在如下图所描述的服务模型中,分为交易层-创建需要处理的交易任务,服务层-异步处理交易任务。其中,交易层需要配置交易处理的并发数dealconfig,用来控制创建交易任务的效率;服务层需要配置处理交易任务的并发数serverconfig,用来控制处理交易任务的效率。

    服务模型

    所以我们需要找到一组dealconfig、serverconfig的配置,定义如下:

    configs=['dealconfig','serverconfig']  

    使得系统运行是良好的,并且知道在这组配置下,打印系统预期的运行情况:

    def printsolution(vec):

        print configs[0],vec[0],dealcount(vec[0])

        print configs[1],vec[1],servercount(vec[1])

    其中vec代表配置项的一组可能的解,例如[20,34],dealcount()用于计算在当前交易并发配置时,交易创建的预期tps(dealtps),servercount()用于计算在当前服务并发配置时,交易处理的tps(servertps)。接下来我们就要确定一下这两个函数。

    确定配置项与TPS之间的关系函数

    通过《构建自动化性能测试系统的实践》的方式,我们很容易构建在不同配置项下的压力测试,进而得到不同配置项下的tps数据:

    例如:dealconfig与dealtps数据:

    交易配置与交易创建tps数据表 交易配置与交易创建tps数据走势图

    从走势图,我们可以把数据分为3段:[0,70],[70,100],[100,150],使用分段线性拟合来确定dealcount()函数。

    python的线拟合代码如下:

    import numpy as np

    def get1function(x,y):
        z = np.polyfit(x, y, 1)
        print z

    z即为一元方程的系数。

    对于x在[0,70],y=200x

    对于x在[70,100],y=14000

    对于x在[100,150],y=-77x+21476

    所以,我们可以得到dealcount()方法如下:

    def dealcount(cno):
        if cno <= 70 : return 200*cno
        elif cno >70 and cno <= 100: return 14000
        else : return -77*cno + 21476

    对于serverconfig与servertps数据:

    服务配置与交易处理tps数据表

    采用分段线性拟合后,可以确定servercount()函数:

    def servercount(cno):

        if cno <=30 : return 4.9*cno - 1

        elif cno >30 and cno <= 50:return -0.25*cno+148

        elif cno >50 and cno <= 80: return -0.45*cno+46

        else:return 10

    这两个函数的参数:cno应落在[0,150]。

    成本函数

    在使用优化算法时,需要比较那种配置项下的成本是低,用来确定出合适的配置。成本函数要求返回的值越大说明成本越高,该方案越差。在本例中,考虑的成本因素有:

    1、dealertps越大越好,且若是小于10000,则成本相应升高

    2、servertps越大越好,且若是小于100,则成本相应升高

    3、dealertps与servertps同样重要,分值提现应该在一个数量级上

    基于这三点考虑,构造的成本函数如下:

    def configcost(vec):

        dcount = dealcount(vec[0])

        scount = servercount(vec[1])

        cost = -(dcount + scount*100)+(10000-dcount)+(100-scount)*100

        return cost

    优化算法

    常见的优化算法:随机搜索、爬山法、模拟退火算法、遗传算法等【1】。优化算法至少需要传入参数值域,成本函数,输出一组解。这里以模拟退火算法做个例子,代码如下:

    模拟退火的实现:

    def annealingoptimize(domain,costf,T=10000.0,cool=0.95,step=1):
        vec=[random.randint(domain[i][0],domain[i][1]) for i in range(len(domain))]
        while T>0.1:
            i=random.randint(0,len(domain)-1)
            dir=random.randint(-step,step)
            vecb=vec[:]
            vecb[i]+=dir
            if vecb[i]<domain[i][0]:vecb[i]=domain[i][0]
            elif vecb[i]>domain[i][1]:vecb[i]=domain[i][1]
            ea=costf(vec)
            eb=costf(vecb)
            if (eb<ea or random.random()<pow(math.e,-(eb-ea)/T)):
                vec=vecb
            T=T*cool
        return vec

    其中domain表示值域,根据之前的测试数据,应在[0,150],定义如下:

    domain= [(0,150) for i in range(len(configs))]

    costf表示成本函数,即为configcost()

    运行

    自此,我们先后确定了配置项与tps之间的关系函数,成本函数、优化算法。现在只需要将其运行起来即可:

    s=annealingoptimize(domain,configcost)

    print configcost(s)

    printsolution(s)

    得到:

    -23150.0
    dealconfig 39 7800
    serverconfig 41 137.75

    表示:成本值为-23150,dealconfig为39,dealtps为7800,serverconfig为41,servertps为137.75。

    如果运行多次,会得到不同的解,这和成本函数是相关的,如下成本曲线图所示:

    成本曲线

    通常我们可能取到的是在一定范围内的成本最优的解,而不是整体最优解。


    【1】由于超出能力范围,没对算法做具体的说明,见谅。

    欢迎批评指正,共同学习进步。

    相关文章

      网友评论

        本文标题:优化算法在参数配置调优中的应用(python实现)

        本文链接:https://www.haomeiwen.com/subject/urdxaxtx.html