01.深度学习中GPU的多进程推理实现方式

1.需求场景

一次需要推理的数据过多,需要使用多进程技术,同时推理,加快速度。

2.技术实现

2.1 进程:程序的基本执行实体,每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region),是系统分配资源和调度的独立单位。

  • 动态性:进程的实质是程序在多道程序系统中的一次执行过程,进程是动态产生,动态消亡的。
  • 并发性:任何进程都可以同其他进程一起并发执行
  • 独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位;
  • 异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进
  • 结构特征:进程由程序、数据和进程控制块三部分组成。
  • 多个不同的进程可以包含相同的程序:一个程序在不同的数据集里就构成不同的进程,能得到不同的结果;但是执行过程中,程序不能发生改变。

2.2 线程:操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。

  • 轻型实体
  • 独立调度和分派的基本单位
  • 可并发执行
  • 共享进程资源:在同一进程中的各个线程,都可以共享该进程所拥有的资源,这首先表现在:所有线程都具有相同的地址空间(进程的地址空间),线程之间互相通信不必调用内核。

3.多进程实现思路

3.1 进程池
控制可以提交作业的工作进程池。它支持带有超时和回调的异步结果,以及一个并行的 map 实现

from multiprocesssing import Pool
from multiprocessing import Manager
from tqdm import tqdm

# 将ai推理结果回传,在主进程进行记录
def main_predict(model,initial):
    ...
    result = model(initial)
    return result

def setcallback():
    ...
    # print(os.getpid())

def create_ai_model():
   ...
   return ai_model

if __name__ == '__main__':
   print(os.getpid())
   ai_model = create_ai_model()
   pool_nums = 4
   pool = Pool(pool_nums) # 创建4个进程
   inputs = [] # 需要推理的数据列表,可迭代对象
   for i in tqdm(inputs):
       pool.apply_async(func=main_predict,args(ai_model,i),
       callback=setcallback)
pool.close()
pool.join()

3.2 使用队列方法
使用队列和生产者和消费者模型进行进程之间的资源分配

import csv
import multiprocessing as mp
from multiprocessing import Manager

def producer(mp_queue,inputs):
    while True:
        info = inputs.get()
        mp_queue.put(info)
        if inputs.empty():
            mp_queue.put(None)
            break
def consumer(queue,model,result,lock):
    ai_model = create_model()
    while True:
        info = queue.get()
        if info is None:
            break
        else:
            sub_result = main_predict(model,info)
            with lock:
                result.append(subresult)
                
if __name__ == '__main__':
    inputs = []
    inputs_queue = mp.Queue(len(inputs))
    [inputs_queue.put(info) for info in inputs]
    result = Manager().list() # 使用于进程之间的数据存储
    mp_queue_img = mp.Queue(5) # 获取数据
    processes = list()
    lock = Manager().lock()
    csvfile = open('record.csv','w')
    csvwriter = csv.writer(csvfile)
    processes.extend([mp.Process(target=producer,args=(mp_queue_img,inputs-queue))])
    processes.extend([mp.Process(target=consumer,args=(mp_queue_img,result,lock)) for _ in range(2)])
    [setattr(process,'damon',True) for process in processes]
    [process.start() for process in processes]

    while True:
        if inputs_queue.empty():
            for item in result:
                csvwriter.writerow([item])
            [process.join() for process in processes]
            mp_queue_img.close()
            inputs_queue.close()
            break
            

你可能感兴趣的:(多进程,深度学习,人工智能,多进程)