openGauss源码解析(161)

openGauss源码解析:AI技术(8)

5. 算法模块源码解析

可以将数据库的离线参数调优过程看作一个组合优化过程,即找到使数据库性能最好时的参数配置,该过程可以通过下述数学表达式描述。

其中,表示数据库在某个参数配置下的性能,表示数据库的参数配置,表示数据库参数的可配置集合。

X-Tuner支持的算法包括DDPG、PSO、贝叶斯优化,虽然实现原理不同,但他们都可以搜寻上述表达式中的,即数据库的最优参数配置。DDPG算法和贝叶斯优化算法通过引入第三方库实现,PSO算法则自行实现,实现代码在algorithms/pso.py文件中。

在tuner/xtuner.py文件中定义了全局搜索算法与强化学习算法的执行流程,其中强化学习算法的流程代码如下:

def rl_model(mode, env, config):

# 由于加载tensorflow的过程过于耗时,且并非是必要的,因此采用懒加载的模式

from tuner.algorithms.rl_agent import RLAgent

# 启动强化学习代理类

rl = RLAgent(env, alg=config['rl_algorithm'])

# 训练和调优两种模式对应不同的执行流程

# 模型需要先训练,然后才可以利用该模型进行调优。训练和调优过程的输出是待调优参数列表,由于共用一套模型,因此两种模式下,要求待调优的参数列表必须是一致的,否则会抛出输出维度不同的异常。

if mode == 'train':

logging.warning('The list of tuned knobs in the training mode '

'based on the reinforcement learning algorithm must be the same as '

'that in the tuning mode. ')

# 比较关键的参数是最大迭代轮次rl_steps,理论上越长越精准,但是也更加耗时

# max_episode_steps是强化学习算法中的每一轮的最大回合次数,在X-Tuner实现中,该参数被弱化了,一般默认即可

rl.fit(config['rl_steps'], nb_max_episode_steps=config['max_episode_steps'])

rl.save(config['rl_model_path'])

logging.info('Saved reinforcement learning model at %s.', config['rl_model_path'])

elif mode == 'tune':

全局优化算法的流程代码如下:

def global_search(env, config):

method = config['gop_algorithm']

# 判断选择使用哪种算法

if method == 'bayes':

from bayes_opt import BayesianOptimization

action = [0 for _ in range(env.nb_actions)]

pbound = {name: (0, 1) for name in env.db.ordered_knob_list}

# 定义一个黑盒函数,用于适配第三方库的接口

def performance_function(**params):

assert len(params) == env.nb_actions, 'Failed to check the input feature dimension.'

for name, val in params.items():

index = env.db.ordered_knob_list.index(name)

action[index] = val

s, r, d, _ = env.step(action)

return r # 期望结果越大越好

optimizer = BayesianOptimization(

f=performance_function,

pbounds=pbound

)

optimizer.maximize(

# 最大迭代轮次越大结果越精准,但是也更耗时

n_iter=config['max_iterations']

)

elif method == 'pso':

from tuner.algorithms.pso import Pso

def performance_function(v):

s, r, d, _ = env.step(v, False)

return -r # 因为PSO算法的实现中是寻找全局最小值,这里取相反数,就改为取全局最大值

pso = Pso(

func=performance_function,

dim=env.nb_actions,

particle_nums=config['particle_nums'],

# 最大迭代轮次越大结果越精准,但是也更耗时

max_iteration=config['max_iterations'],

x_min=0, x_max=1, max_vel=0.5

)

pso.minimize()

else:

raise ValueError('Incorrect method value: %s.' % method)

上述代码描述的是离线调优过程的策略,对于在线调优,则主要是以启发式规则的方法实现的,其主要代码存在于tuner/recommend.py中,此处逻辑大同小异,下面以shared_buffer参数推荐为例:

@cached_property

def shared_buffers(self):

# 此处应用的是DBA普遍认同的调优策略:在大内存环境下,shared_buffer占比可更高一些,小内存情况下占比应下调

mem_total = self.metric.os_mem_total # unit: kB

if mem_total < 1 * SIZE_UNIT_MAP['GB']:

default = 0.15 * mem_total

elif mem_total > 8 * SIZE_UNIT_MAP['GB']:

default = 0.4 * mem_total

else:

default = 0.25 * mem_total

recommend = default / self.metric.block_size

if self.metric.is_64bit:

database_blocks = self.metric.all_database_size / self.metric.block_size

# 如果数据库文件的比较小,则shared_buffer 也无须设置得太大,否则便是浪费资源

if database_blocks < recommend:

self.report.print_warn("The total size of all databases is less than the memory size. "

"Therefore, it is unnecessary to set shared_buffers to a large value.")

recommend = min(database_blocks, recommend)

upper = recommend * 1.15

lower = min(0.15 * mem_total / self.metric.block_size, recommend)

return Knob.new_instance(name="shared_buffers",

value_default=recommend,

knob_type=Knob.TYPE.INT,

value_max=upper,

value_min=lower,

restart=True)

else:

# 对于非64位操作系统,shared_buffer无须设置得太大

upper = min(recommend, 2 * SIZE_UNIT_MAP["GB"] / self.metric.block_size) # 32-bit OS only can use 2 GB mem.

lower = min(0.15 * mem_total / self.metric.block_size, recommend)

return Knob.new_instance(name="shared_buffers",

value_default=recommend,

knob_type=Knob.TYPE.INT,

value_max=upper,

value_min=lower,

restart=True)

不同的参数应用的规则都不相同,主要参考数据库的workload特征、硬件环境、当前状态等。即对于AP与TP场景,参数配置是不同的,如果用户没有通过配置文件明确指定场景的类型,则根据character.py文件中定义的workload_type()方法自动判断,获取数据库特征的方法都在character.py文件中定义。

posted @ 2024-04-30 11:18  openGauss-bot  阅读(1)  评论(0编辑  收藏  举报