美文网首页
julia GPU编程之CUDA使用

julia GPU编程之CUDA使用

作者: 昵称违法 | 来源:发表于2021-06-11 14:14 被阅读0次

    本文使用的是CUDA.jl

    一、数据在内存和显存之间移动

    如下代码所示,a、b是在内存中的两个vec

    N = 2^10
    a = fill(1.0f0,N)
    b = fill(2.0f0,N)
    

    如何把a、b加载到GPU内存中去?用CuArray()

    a_gpu = CuArray(a)
    b_gpu = CuArray(b)
    

    如何把GPU中的array数据拷贝会内存中来?用Array()

    a_cpu = Array(a_gpu)
    b_cpu = Array(b_gpu)
    

    二、案例练习:如何用GPU来完成 【a_gpu + b_gpu】的操作

    【1】直接用向量化的【+】操作符完成 :a_gpu .+ b_gpu

     a_gpu .+ b_gpu
    

    总结:表达上比较自然、和蔼可亲

    【2】用【map】和【+】完成

    c_gpu = CUDA.map(+,a_gpu,b_gpu)
    

    总结:表达上比较自然、符合常见的编程习惯

    【3】用【map】和匿名函数完成

    c_cpu = CUDA.map((x,y)->x+y,a_gpu,b_gpu)
    

    总结:匿名函数增加了逻辑操作的丰富程度,比如你可以使用三元操作

    【4】用【map】和自定义函数完成

    #自定义一个add函数
    function fn_add(x,y)
        #bula bula 你还可以添加一大堆逻辑
        return x+y
    end
    c_cpu = CUDA.map(fn_add,a_gpu,b_gpu)
    

    总结:自定义function的好处就是,里面你可以写一些更复杂的逻辑,比如下面的例子:

    function fn_format(x,y)
        x>y ? '大' : '小'
    end
    c_cpu = CUDA.map(fn_format,a_gpu,b_gpu)
    @show(c_cpu)
    

    【5】自己写cuda 的kernel函数来完成

    你在写CUDA核函数的时候,你需要补充一些基础知识。
    以下概念你需要弄清楚:流处理器,warps,CUDA核心。Grid,blocks,threads。

    function cuda_add!(a,b,c)
        #blockDim().x  【线程块】的总数量
        #blockIdx().x   当前【线程块】的编号
        #threadIdx().x  当前【线程】在当前【线程块】中的编号
        #注意cuda核函数,return nothing
    
        index = (blockIdx().x - 1) * blockDim().x + threadIdx().x  #计算下标(index)
        @inbounds c[index] = a[index] + b[index]
        return nothing
    end
    
    numblocks = ceil(Int, N/256) #分成多少个线程块
    
    @cuda threads=256 blocks=numblocks cuda_add!(a_gpu,b_gpu,res)
    @show(res)
    

    注意:
    (1)kernel函数不能返回具体的值,只能返回nothing
    (2)函数带一个【!】叹号,代表变量会被就地更新
    (3)CUDA kernel编程请参考https://github.com/JuliaGPU/CUDA.jl

    三、一些奇怪的问题

    下面的代码中,fn_format1和fn_format2的功能是一样的,但为红色代码出会出现报错呢?是精度导致的计算分支的问题吗?


    image.png
    a_d = CUDA.rand(1024)
    b_d = CUDA.rand(1024)
    
    function fn_format1(a,b)    
        if a > b
            a+b
        elseif a <=b
            a*b
        end
    end
    
    function fn_format2(a,b)
        a>b ? a+b : a*b
    end
    
    CUDA.map(fn_format1,a_d,b_d) #此行报错
    CUDA.map(fn_format2,a_d,b_d)
    

    把if加一个else分支后,不再出问题。


    image.png

    相关文章

      网友评论

          本文标题:julia GPU编程之CUDA使用

          本文链接:https://www.haomeiwen.com/subject/vxzmeltx.html