Я приму предположение, что d
хранит результат умножения. Если это не так, вы сможете легко изменить код.
Проблема заключается в том, что вы смешиваете IntPtr
(маршалирование вручную) и управляемые типы (маршалирование автоматически).
Вы можете увидеть созданную оболочку, запустив runner.saveAssembly();
после вызова Wrap
:
HybRunner runner = HybRunner.Cuda();
dynamic wrapped = runner.Wrap(new Program());
runner.saveAssembly();
Затем запустите IlSpy , чтобы проверить сгенерированную dll и увидеть все создаваемые перегрузки:

Как видите, одна перегрузка с массивами, а другая с native int.
первый предназначен для автоматического управления памятью, а второй - для ручного управления памятью.
Однако вы не можете смешивать оба.
В качестве решения вы должны вручную управлять памятью для вашего параметра d
:
static void Main(string[] args)
{
int numelements = 12;
Complex[] a = new Complex[numelements];
Complex[] b = new Complex[numelements];
float[] d = new float[numelements];
int memsize = numelements * Marshal.SizeOf(new Complex());
GCHandle aH = GCHandle.Alloc(a, GCHandleType.Pinned);
GCHandle bH = GCHandle.Alloc(b, GCHandleType.Pinned);
GCHandle dH = GCHandle.Alloc(d, GCHandleType.Pinned);
IntPtr da, db;
cuda.ERROR_CHECK(cuda.Malloc(out da, memsize));
cuda.ERROR_CHECK(cuda.Malloc(out db, memsize));
IntPtr dd;
cuda.ERROR_CHECK(cuda.Malloc(out dd, numelements * sizeof(float)));
cuda.ERROR_CHECK(cuda.Memcpy(da, aH.AddrOfPinnedObject(), memsize, cudaMemcpyKind.cudaMemcpyHostToDevice));
cuda.ERROR_CHECK(cuda.Memcpy(db, bH.AddrOfPinnedObject(), memsize, cudaMemcpyKind.cudaMemcpyHostToDevice));
HybRunner runner = HybRunner.Cuda();
dynamic wrapped = runner.Wrap(new Program());
runner.saveAssembly();
// the following line gives a runtimeBinderException as detailed below
wrapped.Multiply(da, db, dd, numelements);
cuda.Memcpy(dH.AddrOfPinnedObject(), dd, numelements * sizeof(float), cudaMemcpyKind.cudaMemcpyDeviceToHost);
cuda.DeviceSynchronize();
}
Однако в вашем случае я бы использовал тип ResidentArray , предоставляемый Hybridizer. Они предназначены, чтобы помочь вам с такими проблемами.
[EntryPoint]
static void Multiply(ResidentArrayGeneric<Complex> a, ResidentArrayGeneric<Complex> b, FloatResidentArray d, int len)
{
}
static void Main(string[] args)
{
int numelements = 12;
var a = new ResidentArrayGeneric<Complex>(numelements);
var b = new ResidentArrayGeneric<Complex>(numelements);
var d = new FloatResidentArray(numelements);
// populate a and b
a.RefreshDevice();
b.RefreshDevice();
HybRunner runner = HybRunner.Cuda();
dynamic wrapped = runner.Wrap(new Program());
runner.saveAssembly();
// the following line gives a runtimeBinderException as detailed below
wrapped.Multiply(a, b, d, numelements);
d.RefreshHost();
cuda.DeviceSynchronize();
}
Более подробный образец вы можете найти с ResidentArrays здесь