c# – 将非托管System.IntPtr字节向量复制到2D设备字节数组的GPU行

我正在使用C#和CUDAfy.net(是的,这个问题在带有指针的直接C中更容易,但我有理由在给定更大的系统时使用这种方法).

我有一个视频帧采集卡,以30 FPS收集字节[1024 x 1024]图像数据.每33.3毫秒填充一个循环缓冲区中的一个插槽并返回一个System.IntPtr,它指向* byte的未管理的1D向量;循环缓冲区有15个插槽.

在GPU设备(Tesla K40)上,我想要一个全局的2D数组,它被组织成一个密集的2D数组.也就是说,我想要像循环队列这样的东西,但在GPU上组织为密集的2D阵列.

byte[15, 1024*1024] rawdata; 
// if CUDAfy.NET supported jagged arrays I could use byte[15][1024*1024 but it does not

如何每33毫秒填一个不同的行?我是否使用类似的东西:

gpu.CopyToDevice<byte>(inputPtr, 0, rawdata, offset, length) // length = 1024*1024
//offset is computed by  rowID*(1024*1024) where rowID wraps to 0 via modulo 15.
// inputPrt is the System.Inptr that points to the buffer in the circular queue (un-managed)?
// rawdata is a device buffer allocated gpu.Allocate<byte>(1024*1024);

在我的内核标题是:

[Cudafy]
public static void filter(GThread thread, byte[,] rawdata, int frameSize, byte[] result)

我确实尝试过这些方法.但是CudaFy中没有API模式:

GPGPU.CopyToDevice(T) Method (IntPtr, Int32, T[,], Int32, Int32, Int32)

所以我使用gpu.Cast函数将2D设备数组更改为1D.

我尝试了下面的代码,但我得到了CUDA.net异常:ErrorLaunchFailed

FYI: When I try the CUDA emulator, it aborts on the CopyToDevice
claiming that Data is not host allocated

public static byte[] process(System.IntPtr data, int slot)
{
    Stopwatch watch = new Stopwatch();
    watch.Start();
    byte[] output = new byte[FrameSize];
    int offset = slot*FrameSize;
    gpu.Lock();
    byte[] rawdata = gpu.Cast<byte>(grawdata, FrameSize); // What is the size supposed to be? Documentation lacking
    gpu.CopyToDevice<byte>(data, 0, rawdata, offset, FrameSize * frameCount);
    byte[] goutput = gpu.Allocate<byte>(output);
    gpu.Launch(height, width).filter(rawdata, FrameSize, goutput);
    runTime = watch.Elapsed.ToString();
    gpu.CopyFromDevice(goutput, output);
    gpu.Free(goutput);
    gpu.Synchronize();
    gpu.Unlock();
    watch.Stop();
    totalRunTime = watch.Elapsed.ToString();
    return output;
}

最佳答案 您应该考虑使用内置的GPGPU异步功能,以便以非常有效的方式将数据从/向主机/设备移动并使用gpuKern.LaunchAsync(…)

查看http://www.codeproject.com/Articles/276993/Base-Encoding-on-a-GPU以获得有效的使用方法.另一个很好的例子可以在CudafyExamples项目中找到,查找PinnedAsyncIO.cs.做你所描述的所需的一切.

这是在Cudafy.Host项目中的CudaGPU.cs中,它匹配您正在寻找的方法(只是它的异步):

public void CopyToDeviceAsync<T>(IntPtr hostArray, int hostOffset, DevicePtrEx devArray,
                                  int devOffset, int count, int streamId = 0) where T : struct;
public void CopyToDeviceAsync<T>(IntPtr hostArray, int hostOffset, T[, ,] devArray,
                                 int devOffset, int count, int streamId = 0) where T : struct;
public void CopyToDeviceAsync<T>(IntPtr hostArray, int hostOffset, T[,] devArray,
                                  int devOffset, int count, int streamId = 0) where T : struct;
public void CopyToDeviceAsync<T>(IntPtr hostArray, int hostOffset, T[] devArray,
                                  int devOffset, int count, int streamId = 0) where T : struct;
点赞