使用 C# 反射“手动”调用内联方法

问题描述 投票:0回答:1

我使用 ILGPU 在 GPU 上运行大量数学代码,我将其组织在按接口隔离的模块化类中,以实现不同的模块化算法。

现在 ILGPU 只允许在 GPU 内核上运行静态方法。因此,我需要从这些嵌套类中取出 IL,并手动内联,输出一个称为 Kernel 的静态方法。

示例中

public interface IFunction
{
    public float DoSum(float[] input);
}


public class NormalSum
{
    public float(float[] input)
    {
        float sum=0.0f;
        for(int i=0;i<input.Lenght;i++)
            sum+=input[i];
    }
}

public interface IAlgorithm
{
    public void DoAlgorithm(float[] input, float[] output);
}

public class MyAlgorithm
{
    IFunction fun;
    public MyAlgorithm(IFunction fun)
    {
        this.fun = fun;
    }
    public void DoAlgorithm(float[] input, float[] output)
    {
          for(int j=0;j<output.Length;j++)
          {
               output[j] = 2.0f* fun.DoSum(input);
          }
    }
}

没有存储变量,类和接口只是算法的包装器,所以我需要一个代码并期望它将方法内联到类似的东西,而不必费心解决对实例成员的最终引用,我希望“有趣”只是为了提取方法实现,那么“乐趣”就可以丢弃了。

var staticMethod = Inline(new MyAlgorithm(new NormalSum));

 // generated IL
public static void GeneratedCode(float[] input, float[] output)
{
          for(int j=0;j<output.Length;j++)
          {
              float sum=0.0f;
              for(int i=0;i<input.Length;i++)
                  sum+=input[i];
              float result = sum;
              output[j] = 2.0f* result;
          }
}

到目前为止,我只是复制了一个静态方法,但无法进入“实现内部”。

    MethodInfo existingMethod = typeof(MyStaticClass).GetMethod("MethodToCopy", BindingFlags.Static | BindingFlags.Public);

    AssemblyName assemblyName = new AssemblyName("DynamicAssembly");
    AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);

    ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicModule");

    TypeBuilder typeBuilder = moduleBuilder.DefineType("DynamicClass", TypeAttributes.Public);

    MethodBuilder methodBuilder = typeBuilder.DefineMethod("DynamicMethod", MethodAttributes.Public | MethodAttributes.Static, existingMethod.ReturnType, new Type[] { });

    ILGenerator ilGenerator = methodBuilder.GetILGenerator();
    
    // Copy IL code
    foreach (var instruction in existingMethod.GetMethodBody().GetILAsByteArray())
    {
        ilGenerator.Emit(instruction);
    }
    
    Type type = typeBuilder.CreateType();

    type.GetMethod("DynamicMethod").Invoke(null, null);
c# reflection.emit
1个回答
0
投票

如果您可以使用 C# 11+,那么您可以尝试使用 静态抽象接口成员并完全转储反射:

使用静态方法声明接口:

public interface IAlgorithm1
{
    public static abstract void DoAlgorithm(float[] input, float[] ouput) ;
}

public interface IFunction1
{
    public static abstract float DoSum(float[] input);
}

然后实施它们:

public class MyAlgorithm1<T> : IAlgorithm1 where T : IFunction1
{
    public static void DoAlgorithm(float[] input, float[] output)
    {
        for(int j=0;j<output.Length;j++)
        {
            output[j] = 2.0f* T.DoSum(input); // call to the static method of the generic type
        }
    }
}

public class NormalSum1 : IFunction1
{
    public static float DoSum(float[] input)
    {
        float sum = 0.0f;
        for (int i = 0; i < input.Length; i++)
            sum += input[i];
        return sum;
    }
}

然后你可以通过

MyAlgorithm1<NormalSum1>.DoAlgorithm
访问静态方法:

var output = new float[1];
MyAlgorithm1<NormalSum1>.DoAlgorithm(new []{1f}, output);
© www.soinside.com 2019 - 2024. All rights reserved.