pytorch 网络预处理与后处理中基于numpy操作的GPU加速
admin
2023-06-29 20:02:53
0

  背景

  python脚本运行在服务器端的卷积神经网络往往需要将图片数据从cv2(numpy.ndarray)->tensor送入网络,之后进行inference,再将结果从tensor-> numpy.ndarray的过程。

  由于cv2读取的数据存于内存中,以pytorch框架举例,在把数据送入GPU前会产生如下的数据转换:

  GPU准备进行inference之前会判断torch.cuda.FloatTensor是否已经处于显存内,如果没有的话会隐式调用内存与显存中的数据转存协议方法.async_copy()函数,将数据转存至GPU显存中,但该部分往往需要消耗大量时间。

  对策:直接在GPU显存中开辟空间

  应用库:cupy、dlpack

  一、前处理

  通常pytorch前处理如下:

  # 内存分配torch.FloatTensor空间

  batch_input = torch.zeros(len(image_list), 3, target_height, target_width)

  for index in range(len(image_list)):

  # image->numpy.ndarray

  img = cv2.resize(image_list[index].copy(), (target_width, target_height))

  # uint8->float32

  t_img = np.asarray(img, np.float32)

  #转置

  m_img = t_img.transpose((2, 0, 1))

  #numpy.ndarray->torch.FloatTensor + 图像正则化

  n_img = transform(torch.from_numpy(m_img))

  #组成batch data

  batch_input[index, :] = n_img

  # torch.FloatTensor-> torch.cuda.FloatTensor

  batch_input.cuda()

  如果将此batch送入GPU,则会发生如图1所示的数据转换。

  现用cupy来取代numpy操作:

  import cupy as cp

  # GPU显存分配cupy batch_data空间

  batch_input = cp.zeros((len(image_list), 3, target_height, target_width), dtype=cp.float32)

  for index in range(len(image_list)):

  # image->cupy.ndarray

  img = cv2.resize(image_list[index], (target_width, target_height))

  # numpy.uint8 -> cupy.float32

  t_img = cp.asarray(img, cp.float32)

  # 转置(cupy层面)

  m_img = t_img.transpose((2, 0, 1))

  # 图像正则化

  n_img = gpu_transform(m_img)

  # 组成 batch data

  batch_input[index, :] = n_img

  # cupy.ndarray -> torch.cuda.FloatTensor

  batch_data = from_dlpack(toDlpack(batch_input)).cuda()

  此时过程转换为:

  说明几点:

  1.1由于cupy直接在GPU显存中分配空间,不需要隐式调用.async_copy()将数据调入显存内,可见时间对比:

  隐式调用GPU前传时间如下图:

  非隐式调用GPU前传时间如下图:

  1.2 cupy.ndarray到torch.cuda.FloatTensor没办法直接转换,需要中间转换格式dlpack,具体转换如下

  rom cupy.core.dlpack import toDlpack

  from cupy.core.dlpack import fromDlpack

  from torch.utils.dlpack import to_dlpack

  from torch.utils.dlpack import from_dlpack

  import torch郑州妇科医院 http://www.sptdfk.com/

  #tensor->cupy

  cupy_data = fromDlpack(to_dlpack(tensor_data))

  #cupy->tensor

  tensor_data = from_dlpack(toDlpack(cupy_data))

  1.3 在pytorch框架中,有的工程需要图像正则化,有的不需要。当网络前传时若需要图像正则化(一般为减均值与除方差),一般选用的是torchvision.transform。但是该内置函数只接受CPU端的torch.FloatTensor,这就意味着若要使用内置transform函数,就需要将cupy GPU数据先转成CPU的torch.FloatTensor,势必会造成数据转换资源浪费。重写transform函数:

  self.mean = cp.array([102.9801, 115.9465, 122.7717])

  self.std = cp.array([1., 1., 1.])

  def gpu_transform(self, img):

  for index in range(img.shape[0]):

  img[index,:] -= self.mean[index]

  img[index, :] /= self.std[index]

  return img

  以上过程全部都在GPU内运行,时间几乎可以忽略

  二、后处理

  此部分适用于分割网络,即需要预先在GPU端分配生成的mask空间。通常做法分配torch.cuda.FloatTensor空间,隐式调用.async_copy()送入GPU,同样会消耗很多时间。类似于前处理,可以利用cupy生成mask空间,再转torch.cuda.FloatTensor。

  mask_gpu= from_dlpack(toDlpack(cp.zeros((len(image_list), self.num_classes, ori_img_size[0], ori_img_size[1]), dtype=cp.float32))).cuda()

  pytorch分配mask时间

  cupy分配mask时间

  三、cupy与常规前后处理时间对比


相关内容

热门资讯

多地职校招生报名火爆 作者 | 第一财经 林靖职业教育正在成为越来越多人的“主动选择”,中职赛道不再是备选项。近日,北京中...
初一男生校门口遭群殴或失聪,教... 哥哥同学辱骂母亲,辽宁鞍山13岁少年在学校门口维护哥哥与人发生争执,随后数名同龄少年一拥而上对其实施...
演唱会大量邀请票被当众焚毁,警... 极目新闻记者 杜光然5月29日,网友发帖称,有人当众焚烧大量演唱会邀请票,视频定位于温岭市体育中心。...
多所高校撤销外语学院 人工智能的发展及其他因素的影响下,外语类专业面临挑战,近年来一些高校对外语学院进行调整、重组。近日,...
解放军少将质问日方:有没有资格... 【环球时报-环球网报道 记者 郭媛丹 苏雅瑄】 “殷鉴不远,今天的世界又处在新的十字路口,我们必须警...
《给阿嬷的情书》导演被网友二创... 《给阿嬷的情书》这段解读直接破防!网友二创还原木生守桥的画面,把邮差落水,弄丢写有真相的讣告信件,解...
伊朗最高领袖顾问批特朗普背弃外... 据凤凰卫视报道,美伊谈判前景不明,伊朗最高领袖顾问雷扎伊5月30日指责美国总统特朗普第三次背弃外交原...
免去南开大学陈某院长、中山大学... 刚刚,南开大学和中山大学发布情况通报。南开大学:免去陈某院长职务南开大学通报中指出,论文第一作者郑某...
绿色算力全栈AI平台在呼和浩特...   新华社呼和浩特5月30日电(记者侯维轶)30日,绿色算力全栈AI平台——内蒙古词元交易平台在内蒙...
北京太空智算研究院在北京亦庄成... 红星资本局5月30日消息,近日,北京太空智算研究院在北京经济技术开发区(简称“北京经开区”,又称“北...