【问题标题】:What's the fastest way to copy values from one tensor to another in PyTorch?在 PyTorch 中将值从一个张量复制到另一个张量的最快方法是什么?
【发布时间】:2019-09-04 06:44:55
【问题描述】:

我正在尝试使用 PyTorch 将数据从一个 2D 张量复制到另一个 2D 张量的卷积膨胀。我正在将值从张量A 复制到张量B,这样复制到B 中的A 的每个元素都被n 零包围。

我已经尝试过使用嵌套的for 循环,这是一种非常幼稚的方式。当我使用大量灰度图像作为输入时,性能显然很差。

for i in range(A.shape[0]):
   for j in range(A.shape[1]):
      B[n+i][n+j] = A[i][j]

有什么更快的东西不需要使用循环吗?

【问题讨论】:

    标签: python conv-neural-network pytorch convolution tensor


    【解决方案1】:

    如果我正确理解您的问题,这里有一个更快的替代方案,没有任何循环:

    # sample `n`
    In [108]: n = 2
    
    # sample tensor to work with
    In [102]: A = torch.arange(start=1, end=5*4 + 1).view(5, -1)
    
    In [103]: A
    Out[103]: 
    tensor([[ 1,  2,  3,  4],
            [ 5,  6,  7,  8],
            [ 9, 10, 11, 12],
            [13, 14, 15, 16],
            [17, 18, 19, 20]])
    
    # our target tensor where we will copy values
    # we need to multiply `n` by 2 since there are two axes
    In [104]: B = torch.zeros(A.shape[0] + 2*n, A.shape[1] + 2*n)
    
    # copy the values, at the center of the grid
    # leaving `n` positions on the surrounding
    In [106]: B[n:-n, n:-n] = A
    
    # check whether we did it correctly
    In [107]: B
    Out[107]: 
    tensor([[ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
            [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
            [ 0.,  0.,  1.,  2.,  3.,  4.,  0.,  0.],
            [ 0.,  0.,  5.,  6.,  7.,  8.,  0.,  0.],
            [ 0.,  0.,  9., 10., 11., 12.,  0.,  0.],
            [ 0.,  0., 13., 14., 15., 16.,  0.,  0.],
            [ 0.,  0., 17., 18., 19., 20.,  0.,  0.],
            [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
            [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]])
    

    n=3的另一种情况

    In [118]: n = 3
    
    # we need to multiply `n` by 2 since there are two axes
    In [119]: B = torch.zeros(A.shape[0] + 2*n, A.shape[1] + 2*n)
    
    # copy the values, at the center of the grid
    # leaving `n` positions on the surrounding
    In [120]: B[n:-n, n:-n] = A
    
    In [121]: B
    Out[121]: 
    tensor([[ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
            [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
            [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
            [ 0.,  0.,  0.,  1.,  2.,  3.,  4.,  0.,  0.,  0.],
            [ 0.,  0.,  0.,  5.,  6.,  7.,  8.,  0.,  0.,  0.],
            [ 0.,  0.,  0.,  9., 10., 11., 12.,  0.,  0.,  0.],
            [ 0.,  0.,  0., 13., 14., 15., 16.,  0.,  0.,  0.],
            [ 0.,  0.,  0., 17., 18., 19., 20.,  0.,  0.,  0.],
            [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
            [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
            [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]])
    

    健全性检查与您基于 loop 的解决方案:

    In [122]: n = 2
    In [123]: B = torch.zeros(A.shape[0] + 2*n, A.shape[1] + 2*n)
    In [124]: for i in range(A.shape[0]):
         ...:    for j in range(A.shape[1]):
         ...:       B[n+i][n+j] = A[i][j]
         ...:       
    
    In [125]: B
    Out[125]: 
    tensor([[ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
            [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
            [ 0.,  0.,  1.,  2.,  3.,  4.,  0.,  0.],
            [ 0.,  0.,  5.,  6.,  7.,  8.,  0.,  0.],
            [ 0.,  0.,  9., 10., 11., 12.,  0.,  0.],
            [ 0.,  0., 13., 14., 15., 16.,  0.,  0.],
            [ 0.,  0., 17., 18., 19., 20.,  0.,  0.],
            [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
            [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]])
    

    时间

    # large sized input tensor
    In [126]: A = torch.arange(start=1, end=5000*4 + 1).view(5000, -1)
    In [127]: n = 2
    In [132]: B = torch.zeros(A.shape[0] + 2*n, A.shape[1] + 2*n)
    # loopy solution
    In [133]: %%timeit
         ...: for i in range(A.shape[0]):
         ...:    for j in range(A.shape[1]):
         ...:       B[n+i][n+j] = A[i][j]
         ...:       
    92.1 ms ± 434 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
    
    
    # clear out `B` again by reinitializing it.
    In [128]: B = torch.zeros(A.shape[0] + 2*n, A.shape[1] + 2*n)
    
    In [129]: %timeit B[n:-n, n:-n] = A
    49.6 µs ± 239 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    

    从上述时序中,我们可以看到矢量化方法比基于循环的解决方案快~200x

    【讨论】:

      猜你喜欢
      • 2019-04-25
      • 1970-01-01
      • 2020-03-18
      • 1970-01-01
      • 1970-01-01
      • 2021-06-18
      • 2019-05-17
      • 2020-08-01
      • 2021-07-23
      相关资源
      最近更新 更多