环境

python 3.6
xgboost 1.0.1

现象

在一台48c的服务器上,就import xgboost,还没进行训练,通过命令发现,线程数就达到48个
代码:

import time
import xgboost

if __name__ == '__main__':
    print("睡眠开始")
    time.sleep(15)
    print("睡眠结束")

这里启了一个镜像,通过Linux中/proc/pid/status查询线程数

pid=`docker top fad7c792ccf35b65ddd | grep test.py |  awk '{print $2}'`;cat /proc/$pid/status  

查询到的线程数为48
在这里插入图片描述

原理

在XGBoost里,单机多线程,并没有通过显式的pthread这样的方式来实现,而是通过OpenMP来完成多线程的处理,这可能跟XGBoost里多线程的处理逻辑相对简单,没有复杂的线程之间同步的需要,所以通过OpenMP可以支持得比较好,也简化了代码的开发和维护负担。

OpenMP

OpenMP 是 Open MultiProcessing 的缩写。是一套支持跨平台共享内存方式的多线程并发的编程API。
在项目程序已经完成好的情况下不需要大幅度的修改源代码,只需要加上专用的pragma来指明自己的意图,由此编译器可以自动将程序进行并行化,并在必要之处加入同步互斥以及通信。
例如 #pragma omp parallel for

解决方案

omp_num_threads

对于调用OpenMP的lib编译编译成OpenMP的程序,对于加了#pragma的代码,默认情况下会调用和你CPU内核数相同数量的线程来执行这段程序。而可以通过设置环境变量OMP_NUM_THREADS 来控制线程数。

python可以通过以下设置环境变量omp_num_threads

import os
os.environ['OMP_NUM_THREADS'] = "1"

xgboost多线程

对于sklearn的XGBClassifier、XGBModel
可以通过设置n_jobs来控制线程数

对于原生的xgboost,通过nthread来控制线程数

如果没有通过OMP_NUM_THREADS变量来控制,那么配置了n_jobs或者nthread,则在原有48核的基础上,再调整线程数。

Logo

更多推荐