使用VS 2012,.NET 4.5、64位和CUDAfy 1.12,我有以下概念证明
using System;
using System.Runtime.InteropServices;
using Cudafy;
using Cudafy.Host;
using Cudafy.Translator;
namespace Test
{
[Cudafy(eCudafyType.Struct)]
[StructLayout(LayoutKind.Sequential)]
public struct ChildStruct
{
[MarshalAs(UnmanagedType.LPArray)]
public float[] FArray;
public long FArrayLength;
}
[Cudafy(eCudafyType.Struct)]
[StructLayout(LayoutKind.Sequential)]
public struct ParentStruct
{
public ChildStruct Child;
}
public class Program
{
[Cudafy]
public static void KernelFunction(GThread gThread, ParentStruct parent)
{
long length = parent.Child.FArrayLength;
}
public static void Main(string[] args)
{
var module = CudafyTranslator.Cudafy(
ePlatform.x64, eArchitecture.sm_35,
new[] {typeof(ChildStruct), typeof(ParentStruct), typeof(Program)});
var dev = CudafyHost.GetDevice();
dev.LoadModule(module);
float[] hostFloat = new float[10];
for (int i = 0; i < hostFloat.Length; i++) { hostFloat[i] = i; }
ParentStruct parent = new ParentStruct
{
Child = new ChildStruct
{
FArray = dev.Allocate(hostFloat),
FArrayLength = hostFloat.Length
}
};
dev.Launch(1, 1, KernelFunction, parent);
Console.ReadLine();
}
}
}
程序运行时,在dev.Launch上出现以下错误:
Type 'Test.ParentStruct' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.
如果我从ChildStruct中删除了float数组,它将按预期工作。
过去曾在C / C ++ / Cli和CUDA C中工作,我知道该错误的性质。针对此错误的某些解决方案建议使用
Size
的MarshalAs
参数手动设置结构大小,但是由于结构内类型的多样性,因此无法实现。我查看了生成的.cu文件,它正在生成float数组作为
float *
,这正是我所期望的。有没有办法将结构体中的数组传递给内核?如果没有最好的第二种选择?这个问题在CUDA C中不存在,仅存在是因为我们正在从CLR封送。
最佳答案
我花了很多时间阅读CUDAfy的源代码,以查看是否有解决此问题的方法。
CUDAfy试图使.NET开发人员过分简单,并使它们远离IntPtr
和其他指针概念。但是,由于没有足够的抽象级别,因此很难在很大程度上不考虑该库的工作方式的情况下考虑该问题的答案。
不能在结构中发送浮点数组的是显示停止器。我最终对CUDA运行时进行了PInvoke,而没有使用CUDAfy。