2013-05-02 9 views
2

Использование VS 2012, .NET 4.5, 64bit и CUDAfy 1.12 и я следующее доказательство концепцииПередача массива в пределах структуры в CUDAfy

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 в прошлом, я знаю о характере ошибки. Некоторые решения этой ошибки предполагают установку размера структуры вручную с использованием параметра SizeMarshalAs, но это невозможно из-за разнообразия типов внутри структуры.

Я посмотрел на сгенерированный файл .cu и он генерирует массив с плавающей запятой как float *, который я и ожидал.

Есть ли способ передать массив внутри структуры в ядро? А если нет лучшей альтернативы? Эта проблема не существует в CUDA C, и она существует только потому, что мы маршируем из CLR.

+0

Означает ли это, что список невозможен с помощью CUDAFY? –

+1

Во-первых, это должен быть массив, который вы отправляете, а не список. Тем не менее, я не думаю, что это проблема, если только ваша структура имеет массив. – Adam

+0

ОК прохладно. Структура содержит только дату и время, десятичную дробь и т. Д. У меня такое ощущение, что десятичное значение может быть проблемой, хотя я не заметил, что он упоминается в «CUDA на примере». + 1 на ur комментарий и вопрос btw;) –

ответ

1

Я потратил хорошее время на чтение исходного кода CUDA, чтобы узнать, есть ли решение этой проблемы.

CUDAfy пытается сделать вещи слишком простыми для разработчиков .NET и защищать их от IntPtr и других понятий указателя. Тем не менее, уровень абстракции затрудняет представление ответа на эту проблему без значительного рефакторинга в отношении того, как работает эта библиотека.

Невозможность отправить массив с плавающей точкой внутри структуры - это пробная пробка. Я закончил работу с PInvoke в CUDA Runtime и не использовал CUDAfy.

+0

Или вы могли послать psuedo ptr через другой массив, как C# и C++/ASM dev. Я использовал его довольно часто, интеграция IMO C# теперь требует таких решений; развязанное управление памятью. –

1

Это ограничение .NET, а не CUDAfy. Данные должны быть blittable, а массив нефиксированного размера - нет. Это справедливо и на основе модульных тестов CUDAfy на CodePlex:

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

Там также нет оснований хранить длину массива в явном виде, так как вы можете использовать свойство Length в пределах кода устройства.

+0

Я видел этот код, однако он имеет дело с массивами с фиксированным размером, и проблема связана с массивами с переменным размером. – Adam

+0

Просто установите максимальный размер и удалите остальную часть –