2015-11-08 1 views
1

У меня есть массивы a и b как подписи double [] [].Alea CUDA Jagged Arrays

Я хочу сравнить детей этих массивов в моем ядре (они имеют одинаковую длину).

На данный момент я получаю ошибку при

use data = this.GPUWorker.MallocArray(data) 

называется.

Исключение брошено: 'System.Exception' в Alea.CUDA.dll Дополнительная информация: привязка нулевой копии узла Host является непубличной функцией.

Я не вижу, как я неправильно использую функцию 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 

ответ

1

В версии 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**.