IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 计算性能的提升之异步计算与并行计算(MXNet) -> 正文阅读

[人工智能]计算性能的提升之异步计算与并行计算(MXNet)

????????熟悉MXNet的异步计算原理,有助于开发更高效的程序,也可以在内存资源有限的情况下主动降低计算性能从而减小内存的开销,根据具体的情况做不同的操作,这是很重要的。

异步计算

from mxnet import autograd,gluon,nd
from mxnet.gluon import loss as gloss,nn
import os
import subprocess
import time

#d2lzh包中已有,里面是一些魔法函数,with操作将自动开始与结束
class Benchmark():
    def __init__(self,prefix=None):
        self.prefix=prefix+' ' if prefix else ''
    def __enter__(self):
        self.start=time.time()
    def __exit__(self,*args):
        print('%s 耗时:%.4f 秒'%(self.prefix,time.time()-self.start))


with Benchmark('加载到队列'):
    x=nd.random.uniform(shape=(4000,4000))
    y=nd.dot(x,x).sum()


with Benchmark('计算结果'):
    print('点积之和=',y)

'''
加载到队列  耗时:0.0010 秒
点积之和= 
[1.5990974e+10]
<NDArray 1 @cpu(0)>
计算结果  耗时:2.1746 秒
'''

第一个Benchmark中的nd.dot(x,x).sum()计时与下面比较快很多,这说明这个计算是不需要等它全部计算完再返回。
第二个Benchmark是打印出y的结果,这个时候就必须等待它全部计算完。
也就是说前端线程不执行计算,只需放在队列里面,交给后端的C++程序来处理即可,只要数据是保存在NDArray里并使用MXNet提供的运算符,MXNet将默认使用异步计算来获取高性能计算。

除了print函数之外,wait_to_read,waitall函数也需要等待所有计算完成,也时常拿来做性能测试。
来看下wait_to_read与waitall函数

wait_to_read与waitall

with Benchmark():
    y=nd.dot(x,x)
    y.wait_to_read()
# 耗时:1.6327 秒

with Benchmark():
    y=nd.dot(x,x)
    z=nd.dot(x,x)
    nd.waitall()
# 耗时:3.2405 秒

我们从名字包含wait也可以知道这两个函数都需要等待计算的全部完成才可以。
另外对于NDArray转换成其他不支持异步计算的数据结构的操作,也都需要等待计算的全部完成,比如:asnumpy与asscalar函数

with Benchmark():
    y=nd.dot(x,x)
    y.asnumpy()
# 耗时:1.5788 秒
with Benchmark():
    y=nd.dot(x,x)
    y.norm().asscalar()
# 耗时:1.7495 秒

像这些需要等待计算完成的都属于同步函数,在计算耗时方面肯定要多点,那是不是都使用异步不更好吗,也不是,这个需要看情况,因为异步操作,会将这些计算任务在极短时间内丢给后端,这样就会占用更多内存,尤其是深度学习的模型一般都是比较大的,这就需要很大的内存来存放,这也是它的缺点(特点),所以有时内存不够的情况,我们就需要使用同步函数,减小这个内存的占用。
我们来看下异步计算对内存的影响,异步对内存的影响(其中检测内存的函数只能在Linux或macOX系统上运行),没有Linux环境,可以在windows系统安装linux子系统,安装方法:Windows系统运行Linux(Windows Subsystem for Linux)

def data_iter():
    start=time.time()
    num_batches,batch_size=100,1024
    for i in range(num_batches):
        X=nd.random.normal(shape=(batch_size,512))
        y=nd.ones((batch_size,))
        yield X,y
        if (i+1)%50==0:
            print('batch %d,耗时:%f秒'%(i+1,time.time()-start))

#定义多层感知机、优化算法和损失函数
net=nn.Sequential()
net.add(nn.Dense(2048,activation='relu'),nn.Dense(512,activation='relu'),nn.Dense(1))
net.initialize()
trainer=gluon.Trainer(net.collect_params(),'sgd',{'learning_rate':0.005})
loss=gloss.L2Loss()

#辅助函数来检测内存的使用情况
def get_mem():
    res=subprocess.check_output(['ps','u','-p',str(os.getpid())])
    return int(str(res).split()[15])/1e3

for X,y in data_iter():
    break

loss(y,net(X)).wait_to_read()

l_sum,mem=0,get_mem()
for X,y in data_iter():
    with autograd.record():
        l=loss(y,net(X))
    l_sum+=l.mean().asscalar()#asscalar同步函数
    l.backward()
    trainer.step(X.shape[0])

nd.waitall()

print('增加的内存:%f MB'%(get_mem()-mem))
'''
batch 50,耗时:3.952379秒
batch 100,耗时:7.925409秒
增加的内存:41.824000 MB
'''

可以看到,耗时比较多,但是内存占用比较小,然后我们去掉同步函数,看下异步对内存的影响

mem=get_mem()
for X,y in data_iter():
    with autograd.record():
        l=loss(y,net(X))
    l.backward()
    trainer.step(X.shape[0])

nd.waitall()

print('增加的内存:%f MB'%(mem))

'''
batch 50,耗时:0.101752秒
batch 100,耗时:0.178621秒
增加的内存:323.216000 MB
'''

可以看到耗时小,但是内存占用大
其中进程打印看下:

b'USER ? ? ? PID %CPU %MEM ? ?VSZ ? RSS TTY ? ? ?STAT START ? TIME COMMAND
tony ? ? ? ?36 ?2.3 ?2.8 1220736 373352 pts/0 ?Sl+ ?10:15 ? 2:51 python\n'
["b'USER", 'PID', '%CPU', '%MEM', 'VSZ', 'RSS', 'TTY', 'STAT', 'START', 'TIME', 'COMMAND
tony', '36', '2.3', '2.8', '1220736', '373352', 'pts/0', 'Sl+', '10:15', '2:51', "python\\n'"]

并行计算

MXNet后端会自动构建计算图,通过计算图,系统可以知道所有计算的依赖关系,对没有依赖关系的计算执行并行计算提高性能。
比如,a=nd.ones((1,2))和b=nd.ones((1,2))这两个计算是没有依赖关系的,所以可以并行计算。
这里主要介绍CPU和GPU的并行计算

import d2lzh as d2l
import mxnet as mx
from mxnet import nd

def run(x):
    return [nd.dot(x,x) for _ in range(10)]

x_cpu=nd.random.uniform(shape=(2000,2000))
x_gpu=nd.random.uniform(shape=(6000,6000),ctx=mx.gpu(0))

run(x_cpu)
run(x_gpu)
nd.waitall()

with d2l.Benchmark('运行在CPU上'):
    run(x_cpu)
    nd.waitall()
#运行在CPU上 time: 1.9970 sec
    
with d2l.Benchmark('运行在GPU上'):
    run(x_gpu)
    nd.waitall()    
#运行在GPU上 time: 0.0266 sec

with d2l.Benchmark('CPU和GPU上进行并行计算'):
    run(x_gpu)
    run(x_gpu)
    nd.waitall()
#CPU和GPU上进行并行计算 time: 0.0447 sec

运行多了,占了很多显存,内存溢出,于是将x_gpu调小了测试,可以看出并行计算的耗时分别比在CPU和GPU上执行的耗时之和小很多

通信时间

我们在使用并行计算的时候,经常需要在内存和显存之间进行数据的复制,造成数据的通信,比如说,我们在GPU上计算,然后将计算的结果复制到CPU使用的内存,我们来看下这个GPU的耗时以及GPU到CPU的内存的通信时间。

import d2lzh as d2l
import mxnet as mx
from mxnet import nd

def copy_to_cpu(x):
    return [y.copyto(mx.cpu()) for y in x]

with d2l.Benchmark('运行在CPU上'):
    y=run(x_cpu)
    nd.waitall()

#运行在CPU上 time: 1.9947 sec

with d2l.Benchmark('拷贝到CPU的内存'):
    copy_to_cpu(y)
    nd.waitall()
    
#拷贝到CPU的内存 time: 0.0995 sec

看下并行的耗时

with d2l.Benchmark('运行和复制并行计算'):
? ? y=run(x_cpu)
? ? copy_to_cpu(y)
? ? nd.waitall()

#运行和复制并行计算 time: 2.0218 sec

可以看出并行计算的耗时小于两者的耗时之和。这里的并行与前面的同时使用CPU和GPU有点区别,因为这里存在了依赖关系,也就是说y[i]必须先在GPU上计算好才能复制到CPU使用的内存上,所幸的是,在计算y[i]的时候,系统可以复制y[i-1],从而减小计算和通信的总的运行时间。

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-10-22 21:15:35  更:2022-10-22 21:19:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 23:50:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码