在CUDAfy的结构中传递一个数组

本文关键字:一个 数组 CUDAfy 结构 | 更新日期: 2023-09-27 18:11:54

使用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中删除浮点数组,它会像预期的那样工作。

过去在C/c++/Cli和CUDA C中工作过,我知道错误的性质。对于这个错误的一些解决方案建议使用MarshalAsSize参数手动设置结构体大小,但由于结构体中类型的多样性,这是不可能的。

我查看了生成的.cu文件,它正在生成浮点数组作为float *,这是我所期望的。

是否有一种方法可以将结构体中的数组传递给内核?如果没有,最好的第二选择是什么?这个问题在CUDA C中不存在,它只存在,因为我们从CLR封送。

在CUDAfy的结构中传递一个数组

我花了很多时间阅读CUDAfy的源代码,看看是否有解决这个问题的方法。

CUDAfy试图使事情对。net开发人员来说过于简单,并使他们远离IntPtr和其他指针概念。然而,抽象的层次使得如果不对这个库的工作方式进行重大重构,就很难想到这个问题的答案。

不能在struct中发送浮点数组是一个show stopper。我最终做了PInvoke到CUDA运行时,而不是使用CUDAfy。

这是。net的限制,而不是CUDAfy。数据必须是位元化的,而非固定大小的数组则不能。这是有效的,并且基于codeplex上的CUDAfy单元测试:

[Cudafy]
[StructLayout(LayoutKind.Sequential, Size=64, CharSet = CharSet.Unicode)]
public unsafe struct PrimitiveStruct
{
    public fixed sbyte Message[32];
    public fixed char MessageChars[16];
}

也没有理由显式存储数组长度,因为您可以在设备代码中使用length属性。