Alea CUDA 锯齿状数组

Alea CUDA Jagged Arrays

我有两个签名为double[][]的数组a和b。

我想比较内核中那些数组的子数组(它们的长度相同)。

目前我在

时遇到错误
use data = this.GPUWorker.MallocArray(data)

被调用。

抛出异常:Alea.CUDA.dll 中的 'System.Exception' 附加信息:主机数组零拷贝绑定是非 public 功能。

我看不出我是如何错误地使用 MallocArray 函数的?

let inline (?+) a b = ((b - a) / a) * 100.0

let inline change a b = 
    let a = a |> Array.reduce (+)
    let b = b |> Array.reduce (+)
    if a > 0.0 && b > 0.0 && (?+) a b >= 5.0 then a else 0.0

type GPU<'T>(target, op : Expr<'T[] -> 'T[] -> 'T>) = 
    inherit ILGPUModule(target)

    new(target, op : Func<'T[], 'T[], 'T>) = 
        new GPU<'T>(target, <@ fun x y -> op.Invoke(x, y) @>)

    [<Kernel;ReflectedDefinition>]
    member this.Kernel (n : int) (input : deviceptr<'T[]>) (input2 : deviceptr<'T[]>) (output : deviceptr<'T>) = 

        let start = blockIdx.x * blockDim.x + threadIdx.x
        let stride = gridDim.x * blockDim.x
        let mutable i = start

        // TODO this is the actual logic.
        while i < n do
            let a = input.[i]
            let b = input2.[i]
            output.[i] <- __eval(op) a b
            i <- i + stride

    member this.Apply(n : int, input : deviceptr<'T[]>, input2 : deviceptr<'T[]>, output : deviceptr<'T>) = 
        let numSm = this.GPUWorker.Device.Attributes.MULTIPROCESSOR_COUNT
        let blockSize = 256
        let gridSize = min (16 * numSm) (divup n blockSize)
        let lp = LaunchParam(gridSize, blockSize)
        this.GPULaunch <@ this.Kernel @> lp n input input2 output

    /// Takes in generic array to be used by GPU.
    // May need modification to support other input parameters.
    member this.Apply(data : 'T[][], pattern : 'T[][]) = 

        // Allocate GPU memory for the data sets.
        use data = this.GPUWorker.MallocArray(data)
        use pattern = this.GPUWorker.MallocArray(pattern)

        // Output length is likely to match the number of elements in the input array.
        use output = this.GPUWorker.Malloc(data.Length)

        // Execute GPU compuation. 
        this.Apply(data.Length, data.Ptr, pattern.Ptr, output.Ptr)

        // Copy data from GPU to CPU memory.
        output.Gather()

[<AOTCompile>]
type GPUModule(target) = 
    inherit GPU<double>(target, fun a b -> change a b)
    static let instance = lazy new GPUModule(GPUModuleTarget.DefaultWorker)
    static member DefaultInstance = instance.Value

在版本 2 中,您不能使用交错数组,因为交错数组本身不可 blittable。我们将在下一个版本中支持它。

我认为目前您有两个选择:

  1. 如果你的交错数组的维度是已知的,你可以把它变成一个线性数组,然后做一些索引计算。

  2. 你必须单独分配内部数组,并将它们的指针填充到外部数组,比如:

代码:

let innerDMems = jaggedHostArray |> Array.map (fun array -> worker.Malloc array)
use outterDMem = worker.Malloc(innerDMems |> Array.map (fun dmem -> dmem.Ptr))        
....
//launch kernel with outterDMem.Ptr which is deviceptr<deviceptr<T>>
....
innerDMems |> Array.iter (fun dmem -> dmem.Dispose())

然后你的签名是deviceptr<deviceptr<T>>,就像C语言T**