1

私は配列 a と b の両方の署名 double[][] を持っています。

カーネル内のこれらの配列の子を比較したい (それらは同じ長さです)。

現時点では、次の場合にエラーが発生します

use data = this.GPUWorker.MallocArray(data)

と呼ばれます。

例外がスローされました: Alea.CUDA.dll の 'System.Exception' 追加情報: ホスト配列のゼロコピー バインディングは非公開機能です。

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
4

1 に答える 1

1

バージョン 2 では、ジャグ配列自体は blittable ではないため、ジャグ配列を使用できません。次のバージョンでサポートしています。

現在、次の 2 つのオプションがあると思います。

  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**

于 2015-11-10T09:05:31.590 に答える