在 Alea.GPU 中传递超过 16 个内核参数
Passing more than 16 kernel arguments in Alea.GPU
我正在尝试编写一个相当复杂的内核。事实证明,我需要传递超过 16 个参数,显然 Alea GPU 有 16 个参数的限制。 (http://quantalea.com/static/app/manual/reference/alea_cuda_il/alea-cuda-il-ilgpumodule.html)
我知道从 16 个参数开始听起来不是个好主意...还有哪些其他选择?在普通代码中,我当然会把东西包装到它自己的 class 中,但是在 GPU 代码中我能做什么?
在这种情况下,您可以通过 GPUModule.GPUEntities
属性 检索一个未类型化的内核对象,然后将这些参数放入 Object
类型的列表中,然后您可以启动它。
您还可以为此目的制作一些扩展方法并使它们类型安全,这是一个示例,为了简单起见我只使用了 3 个参数:
public static class GPUModuleExtensions
{
public static void MyGPULaunch<T1, T2, T3>(
this ILGPUModule module,
Action<T1, T2, T3> kernelD, LaunchParam lp,
T1 arg1, T2 arg2, T3 arg3)
{
// get the kernel object by method name
var kernel = module.GPUEntities.GetKernel(kernelD.Method.Name).Kernel;
// create parameter list (which is FSharpList)
var parameterArray = new object[] {arg1, arg2, arg3};
var parameterList = ListModule.OfArray(parameterArray);
// use untyped LaunchRaw to launch the kernel
kernel.LaunchRaw(lp, parameterList);
}
}
public class GPUModule : ILGPUModule
{
public GPUModule() : base(GPUModuleTarget.DefaultWorker)
{
}
[Kernel]
public void Kernel(deviceptr<int> outputs, int arg1, int arg2)
{
var tid = threadIdx.x;
outputs[tid] = arg1 + arg2;
}
[Test]
public void Test()
{
const int n = 32;
var lp = new LaunchParam(1, n);
using (var outputs = GPUWorker.Malloc<int>(n))
{
this.MyGPULaunch(Kernel, lp, outputs.Ptr, 1, 3);
Console.WriteLine("{0}", (outputs.Gather())[4]);
}
}
}
注意,在这个例子中,我使用 Action<T1,T2,T3>
,但是 Action
类型最多有 16 种类型,因此您可能需要定义自己的委托来传递超过 16 种参数类型。
我正在尝试编写一个相当复杂的内核。事实证明,我需要传递超过 16 个参数,显然 Alea GPU 有 16 个参数的限制。 (http://quantalea.com/static/app/manual/reference/alea_cuda_il/alea-cuda-il-ilgpumodule.html)
我知道从 16 个参数开始听起来不是个好主意...还有哪些其他选择?在普通代码中,我当然会把东西包装到它自己的 class 中,但是在 GPU 代码中我能做什么?
在这种情况下,您可以通过 GPUModule.GPUEntities
属性 检索一个未类型化的内核对象,然后将这些参数放入 Object
类型的列表中,然后您可以启动它。
您还可以为此目的制作一些扩展方法并使它们类型安全,这是一个示例,为了简单起见我只使用了 3 个参数:
public static class GPUModuleExtensions
{
public static void MyGPULaunch<T1, T2, T3>(
this ILGPUModule module,
Action<T1, T2, T3> kernelD, LaunchParam lp,
T1 arg1, T2 arg2, T3 arg3)
{
// get the kernel object by method name
var kernel = module.GPUEntities.GetKernel(kernelD.Method.Name).Kernel;
// create parameter list (which is FSharpList)
var parameterArray = new object[] {arg1, arg2, arg3};
var parameterList = ListModule.OfArray(parameterArray);
// use untyped LaunchRaw to launch the kernel
kernel.LaunchRaw(lp, parameterList);
}
}
public class GPUModule : ILGPUModule
{
public GPUModule() : base(GPUModuleTarget.DefaultWorker)
{
}
[Kernel]
public void Kernel(deviceptr<int> outputs, int arg1, int arg2)
{
var tid = threadIdx.x;
outputs[tid] = arg1 + arg2;
}
[Test]
public void Test()
{
const int n = 32;
var lp = new LaunchParam(1, n);
using (var outputs = GPUWorker.Malloc<int>(n))
{
this.MyGPULaunch(Kernel, lp, outputs.Ptr, 1, 3);
Console.WriteLine("{0}", (outputs.Gather())[4]);
}
}
}
注意,在这个例子中,我使用 Action<T1,T2,T3>
,但是 Action
类型最多有 16 种类型,因此您可能需要定义自己的委托来传递超过 16 种参数类型。