Я возился с внутренними качествами simnet .net 3.0 и видел несколько довольно значительных улучшений производительности. Я хотел попробовать написать переводчик выражений. Таким образом, вы можете определить базовое выражение с плавающей запятой, но тогда переводчик выдаст функцию, которая будет выполнять основные действия, такие как «Преобразование», «Сокращение», «Накопление» и т. Д.
Я написал кое-что, что, по моему мнению, должно работатьниже, но, очевидно, Expression.Variable не допускает типы указателей. Я заметил, что функция проверки имеет логическое значение allowPointer в трассировке стека. Есть ли способ построить дерево выражений с указателями и скомпилировать небезопасную функцию в ядре .net?
Приведенный ниже код просто пытается создать простую функцию добавления. Мне известно, что оно еще не обрабатывает входящее выражение.
Возникла исключительная ситуация: CLR / System.ArgumentException Произошло необработанное исключение типа 'System.ArgumentException' в System.Linq.Expressions.dll. : «Тип не должен быть указателем типа» в System.Dynamic.Utils.TypeUtils.ValidateType (Тип типа, String paramName, Boolean allowByRef, Boolean allowPointer) в System.Linq.Expressions.Expression.Validate (Тип тип, Boolean allowByRef)в System.Linq.Expressions.Expression.Variable (тип Type, имя строки) в MLNet.Math.VMExpression.Transform (Expression`1 expr) в /home/mltrainer/Desktop/mlnet/math/VM-Expression.cs:line67 на MLNet.Program.Main (String [] args) в /home/mltrainer/Desktop/mlnet/Program.cs:line 23
using System;
using VM.Core;
using System.Buffers;
using System.Linq.Expressions;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
namespace VM.Math
{
public static class VMExpression
{
private static Expression BuildLessThanForLoop(Expression index,Expression end,Expression step,Func<Expression,Expression> block)
{
LabelTarget endLoop = Expression.Label();
return Expression.Loop(Expression.Block(new Expression[]
{
Expression.IfThen(Expression.LessThan(index,end),Expression.Break(endLoop)),
block(index),
Expression.AddAssign(index,step)
}),endLoop);
}
private static Expression CalculateVectorLength(Expression arrayLength,ConstantExpression vectorLength)
{
return Expression.And(arrayLength,Expression.OnesComplement(Expression.Subtract(vectorLength,Expression.Constant(1))));
}
private static Expression LoadAlignedVector128Float(Expression vector,Expression ptr)
{
return Expression.Assign(vector,Expression.Call(typeof(Sse2).GetMethod("LoadAlignedVector128",new Type[] { typeof(float*) }),new Expression[] { ptr }));
}
private static Expression StoreAligned128Float(Expression vector,Expression ptr)
{
return Expression.Call(typeof(Sse2).GetMethod("StoreAligned",new Type[] { typeof(float*), typeof(Vector128<float>) }),new Expression[] { ptr, vector });
}
private static Expression Index(Expression array,Expression index)
{
return Expression.ArrayIndex(array,new Expression[] { index });
}
private static Expression Add128Float(Expression vx, Expression vy)
{
return Expression.Call(typeof(Sse2).GetMethod("Add",new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }), new Expression[] { vx, vy });
}
private static Expression CreateAlignedArray(Expression count)
{
return Expression.New(typeof(AlignedFloatArray).GetConstructor(new Type[]{ typeof(int) }), new Expression[] { count });
}
public static unsafe Func<AlignedFloatArray,AlignedFloatArray,AlignedFloatArray> Transform(Expression<Func<float,float,float>> expr)
{
var paramX = Expression.Parameter(typeof(AlignedFloatArray),"x");
var paramY = Expression.Parameter(typeof(AlignedFloatArray),"y");
var parameters = new ParameterExpression[] { paramX, paramY };
var result = Expression.Variable(typeof(AlignedFloatArray),"result");
var memX = Expression.Variable(typeof(Memory<float>),"memX");
var memY = Expression.Variable(typeof(Memory<float>),"memY");
var memZ = Expression.Variable(typeof(Memory<float>),"memZ");
var pinX = Expression.Variable(typeof(MemoryHandle),"pinX");
var pinY = Expression.Variable(typeof(MemoryHandle),"pinY");
var pinZ = Expression.Variable(typeof(MemoryHandle),"pinZ");
var ptrX = Expression.Variable(typeof(float*),"ptrX");
var ptrY = Expression.Variable(typeof(float*),"ptrY");
var ptrZ = Expression.Variable(typeof(float*),"ptrZ");
var i = Expression.Variable(typeof(int),"i");
var n = Expression.Variable(typeof(int),"n");
var step = Expression.Constant(Vector128<float>.Count);
var length = Expression.Variable(typeof(int),"length");
var vx = Expression.Variable(typeof(Vector128<float>));
var vy = Expression.Variable(typeof(Vector128<float>));
var returnLabel = Expression.Label();
var methodBlock = Expression.Block(parameters, new Expression[]
{
Expression.Assign(result,CreateAlignedArray(Expression.PropertyOrField(paramX,"Length"))),
Expression.Assign(memX,Expression.Call(paramX,typeof(AlignedFloatArray).GetMethod("AsMemory"))),
Expression.Assign(memY,Expression.Call(paramY,typeof(AlignedFloatArray).GetMethod("AsMemory"))),
Expression.Assign(memZ,Expression.Call(result,typeof(AlignedFloatArray).GetMethod("AsMemory"))),
Expression.Assign(pinX,Expression.Call(memX,typeof(Memory<float>).GetMethod("Pin"))),
Expression.Assign(pinY,Expression.Call(memY,typeof(Memory<float>).GetMethod("Pin"))),
Expression.Assign(pinZ,Expression.Call(memZ,typeof(Memory<float>).GetMethod("Pin"))),
Expression.Assign(ptrX,Expression.Convert(Expression.PropertyOrField(pinX,"Pointer"),typeof(float*))),
Expression.Assign(ptrY,Expression.Convert(Expression.PropertyOrField(pinY,"Pointer"),typeof(float*))),
Expression.Assign(ptrZ,Expression.Convert(Expression.PropertyOrField(pinZ,"Pointer"),typeof(float*))),
Expression.TryFinally(Expression.Block(new Expression[]
{
Expression.Assign(i,Expression.Constant(0)),
Expression.Assign(length,Expression.PropertyOrField(paramX,"Length")),
Expression.Assign(n,CalculateVectorLength(length,step)),
Expression.IfThen(Expression.GreaterThanOrEqual(n,step),Expression.Block(new Expression[]
{
BuildLessThanForLoop(i,n,step,(index) => {
return Expression.Block(new Expression[]
{
LoadAlignedVector128Float(vx,ptrX),
LoadAlignedVector128Float(vy,ptrY),
StoreAligned128Float(ptrZ,Add128Float(vx,vy))
});
})
})),
BuildLessThanForLoop(i,length,Expression.Constant(1),(index) =>
{
return Expression.Block(new Expression[]
{
Expression.Assign(Index(ptrZ,index),Expression.Add(Index(ptrX,index),Index(ptrY,index)))
});
}),
Expression.Return(returnLabel,result)
}),
Expression.Block(new Expression[]
{
Expression.Call(pinX,typeof(MemoryHandle).GetMethod("Dispose")),
Expression.Call(pinY,typeof(MemoryHandle).GetMethod("Dispose")),
Expression.Call(pinZ,typeof(MemoryHandle).GetMethod("Dispose"))
}))
});
return (Func<AlignedFloatArray,AlignedFloatArray,AlignedFloatArray>)Expression.Lambda(methodBlock,parameters).Compile(false);
}
}
}