python启动多核并行编程
引言:
最近在做可视化字幕语料的数据预处理工作,有两万多条数据,需要调用NL4DV的可视分析库做初步的整理工作,一次调用大概2s,我算了下 2.5w条数据 * 2s / 3600s = 14个小时;我时间挺紧迫的,没有时间等这么久。于是,就决定尝试启用Python多线程去执行2.5w条数据的分析任务。
一些基础知识概览:
- 并发、并行的概念与关系
- CPU、物理核、逻辑核概念与关系
- 查看Mac核的数量
- Python多线程实现
以下python启动多核并行编程的正文:
(1)并发、并行的概念与关系
并发(concurrency)指计算机似乎同时在做很多事情。例如对于单CPU机器,操作系统会在各个程序之间进行快速的切换,达到多个程序同时执行的假象。 并行(Parallel)系统有一个以上CPU时,当一个CPU执行一个进程时,另一个CPU可以执行另一个进程,两个进程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行。
区别:
- 并发,指的是多个事情,在同一时间段内同时发生了。
- 并行,指的是多个事情,在同一时间点上同时发生了。
并发的多个任务之间是互相抢占资源的。 并行的多个任务之间是不互相抢占资源的.
只有在多CPU的情况中,才会发生并行。否则,看似同时发生的事情,其实都是并发执行的。
(2)CPU、物理核、逻辑核概念和关系
- CPU 就是实实在在插在主机上看得见摸得着那块CPU硬件
- 物理核 一个物理CPU上可能会有多个核心,日常中说的双核,四核就是指的CPU核数
- 逻辑核 借助超线程技术,可以把一个物理线程模拟出两个线程来使用,这时逻辑核数就是物理核数的两倍了
(3)查看Mac核的数量
- 查看所有信息
sysctl machdep.cpu
此命令会将所有CPU信息列出,根据需要查看即可。 如果只关心部分信息,可添加更详细的查询参数。下面的-n参数,表示是否显示查询的变量名。
- 查看CPU型号
sysctl -n machdep.cpu.brand_string
- 查看CPU物理核数
sysctl hw.physicalcpu
或者
sysctl -n machdep.cpu.core_count
- 查看逻辑核数
sysctl hw.logicalcpu
或者
sysctl -n machdep.cpu.thread_count
(4)Python多线程实现
启动Python多线程主要是为了最大化利用好硬件资源,缩短程序执行时间。
- 参考【菜鸟教程】的demo
import _thread
import time
# 5 * 6 = 30个循环
#现在手动的操作6个子线程。并发调用
# 为线程定义一个函数
def print_time( threadName, delay):
count = 0
while count < 5:
print ("time.sleep before: %s: %s" % ( threadName,delay))
time.sleep(delay)
count += 1
print ("time.sleep end: %s: %s" % ( threadName, delay))
print ("start",time.ctime(time.time()))
# 创建两个线程
try:
_thread.start_new_thread( print_time, ("Thread-1", 1, ) )
_thread.start_new_thread( print_time, ("Thread-2", 2, ) )
_thread.start_new_thread( print_time, ("Thread-3", 2, ) )
_thread.start_new_thread( print_time, ("Thread-4", 1, ) )
_thread.start_new_thread( print_time, ("Thread-5", 2, ) )
_thread.start_new_thread( print_time, ("Thread-6", 1, ) )
except:
print ("Error: 无法启动线程")
print ("end",time.ctime(time.time()))
- 实际调用
# main
dataFiles = os.listdir('datasets/data')
thread_count = 16
total = 16 * 1000 # 1 - 160001.csv
#分段
duration = int(total / thread_count) # 1000
def runAnalyse(start,end,threadName):
print('threadName Analysebrefore ',threadName)
#这个有一个异步操作
print('threadName AnalysebreEnd ',threadName)
for t in range(thread_count):
start = t * duration + 1
end = (t+1) * duration
_thread.start_new_thread( runAnalyse, (start, end,'thread-'+ str(t)) )
“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天”