首页 文章

使用Numba Vectorize目标的负速度增益= 'cuda'

提问于
浏览
2

我正在尝试使用CUDAcast#10中提供的代码片段here来测试使用Python Numba模块's @vectorize decorator for speeding up a code snippet relevant to my actual code. I' m的有效性,如下所示:

import numpy as np
from timeit import default_timer as timer
from numba import vectorize


@vectorize(["float32(float32, float32)"], target='cpu')
def VectorAdd(a,b):
        return a + b

def main():
        N = 32000000

        A = np.ones(N, dtype=np.float32)
        B = np.ones(N, dtype=np.float32)
        C = np.zeros(N, dtype=np.float32)


        start = timer()
        C = VectorAdd(A, B)
        vectoradd_time = timer() - start

        print("C[:5] = " + str(C[:5]))
        print("C[-5:] = " + str(C[-5:]))

        print("VectorAdd took %f seconds" % vectoradd_time)

if __name__ == '__main__':
        main()

在CUDAcast的演示中,演示者通过@vectorize装饰器将大型数组方程式发送到gpu,从而获得100倍的加速 . 但是,当我将@vectorize目标设置为gpu时:

@vectorize(["float32(float32, float32)"], target='cuda')

......结果慢了3-4倍 . 使用target ='cpu',我的运行时间为0.048秒;使用target ='cuda'我的运行时间为0.22秒 . 我正在使用配备Intel Core i7-4710MQ处理器和NVIDIA Quadro K2100M GPU的DELL Precision笔记本电脑 . 运行nvprof(NVIDIA分析器工具)的输出表明大部分时间花费在内存处理(预期)上,但即使功能评估在GPU上花费的时间也比整个过程在CPU上花费的时间长 . 显然这不是我希望的结果,但这是由于我的一些错误还是基于我的硬件和代码这是合理的?

1 回答

  • 1

    这个问题对我来说也很有意思 . 我已经尝试过您的代码并获得了类似的结果 . 以某种方式调查此问题我使用cuda.jit编写了CUDA内核并将其添加到您的代码中:

    import numpy as np
    from timeit import default_timer as timer
    from numba import vectorize, cuda
    
    N = 16*50000 #32000000
    blockdim = 16, 1
    griddim = int(N/blockdim[0]), 1
    
    @cuda.jit("void(float32[:], float32[:])")
    def VectorAdd_GPU(a, b):
        i = cuda.grid(1)
        if i < N:
            a[i] += b[i]
    
    @vectorize("float32(float32, float32)", target='cpu')
    def VectorAdd(a,b):
        return a + b
    
    
    A = np.ones(N, dtype=np.float32)
    B = np.ones(N, dtype=np.float32)
    C = np.zeros(N, dtype=np.float32)
    
    start = timer()
    C = VectorAdd(A, B)
    vectoradd_time = timer() - start
    print("VectorAdd took %f seconds" % vectoradd_time)
    
    start = timer()
    d_A = cuda.to_device(A)
    d_B = cuda.to_device(B)
    VectorAdd_GPU[griddim,blockdim](d_A, d_B)
    C = d_A.copy_to_host()
    vectoradd_time = timer() - start
    print("VectorAdd_GPU took %f seconds" % vectoradd_time)
    
    print("C[:5] = " + str(C[:5]))
    print("C[-5:] = " + str(C[-5:]))
    

    在这个“基准”中,我还考虑了从主机到设备以及从设备到主机复制阵列的时间 . 在这种情况下,GPU功能比CPU 1慢 .

    对于上述情况:

    CPU - 0.0033; 
    GPU - 0.0096; 
    Vectorize (target='cuda') - 0.15 (for my PC).
    

    如果没有考虑复制时间:

    GPU - 0.000245
    

    所以,我所学到的,(1)从主机到设备以及从设备到主机的复制非常耗时 . 这是显而易见的,众所周知的 . (2)我不知道原因,但@vectorize可以显着减慢GPU的计算速度 . (3)最好使用自编写的内核(当然最小化内存复制) .

    顺便说一下,我还通过显式有限差分方案解决了热传导方程,测试了@ cuda.jit,发现在这种情况下,python程序执行时间与C程序相当,并提供大约100倍的加速 . 这是因为,幸运的是,在这种情况下,您可以进行多次迭代,而无需在主机和设备之间进行数据交换 .

    UPD . 二手软件和硬件:Win7 64bit,CPU:Intel Core2 Quad 3GHz,GPU:NVIDIA GeForce GTX 580 .

相关问题