Pytorch 其它有关Tensor的话题,GPU,向量化

本文介绍了TensorFlow中tensor在GPU和CPU间传输的方法,强调使用`.to(device)`的灵活性,并提醒避免频繁的数据传输以提高效率。还涉及tensor的保存和加载,以及向量化计算的重要性,指出应避免Python原生for循环以提升计算速度。最后,讨论了设置打印选项和避免数值溢出的技巧。
摘要由CSDN通过智能技术生成

3.1.4 其它有关Tensor的话题

这部分的内容不好专门划分一小节,但是笔者认为仍值得读者注意,故而将其放在这一小节。

GPU/CPU

tensor可以很随意的在gpu/cpu上传输。使用tensor.cuda(device_id)或者tensor.cpu()。另外一个更通用的方法是tensor.to(device)

In [119]:

a = t.randn(3, 4)
a.device

Out[119]:

device(type='cpu')

In [120]:

if t.cuda.is_available():
    a = t.randn(3,4, device=t.device('cuda:1'))
    # 等价于
    # a.t.randn(3,4).cuda(1)
    # 但是前者更快
    a.device

In [121]:

device = t.device('cpu')
a.to(device)

Out[121]:

tensor([[-1.8934,  0.8776,  2.3714, -0.0861],
        [-0.2218,  1.7379,  0.5166,  0.2940],
        [ 1.1621,  0.6702, -0.4791, -0.7298]])

注意

  • 尽量使用tensor.to(device), 将device设为一个可配置的参数,这样可以很轻松的使程序同时兼容GPU和CPU
  • 数据在GPU之中传输的速度要远快于内存(CPU)到显存(GPU), 所以尽量避免频繁的在内存和显存中传输数据。

持久化

Tensor的保存和加载十分的简单,使用t.save和t.load即可完成相应的功能。在save/load时可指定使用的pickle模块,在load时还可将GPU tensor映射到CPU或其它GPU上。

In [122]:

if t.cuda.is_available():
    a = a.cuda(1) # 把a转为GPU1上的tensor,
    t.save(a,'a.pth')

    # 加载为b, 存储于GPU1上(因为保存时tensor就在GPU1上)
    b = t.load('a.pth')
    # 加载为c, 存储于CPU
    c = t.load('a.pth', map_location=lambda storage, loc: storage)
    # 加载为d, 存储于GPU0上
    d = t.load('a.pth', map_location={'cuda:1':'cuda:0'})

向量化

向量化计算是一种特殊的并行计算方式,相对于一般程序在同一时间只执行一个操作的方式,它可在同一时间执行多个操作,通常是对不同的数据执行同样的一个或一批指令,或者说把指令应用于一个数组/向量上。向量化可极大提高科学运算的效率,Python本身是一门高级语言,使用很方便,但这也意味着很多操作很低效,尤其是for循环。在科学计算程序中应当极力避免使用Python原生的for循环

In [123]:

def for_loop_add(x, y):
    result = []
    for i,j in zip(x, y):
        result.append(i + j)
    return t.Tensor(result)

In [124]:

x = t.zeros(100)
y = t.ones(100)
%timeit -n 10 for_loop_add(x, y)
%timeit -n 10 x + y
10 loops, best of 3: 997 µs per loop
The slowest run took 5.80 times longer than the fastest. This could mean that an intermediate result is being cached.
10 loops, best of 3: 4.91 µs per loop

可见二者有超过几十倍的速度差距,因此在实际使用中应尽量调用内建函数(buildin-function),这些函数底层由C/C++实现,能通过执行底层优化实现高效计算。因此在平时写代码时,就应养成向量化的思维习惯,千万避免对较大的tensor进行逐元素遍历。

此外还有以下几点需要注意:

  • 大多数t.function都有一个参数out,这时候产生的结果将保存在out指定tensor之中。
  • t.set_num_threads可以设置PyTorch进行CPU多线程并行计算时候所占用的线程数,这个可以用来限制PyTorch所占用的CPU数目。
  • t.set_printoptions可以用来设置打印tensor时的数值精度和格式。 下面举例说明。

In [125]:

a = t.arange(0, 20000000)
print(a[-1], a[-2]) # 32bit的IntTensor精度有限导致溢出
b = t.LongTensor()
t.arange(0, 20000000, out=b) # 64bit的LongTensor不会溢出
b[-1],b[-2]
tensor(19999999) tensor(19999998)

Out[125]:

(tensor(19999999), tensor(19999998))

In [126]:

a = t.randn(2,3)
a

Out[126]:

tensor([[ 1.2645,  0.0270, -0.7174],
        [ 0.4271,  0.0869,  0.6367]])

In [127]:

t.set_printoptions(precision=10)
a

Out[127]:

tensor([[ 1.2645452023,  0.0270472951, -0.7174307108],
        [ 0.4270690084,  0.0868919790,  0.6366676688]])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值