pytorch网络预处理与后处理中基于numpy操作的GPU加速-创新互联
背景
为江城等地区用户提供了全套网页设计制作服务,及江城网站建设行业解决方案。主营业务为成都网站制作、成都网站设计、江城网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!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与常规前后处理时间对比
另外有需要云服务器可以了解下创新互联cdcxhl.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。
新闻标题:pytorch网络预处理与后处理中基于numpy操作的GPU加速-创新互联
本文网址:http://cdiso.cn/article/pgssp.html