我正在使用 C# 和 CUDAfy.net(是的,这个问题在带有指针的直接 C 中更容易,但考虑到更大的系统,我有使用这种方法的原因)。
我有一个视频帧采集卡,它以 30 FPS 的速度收集字节 [1024 x 1024] 图像数据。每 33.3 毫秒,它填充一个循环缓冲区中的一个槽,并返回一个System.IntPtr
指向 的非托管 1D 向量的*byte
; 循环缓冲区有 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
仅供参考:当我尝试使用 CUDA 模拟器时,它在 CopyToDevice 上中止,声称Data 不是主机分配的
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;
}